1 / 93

Multiple Inheritance, Factories, & Facades

Multiple Inheritance, Factories, & Facades. Prasun Dewan Comp 114. Topics Covered. Multiple inheritance Extending more than one type Factories Class creating objects Facades Compose objects Can be used independently We use them together here Factory methods

erasmos
Télécharger la présentation

Multiple Inheritance, Factories, & Facades

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Multiple Inheritance, Factories, & Facades Prasun Dewan Comp 114

  2. Topics Covered • Multiple inheritance • Extending more than one type • Factories • Class creating objects • Facades • Compose objects • Can be used independently • We use them together here • Factory methods • Abstract method instead of class

  3. Problem • A modification to the course problem. • Want to gather statistics on how many times a user requested a course • How many times matchTitle() successfully matched a course

  4. Old Course Interface package courseTree; publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); publicvoidinit (String theTitle, String theDept); }

  5. New Course Interface package courseTree; publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); }

  6. Old abstract class package courseTree; publicabstractclass ACourse implements Course { String title, dept; public ACourse (String theTitle, String theDept) { init (theTitle, theDept); } public ACourse () {} publicvoid init (String theTitle, String theDept) { title = theTitle; dept = theDept; } public String getTitle() {return title;} public String getDepartment() {return dept; } public Course matchTitle(String theTitle) { if ( title.equals(theTitle)) returnthis; elsereturnnull; } }

  7. New abstract class package courseTree; publicabstract class ALoggedCourse extends ACourse implements LoggedCourse { int numberOfQueries = 0; public ALoggedCourse (String theTitle, String theDept) { super (theTitle, theDept); } public ALoggedCourse () { } publicint getNumberOfQueries() { return numberOfQueries; } publicCourse matchTitle(String theTitle) { Course course = super.matchTitle(theTitle); if (course != null) numberOfQueries++; return course; } }

  8. Old Regular Course Interface package courseTree; publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); }

  9. New Regular Course Interface package courseTree; publicinterface LoggedRegularCourse extends LoggedCourse { publicvoidinit (String theTitle, String theDept, int theCourseNum); }

  10. Duplication package courseTree; publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } package courseTree; publicinterface LoggedRegularCourse extends LoggedCourse { publicvoidinit (String theTitle, String theDept, int theCourseNum); } LoggedRegularCourse IS-A RegularCourse

  11. Single Interface Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); } LoggedRegularCourse package courseTree; publicinterface LoggedRegularCourse extends LoggedCourse { publicvoidinit (String theTitle, String theDept, int theCourseNum); }

  12. Alternative Single Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); } LoggedRegularCourse package courseTree; publicinterface LoggedRegularCourse extends RegularCourse { publicint getNumberOfQueries(); }

  13. empty interface Multiple Interface Inheritance package courseTree; publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); } package courseTree; publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } package courseTree; publicinterface LoggedRegularCourse extends LoggedCourse, RegularCourse{}

  14. empty interface Multiple Interface Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); } LoggedRegularCourse publicinterface LoggedRegularCourse extends RegularCourse {}

  15. Old Regular Course Class publicclass ARegularCourse extends ACourse implements RegularCourse { int courseNum ; public ARegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ARegularCourse () {} publicvoidinit (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } publicint getNumber() { return courseNum; } }

  16. New Regular Course Class publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { int courseNum ; public ALoggedRegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ALoggedRegularCourse () {} publicvoidinit (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } publicint getNumber() { return courseNum; } } Code duplication and ALoggedRegularCourse is not ARegularCourse!

  17. Single Class Inheritance ACourse publicclass ACourse implements Course { public String getTitle() {…} public String getDepartment() {…}; publicvoidinit (String theTitle, String theDept) {…}; publicCourse matchTitle (String theTitle) {…}; } ALoggedCourse ARegularCourse publicclass ARegularCourse extends ACourse { publicint getNumber() {…}; publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicclass ALoggedCourse extends ACourse { publicint getNumberOfQueries() {…}; publicCourse matchTitle (String theTitle) {…}; } ALoggedRegularCourse publicinterface LoggedRegularCourse extends ALoggedCourse { publicint getNumber() {…}; publicvoidinit (String theTitle, String theDept, int theCourseNum) {…}; }

  18. Multiple Class Inheritance? ACourse publicclass ACourse implements Course { public String getTitle() {…} public String getDepartment() {…}; publicvoidinit (String theTitle, String theDept) {…}; publicCourse matchTitle (String theTitle) {…}; } ALoggedCourse ARegularCourse publicclass ARegularCourse extends ACourse { publicint getNumber() {…}; publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicclass ALoggedCourse extends ACourse { publicint getNumberOfQueries() {…}; publicCourse matchTitle (String theTitle) {…}; } ALoggedRegularCourse publicclass LoggedRegularCourse extends ALoggedCourse, ARegularCourse { }

  19. Multiple Class Inheritance? publicclass ALoggedRegularCourse extends ALoggedCourse, ARegularCourse implements LoggedRegularCourse {} publicabstract class ALoggedCourse extends ACourse implements LoggedCourse { … publicCourse matchTitle(String theTitle) { Course course = super.matchTitle(theTitle); if (course != null) numberOfQueries++; return course; } } publicclass ARegularCourse extends ACourse implements RegularCourse {…} publicabstractclass ACourse implements Course { … public Course matchTitle(String theTitle) { if ( title.equals(theTitle)) returnthis; elsereturnnull; } } Two different implementations with same header inherited

  20. Multiple inheritance rules • Allow interfaces to inherit multiple times • Only headers are inherited • Do not allow classes to inherit multiple times (Java) • Could inherit multiple bodies with same header • Can be confusing to programmers • Other solutions • Allow multiple inheritance if ambiguity does not arise • If ambiguity arises indicate which implementation is used (C++) • ALoggedCourse.matchTitle() vs ARegularCourse.matchTitle() • Choose one or none of the bodies if problem arises • Based on order in extends clause? • extends ALoggedCourse, ARegularCourse

  21. Multiple Interface Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); } LoggedRegularCourse publicinterface LoggedRegularCourse extends RegularCourse, LoggedCourse{ } Same method headers added twice, no problem

  22. Multiple Interface Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); publicvoidinit (String theTitle, String theDept); } LoggedRegularCourse publicinterface LoggedRegularCourse extends RegularCourse, LoggedCourse { } Interface: set of method headers Addition: removes duplicates Equal method headers inherited twice

  23. Multiple Interface Inheritance Course publicinterface Course extends TreeNode { public String getTitle(); public String getDepartment(); publicint getNumber(); publicvoidinit (String theTitle, String theDept); } LoggedCourse RegularCourse publicinterface RegularCourse extends Course { publicvoidinit (String theTitle, String theDept, int theCourseNum); } publicinterface LoggedCourse extends Course { publicint getNumberOfQueries(); publicLoggedCourseinit (String theTitle, String theDept); } LoggedRegularCourse publicinterface LoggedRegularCourse extends RegularCourse, LoggedCourse { } Overloading ambiguity, multiple inheritance not allowed Method headers differ only in return type

  24. Classes as types Interfaces as types Single inheritance => reduced polymorphsism? publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { … } Code Duplication & ALoggedRegularCourse is not ARegularCourse! void print (ARegularCourse course) {…} ALoggedRegularCourse introProg = new ALoggedRegularRegularCourse(); …. print(introProg); void print (RegularCourse course) {…} LoggedRegularCourse introProg = new ALoggedRegularRegularCourse(); …. print(introProg);

  25. Single inheritance => reduced polymorphism? • Yes, if classes used to type variables • Interfaces offer solution to lack of multiple (class) inheritance in Java • Most programmers do not realise other uses. • In text books, interfaces introduced and used only in problems requiring multiple inheritance

  26. Implementing Single Interface publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { int courseNum ; public ALoggedRegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ALoggedRegularCourse () {} publicvoidinit (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } publicint getNumber() { return courseNum; } } package courseTree; publicinterface LoggedRegularCourse extends LoggedCourse, RegularCourse{}

  27. Implementing Multiple Interfaces publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedCourse, RegularCourse { int courseNum ; public ALoggedRegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ALoggedRegularCourse () {} publicvoidinit (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } publicint getNumber() { return courseNum; } }

  28. Multiple interfaces => Casting publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedCourse, RegularCourse { …. } void print (RegularCourse course) {…} void appendToLog (LoggedCourse course) {…} LoggedCourse introProg = new ALoggedRegularRegularCourse(); …. print((RegularCourse)introProg); …. appendToLog(introProg); RegularCourse introProg = new ALoggedRegularRegularCourse(); …. print(introProg); …. appendToLog((LoggedCourse)introProg);

  29. Single interface publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { …. } void print (RegularCourse course) {…} void appendToLog (LoggedCourse course) {…} LoggedregularCourse introProg = new ALoggedRegularRegularCourse(); …. print (introProg); …. appendToLog(introProg);

  30. Single interface and overloading publicclass ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { …. } void print (RegularCourse course) {…} void print (LoggedCourse course) {…} LoggedRegularCourse introProg = new ALoggedRegularRegularCourse(); …. print ((RegularCourse)introProg); …. appendToLog((LoggedCourse)introProg);

  31. Different interfaces evolved independently TreeNode, LeafOnly, CompositeOnly LoggedCourse, RegularCourse Uniting them creates empty interface Does not require casting to use different interfaces of same object Modulo overloading problems These arise whenever an object can be typed in multiple ways. A compile time issue – these casts are needed only at compile time and do not lead to runtime errors. Implementing multiple interfaces vs. Single Interface

  32. Switching between different course configurations • Want both logged and non-logged versions based on users • Logged course has overhead • Some university may decide logging gives misleading /useless information • How to write programs that can easily switch between the two kinds of courses

  33. ACourseList Using interfaces as types Oblivious to actual classes package courseTree; publicclass ACourseList implements CourseList, TreeNode { final int MAX_SIZE = 50; TreeNode[] contents = new TreeNode[MAX_SIZE]; int size = 0; public int size() {return size;} public TreeNode elementAt (int index) {return contents[index];} boolean isFull() { return size == MAX_SIZE;} publicvoid addElement(TreeNode element) { if (isFull()) System.out.println("Adding item to a full collection"); else { contents[size] = element; size++; } } public Course matchTitle (String theTitle) { for (int courseIndex = 0; courseIndex < size; courseIndex++) { Course course = contents[courseIndex].matchTitle(theTitle); if ( course != null) return course; } return null; } }

  34. Main Class package main; … publicclass ACourseDisplayer { static CourseList courses = new ACourseList(); public static void main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseList prog = new ACourseList(); prog.addElement (new ARegularCourse ("Intro. Prog.", "COMP", 14)); prog.addElement (new ARegularCourse ("Found. of Prog.", "COMP", 114)); courses.addElement(prog); courses.addElement (new AFreshmanSeminar("Comp. Animation", "COMP")); courses.addElement (new AFreshmanSeminar("Lego Robots", "COMP")); } }

  35. Switching between classes • How to make main and other classes instantiating course objects oblivious to which course set is used? • How to make sure incompatible courses are not added to course list • AFreshmanSeminar • ALoggedRegularCourse

  36. Factory class • Creates a set of related objects • Different factory classes for different configurations • ACourseFactory • ALoggedCourseFactory • Factory classes providing alternative configurations implement the same interface • CourseFactory

  37. Common Factory Interface package factories; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; public interface CourseFactory { public RegularCourse getRegularCourse(); public FreshmanSeminar getFreshmanSeminar(); }

  38. Parameterless constructors ACourseFactory package factories; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; import courseTree.ARegularCourse; import courseTree.AFreshmanSeminar; publicclass ACourseFactory implements CourseFactory { public RegularCourse getRegularCourse() { returnnew ARegularCourse(); } public FreshmanSeminar getFreshmanSeminar() { returnnew AFreshmanSeminar(); } } Factory user will call init()

  39. ALoggedCourseFactory package factories; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; import courseTree.ALoggedRegularCourse; import courseTree.ALoggedFreshmanSeminar; public class ALoggedCourseFactory implements CourseFactory{ public RegularCourse getRegularCourse() { return new ALoggedRegularCourse(); } public FreshmanSeminar getFreshmanSeminar() { return new ALoggedFreshmanSeminar(); } }

  40. Original Main Class package main; … publicclass ACourseDisplayer { static CourseList courses = new ACourseList(); public static void main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseList prog = new ACourseList(); prog.addElement (new ARegularCourse ("Intro. Prog.", "COMP", 14)); prog.addElement (new ARegularCourse ("Found. of Prog.", "COMP", 114)); … } }

  41. New Main Class package main; … publicclass AFactoryBasedCourseDisplayer { static CourseList courses = new ACourseList(); public static void main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseFactory courseFactory = new ACourseFactory(); CourseList prog = new ACourseList(); RegularCourse introProg = courseFactory.getRegularCourse (); introProg.init("Intro. Prog.", "COMP", 14); RegularCourse foundProg = courseFactory.getRegularCourse (); foundProg.init(“Found. Prog.", "COMP", 114); … } }

  42. New Main Class for logged courses package main; … publicclass AFactoryBasedCourseDisplayer { static CourseList courses = new ACourseList(); public static void main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseFactory courseFactory = new ALoggedCourseFactory(); CourseList prog = new ACourseList(); RegularCourse introProg = courseFactory.getRegularCourse (); introProg.init("Intro. Prog.", "COMP", 14); RegularCourse foundProg = courseFactory.getRegularCourse (); foundProg.init(“Found. Prog.", "COMP", 114); … } }

  43. Factory Transparent Main? • Same main and other course users for different configurations? • Need FactorySelector Class • Only class changed to select different configurations • Main and other classes call factory selector class

  44. Factory Selector Interface package factories; public interface CourseFactorySelector { public CourseFactory getCourseFactory(); }

  45. Factory Selector Class package factories; public class ACourseFactorySelector implements CourseFactorySelector { public CourseFactory getCourseFactory() { //return new ACourseFactory(); return new ALoggedCourseFactory(); } }

  46. Main Class with Factory Selector package main; … publicclass AFactoryBasedCourseDisplayer { static CourseList courses = new ACourseList(); public static void main(String[] args) { fillCourses(); //Do I/O … } ... staticvoid fillCourses() { CourseFactory courseFactory = (new CourseFactorySelector()).getCourseFactory(); CourseList prog = new ACourseList(); RegularCourse introProg = courseFactory.getRegularCourse (); introProg.init("Intro. Prog.", "COMP", 14); RegularCourse foundProg = courseFactory.getRegularCourse (); foundProg.init(“Found. Prog.", "COMP", 114); … } }

  47. Different Selection package factories; public class ACourseFactorySelector { public CourseFactory getCourseFactory() { return new ACourseFactory(); //return new ALoggedCourseFactory(); } } No change to main and other users needed!

  48. ALoggedCourseFactory package factories; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; import courseTree.ALoggedRegularCourse; import courseTree.ALoggedFreshmanSeminar; public class ALoggedCourseFactory implements CourseFactory{ public RegularCourse getRegularCourse() { return new ALoggedRegularCourse(); } public FreshmanSeminar getFreshmanSeminar() { return new ALoggedFreshmanSeminar(); } } Classes that need logged courses must cast

  49. Logged Factory Interface package factories; import courseTree.LoggedRegularCourse; import courseTree.LoggedFreshmanSeminar; public interface LoggedCourseFactory extends CourseFactory { public LoggedRegularCourse getLoggedRegularCourse(); public LoggedFreshmanSeminar getLoggedFreshmanSeminar(); }

  50. ALoggedCourseFactory package factories; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; import courseTree.LoggedRegularCourse; import courseTree.LoggedFreshmanSeminar; import courseTree.ALoggedRegularCourse; import courseTree.ALoggedFreshmanSeminar; public class ALoggedCourseFactory implements LoggedCourseFactory { public RegularCourse getRegularCourse() { return new ALoggedRegularCourse(); } public FreshmanSeminar getFreshmanSeminar() { return new ALoggedFreshmanSeminar(); } public LoggedRegularCourse getLoggedRegularCourse() { return new ALoggedRegularCourse(); } public LoggedFreshmanSeminar getLoggedFreshmanSeminar() { return new ALoggedFreshmanSeminar(); } }

More Related