Download presentation
Presentation is loading. Please wait.
1
Multiple Inheritance & Factories Prasun Dewan Comp 114
2
Topics Covered Multiple inheritance –Extending more than one type Factories –Class creating objects More on 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
Course Interface package courseTree; public interface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String theDept); }
5
Logged Course Interface package courseTree; public interface LoggedCourse extends Course { public int getNumberOfQueries(); }
6
Course abstract class package courseTree; public abstract class ACourse implements Course { String title, dept; public ACourse (String theTitle, String theDept) { init (theTitle, theDept); } public ACourse () {} public void 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))return this; elsereturn null; }
7
ALoggedCourse abstract class package courseTree; public abstract class ALoggedCourse extends ACourse implements LoggedCourse { int numberOfQueries = 0; public ALoggedCourse (String theTitle, String theDept) { super (theTitle, theDept); } public ALoggedCourse () { } public int getNumberOfQueries() { return numberOfQueries; } public Course matchTitle(String theTitle) { Course course = super.matchTitle(theTitle); if (course != null) numberOfQueries++; return course; }
8
Regular Course Interface package courseTree; public interface RegularCourse extends Course { public void init (String theTitle, String theDept, int theCourseNum); }
9
Logged Regular Course Interface package courseTree; public interface LoggedRegularCourse extends ??? { … }
10
Logged Regular Course Interface package courseTree; public interface LoggedRegularCourse extends LoggedCourse { public void init (String theTitle, String theDept, int theCourseNum); } package courseTree; public interface LoggedRegularCourse extends RegularCourse { public int getNumberOfQueries(); }
11
Duplication package courseTree; public interface LoggedRegularCourse extends LoggedCourse { public void init (String theTitle, String theDept, int theCourseNum); } package courseTree; public interface RegularCourse extends Course { public void init (String theTitle, String theDept, int theCourseNum); }
12
package courseTree; public interface LoggedRegularCourse extends RegularCourse { public int getNumberOfQueries(); } Duplication package courseTree; public interface LoggedCourse extends Course { public int getNumberOfQueries(); }
13
Single Interface Inheritance package courseTree; public interface LoggedRegularCourse extends LoggedCourse { public void init (String theTitle, String theDept, int theCourseNum); } public interface RegularCourse extends Course { public void init (String theTitle, String theDept, int theCourseNum); } public interface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String theDept); } public interface LoggedCourse extends Course { public int getNumberOfQueries(); } Course LoggedCourse RegularCourse LoggedRegularCourse
14
Alternative Single Inheritance package courseTree; public interface LoggedRegularCourse extends RegularCourse { public int getNumberOfQueries(); } public interface RegularCourse extends Course { public void init (String theTitle, String theDept, int theCourseNum); } public interface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String theDept); } public interface LoggedCourse extends Course { public int getNumberOfQueries(); } Course LoggedCourse RegularCourse LoggedRegularCourse
15
Multiple Interface Inheritance package courseTree; public interface LoggedRegularCourse extends LoggedCourse, RegularCourse{} package courseTree; public interface RegularCourse extends Course { public void init (String theTitle, String theDept, int theCourseNum); } package courseTree; public interface LoggedCourse extends Course { public int getNumberOfQueries(); } empty interface
16
Multiple Interface Inheritance public interface LoggedRegularCourse extends RegularCourse {} public interface RegularCourse extends Course { public void init (String theTitle, String theDept, int theCourseNum); } public interface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String theDept); } public interface LoggedCourse extends Course { public int getNumberOfQueries(); } Course LoggedCourse RegularCourse LoggedRegularCourse
17
Old Regular Course Class public class ARegularCourse extends ACourse implements RegularCourse { int courseNum ; public ARegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ARegularCourse () {} public void init (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } public int getNumber() { return courseNum; }
18
New Regular Course Class public class ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { int courseNum ; public ALoggedRegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ALoggedRegularCourse () {} public void init (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } public int getNumber() { return courseNum; } Code duplication and not making sure ALoggedRegularCourse is a ARegularCourse!
19
Single Class Inheritance public interface LoggedRegularCourse extends ALoggedCourse { public int getNumber() {…}; public void init (String theTitle, String theDept, int theCourseNum) {…}; } public class ARegularCourse extends ACourse { public int getNumber() {…}; public void init (String theTitle, String theDept, int theCourseNum); } public class ACourse implements Course { public String getTitle() {…} public String getDepartment() {…}; public void init (String theTitle, String theDept) {…}; public Course matchTitle (String theTitle) {…}; } public class ALoggedCourse extends ACourse { public int getNumberOfQueries() {…}; public Course matchTitle (String theTitle) {…}; } ACourse ALoggedCourse ARegularCourse ALoggedRegularCourse
20
Multiple Class Inheritance? public class LoggedRegularCourse extends ALoggedCourse, ARegularCourse { } public class ARegularCourse extends ACourse { public int getNumber() {…}; public void init (String theTitle, String theDept, int theCourseNum); } public class ACourse implements Course { public String getTitle() {…} public String getDepartment() {…}; public void init (String theTitle, String theDept) {…}; public Course matchTitle (String theTitle) {…}; } public class ALoggedCourse extends ACourse { public int getNumberOfQueries() {…}; public Course matchTitle (String theTitle) {…}; } ACourse ALoggedCourse ARegularCourse ALoggedRegularCourse
21
Multiple Class Inheritance? public class ALoggedRegularCourse extends ALoggedCourse, ARegularCourse implements LoggedRegularCourse {} public abstract class ALoggedCourse extends ACourse implements LoggedCourse { … public Course matchTitle(String theTitle) { Course course = super.matchTitle(theTitle); if (course != null) numberOfQueries++; return course; } public class ARegularCourse extends ACourse implements RegularCourse {…} public abstract class ACourse implements Course { … public Course matchTitle(String theTitle) { if ( title.equals(theTitle))return this; elsereturn null; } Two different implementations with same header inherited
22
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
23
Multiple Interface Inheritance public interface LoggedRegularCourse extends RegularCourse, LoggedCourse{ } public interface RegularCourse extends Course { public void init (String theTitle, String theDept, int theCourseNum); } public interface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String theDept); } public interface LoggedCourse extends Course { public int getNumberOfQueries(); } Course LoggedCourse RegularCourse LoggedRegularCourse Same method headers added twice, no problem
24
Multiple Interface Inheritance public interface LoggedRegularCourse extends RegularCourse, LoggedCourse { } public interface RegularCourse extends Course { public void init (String theTitle, String theDept, int theCourseNum); } public interface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String theDept); } public interface LoggedCourse extends Course { public int getNumberOfQueries(); public void init (String theTitle, String theDept); } Course LoggedCourse RegularCourse LoggedRegularCourse Equal method headers inherited twice Interface: set of method headers Addition: removes duplicates
25
Multiple Interface Inheritance public interface LoggedRegularCourse extends RegularCourse, LoggedCourse { } public interface RegularCourse extends Course { public void init (String theTitle, String theDept, int theCourseNum); } public interface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String theDept); } public interface LoggedCourse extends Course { public int getNumberOfQueries(); public LoggedCourse init (String theTitle, String theDept); } Course LoggedCourse RegularCourse LoggedRegularCourse Method headers differ only in return type Overloading ambiguity, multiple inheritance not allowed
26
Single inheritance => reduced polymorphsism? public class ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { … } void print (ARegularCourse course) {…} ALoggedRegularCourse introProg = new ALoggedRegularRegularCourse(); …. print(introProg); LoggedRegularCourse introProg = new ALoggedRegularRegularCourse(); …. print(introProg); void print (RegularCourse course) {…} Code Duplication & ALoggedRegularCourse is not ARegularCourse! Classes as types Interfaces as types
27
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
28
Implementing Single Interface public class ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { int courseNum ; public ALoggedRegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ALoggedRegularCourse () {} public void init (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } public int getNumber() { return courseNum; } package courseTree; public interface LoggedRegularCourse extends LoggedCourse, RegularCourse{}
29
Implementing Multiple Interfaces public class ALoggedRegularCourse extends ALoggedCourse implements LoggedCourse, RegularCourse { int courseNum ; public ALoggedRegularCourse (String theTitle, String theDept, int theCourseNum) { init (theTitle, theDept, theCourseNum); } public ALoggedRegularCourse () {} public void init (String theTitle, String theDept, int theCourseNum) { super.init (theTitle, theDept); courseNum = theCourseNum; } public int getNumber() { return courseNum; }
30
Multiple interfaces => Casting LoggedCourse introProg = new ALoggedRegularRegularCourse(); …. print((RegularCourse)introProg); …. appendToLog(introProg); public class ALoggedRegularCourse extends ALoggedCourse implements LoggedCourse, RegularCourse { …. } RegularCourse introProg = new ALoggedRegularRegularCourse(); …. print(introProg); …. appendToLog((LoggedCourse)introProg); void print (RegularCourse course) {…} void appendToLog (LoggedCourse course) {…}
31
Single interface LoggedregularCourse introProg = new ALoggedRegularRegularCourse(); …. print (introProg); …. appendToLog(introProg); void print (RegularCourse course) {…} void appendToLog (LoggedCourse course) {…} public class ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { …. }
32
Single interface and overloading LoggedRegularCourse introProg = new ALoggedRegularRegularCourse(); …. print ((RegularCourse)introProg); …. appendToLog((LoggedCourse)introProg); void print (RegularCourse course) {…} void print (LoggedCourse course) {…} public class ALoggedRegularCourse extends ALoggedCourse implements LoggedRegularCourse { …. }
33
Implementing multiple interfaces vs. Single Interface 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.
34
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
35
package courseTree; public class 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;} public void 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; } ACourseList Using interfaces as types Oblivious to actual classes
36
Main Class package main; … public class ACourseDisplayer{ static CourseList courses = new ACourseList(); public static void main(String[] args){ fillCourses(); //Do I/O … }... static void 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")); }
37
Code Duplication package main; … public class ACourseDisplayer{ static CourseList courses = new ACourseList(); public static void main(String[] args){ fillCourses(); //Do I/O … }... static void fillCourses() { CourseList prog = new ACourseList(); prog.addElement (new ALoggedRegularCourse ("Intro. Prog.", "COMP", 14)); prog.addElement (new ALoggedRegularCourse ("Found. of Prog.", "COMP", 114)); courses.addElement(prog); courses.addElement (new ALoggedFreshmanSeminar("Comp. Animation", "COMP")); courses.addElement (new ALoggedFreshmanSeminar("Lego Robots", "COMP")); }
38
Code Inconsistency package main; … public class ACourseDisplayer{ static CourseList courses = new ACourseList(); public static void main(String[] args){ fillCourses(); //Do I/O … }... static void fillCourses() { CourseList prog = new ACourseList(); prog.addElement (new ALoggedRegularCourse ("Intro. Prog.", "COMP", 14)); prog.addElement (new ALoggedRegularCourse ("Found. of Prog.", "COMP", 114)); courses.addElement(prog); courses.addElement (new AFreshmanSeminar("Comp. Animation", "COMP")); courses.addElement (new AFreshmanSeminar("Lego Robots", "COMP")); } Adding logged regular course and unlogged freshman seminar
39
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
40
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
41
Common Factory Interface package factories; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; public interface CourseFactory { public RegularCourse getRegularCourse(); public FreshmanSeminar getFreshmanSeminar(); }
42
ACourseFactory package factories; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; import courseTree.ARegularCourse; import courseTree.AFreshmanSeminar; public class ACourseFactory implements CourseFactory { public RegularCourse getRegularCourse() { return new ARegularCourse(); } public FreshmanSeminar getFreshmanSeminar() { return new AFreshmanSeminar(); } Parameterless constructors Factory user will call init()
43
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(); }
44
Original Main Class package main; … public class ACourseDisplayer{ static CourseList courses = new ACourseList(); public static void main(String[] args){ fillCourses(); //Do I/O … }... static void fillCourses() { CourseList prog = new ACourseList(); prog.addElement (new ARegularCourse ("Intro. Prog.", "COMP", 14)); prog.addElement (new ARegularCourse ("Found. of Prog.", "COMP", 114)); … }
45
New Main Class package main; … public class AFactoryBasedCourseDisplayer{ static CourseList courses = new ACourseList(); public static void main(String[] args){ fillCourses(); //Do I/O … }... static void 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); … }
46
New Main Class for logged courses package main; … public class AFactoryBasedCourseDisplayer{ static CourseList courses = new ACourseList(); public static void main(String[] args){ fillCourses(); //Do I/O … }... static void 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); … }
47
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
48
Factory Selector Interface package factories; public interface CourseFactorySelector { public CourseFactory getCourseFactory(); }
49
Factory Selector Class package factories; public class ACourseFactorySelector implements CourseFactorySelector { public CourseFactory getCourseFactory() { //return new ACourseFactory(); return new ALoggedCourseFactory(); }
50
Main Class with Factory Selector package main; … public class AFactoryBasedCourseDisplayer{ static CourseList courses = new ACourseList(); public static void main(String[] args){ fillCourses(); //Do I/O … }... static void 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); … }
51
Different Selection package factories; public class ACourseFactorySelector { public CourseFactory getCourseFactory() { return new ACourseFactory(); //return new ALoggedCourseFactory(); } No change to main and other users needed!
52
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
53
Logged Factory Interface package factories; import courseTree.LoggedRegularCourse; import courseTree.LoggedFreshmanSeminar; public interface LoggedCourseFactory extends CourseFactory { public LoggedRegularCourse getLoggedRegularCourse(); public LoggedFreshmanSeminar getLoggedFreshmanSeminar(); }
54
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(); }
55
Factory Pattern Factory Interface Factory Class 1Factory Class 2 implements
56
Alternative Factory Pattern Abstract Factory Class Factory Class 1Factory Class 2 extends
57
Classes vs. Factory We also called a class a factory –It defines blueprints for its instances Factory in factory pattern is really a broker that orders objects for you. Factory selector decides between different kinds of brokers Analogy –I ask my IT department to get me a 4lb laptop –They decide to go to the IBM CCI “factory” –CCI factory specifies matching computer and accessories –These are then ordered from the real IBM factory Car Analogy –Dealership selling you cars and accessories that go with them.
58
Factory Uses Should we always instantiate via factories? Factories add overhead –Factory interfaces, classes –Factory selector interfaces, classes Define when you need them –Need to switch transparently between alternates BMISpreadsheet and AnotherBMISpreadsheet –Need to ensure matching objects are created ALoggedFreshmanSeminar and ALoggedRegularCourse
59
Factory uses Multiple toolkits provide same kind of widgets with different look and feel/implementations. Package java.awt –TextField, Button, Panel Package javax.swing –JTextField, JButton, JPanel Could define a common factory interface –getTextField(), getButton(), getPanel() SwingFactory and AWTFactory classes implement interface FactorySelector switches between two classes to change implementation
60
Factory Uses Multiple implementation of AWT toolkit for each window system. –Microsoft Windows. –X Windows
61
Factories and Interfaces Factories allow us to switch between alternative objects providing same methods –FreshmanSeminar and LoggedFreshmanSeminar –JTextField and TextField Alternative objects must be united by a common interface Otherwise common factory interface cannot be defined. Desired toolkit factory interface –getTextField(), getButton(), getPanel() JTextField and TextField do not define a common text field interface Though they provide common methods –getText(), setText() Moral: define interfaces!
62
ObjectEditor Factory Example package bus.uigen.view; import java.awt.Container; public interface PanelFactory { public Container createPanel (); }
63
ObjectEditor Factory Selector Example package bus.uigen.view; import java.awt.Container; public class PanelSelector { //static PanelFactory factory = new SwingPanelFactory(); static PanelFactory factory = new AWTPanelFactory(); public static void setPanelFactory (PanelFactory newVal) { factory = newVal; } public static Container createPanel() { return factory.createPanel(); }
64
Main class without Façade package main; … public class AFactoryBasedCourseDisplayer{ static CourseList courses = new ACourseList(); public static void main(String[] args){ fillCourses(); while (true) { System.out.println("Please enter course title:"); String inputLine = readString(); if (inputLine.equals(".")) break; else { Course matchedCourse = courses.matchTitle(inputLine); if (matchedCourse == null) System.out.println("Sorry, this course is not offered."); else { printHeader(); print (matchedCourse); }
65
Main Class without Façade... static void 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); … } … } Composes courses and course lists
66
Main class with façade package main; … public class AFactoryBasedCourseDisplayer{ static TitleToCourseMapper titleToCourseMapper = new ATitleToCourseMapper(); public static void main(String[] args){ while (true) { System.out.println("Please enter course title:"); String inputLine = readString(); if (inputLine.equals(".")) break; else { titleToCourseMapper.setTitle(inputLine); Course matchedCourse = titleToCourseMapper.getCourse(); if (matchedCourse == null) System.out.println("Sorry, this course is not offered."); else { printHeader(); print (matchedCourse); } }}
67
Façade interface package facades; import courseTree.Course; public interface TitleToCourseMapper { public String getTitle(); public void setTitle (String newVal); public Course getCourse(); }
68
Façade Class package facades; import courseTree.Course; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; import courseTree.CourseList; import courseTree.ACourseList; import factories.CourseFactory; import factories.ACourseFactorySelector; public class AFactoryBasedTitleToCourseMapper implements TitleToCourseMapper{ CourseList courses = new ACourseList(); public AFactoryBasedTitleToCourseMapper() { fillCourses(); } String title = ""; public String getTitle() {return title;} public void setTitle (String newVal) { title = newVal; course = courses.matchTitle(title); } Course course; public Course getCourse() { return courses.matchTitle(title); }
69
Façade Class void fillCourses() { CourseFactory courseFactory = (new ACourseFactorySelector()).getCourseFactory(); CourseList prog = new ACourseList(); RegularCourse introProg = courseFactory.getRegularCourse (); introProg.init("Intro. Prog.", "COMP", 14); prog.addElement(introProg); RegularCourse foundProg = courseFactory.getRegularCourse(); foundProg.init ("Found. of Prog.", "COMP", 114); prog.addElement(foundProg); courses.addElement(prog); FreshmanSeminar compAnimation = courseFactory.getFreshmanSeminar(); compAnimation.init("Comp. Animation", "COMP"); courses.addElement(compAnimation); FreshmanSeminar legoRobots = courseFactory.getFreshmanSeminar(); legoRobots.init("Lego Robots", "COMP"); courses.addElement(legoRobots); }
70
Facade pattern RegularCourse FreshmanSeminar CourseList Facade
71
Facade pattern Component1 Component2 ComponentN Facade
72
Factory-based Façade Class package facades; … public class AFactoryBasedTitleToCourseMapper implements TitleToCourseMapper{ … void fillCourses() { CourseFactory courseFactory = (new ACourseFactorySelector()).getCourseFactory(); RegularCourse introProg = courseFactory.getRegularCourse (); FreshmanSeminar legoRobots = courseFactory.getFreshmanSeminar(); … }
73
Application-specific factory Factory switching occurs for all classes What if we want it for some subset of classes
74
Factory Method Creates objects Could be abstract Subclasses override it to create objects of different classes Change in subclass does not change other subclasses
75
Abstract facade class package facades; import courseTree.Course; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; import courseTree.CourseList; import courseTree.ACourseList; public abstract class AnAbstractTitleToCourseMapper implements TitleToCourseMapper{ … abstract RegularCourse getRegularCourse(); abstract FreshmanSeminar getFreshmanSeminar(); void fillCourses() { RegularCourse introProg = getRegularCourse (); FreshmanSeminar legoRobots = getFreshmanSeminar(); … }
76
Concrete course user package facades; import courseTree.Course; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; import courseTree.ARegularCourse; import courseTree.AFreshmanSeminar; public class ATitleToCourseMapper extends AnAbstractTitleToCourseMapper{ RegularCourse getRegularCourse() { return new ARegularCourse(); } FreshmanSeminar getFreshmanSeminar() { return new AFreshmanSeminar(); }
77
Logged course user package facades; import courseTree.Course; import courseTree.RegularCourse; import courseTree.FreshmanSeminar; import courseTree.ALoggedRegularCourse; import courseTree.ALoggedFreshmanSeminar; public class ATitleToLoggedCourseMapper extends AnAbstractTitleToCourseMapper{ RegularCourse getRegularCourse() { return new ALoggedRegularCourse(); } FreshmanSeminar getFreshmanSeminar() { return new ALoggedFreshmanSeminar(); }
78
Factory Methods in Course Example AnAbstractTitleToCourseMapper { defines createRegularCourse and createFreshmanSeminar and uses them} ATitleToCourseMapper { implements these methods to create one configuration } ATitleToLoggedCourseMapper { implements these methods to create another configuration } extends
79
Factory Method Pattern Abstract Class { defines and uses class creation methods} Concrete Class { implements these methods to create some configuration } extends
80
Factory Methods in Course Example AnAbstractTitleToCourseMapper { defines createRegularCourse and createFreshmanSeminar and uses them} ATitleToCourseMapper { implements these methods to create one configuration } ATitleToLoggedCourseMapper { implements these methods to create another configuration } extends ATitleToLoggedCourseMapper IS-A ATitleToCourseMapper
81
Factory Methods in Course Example AnAbstractTitleToCourseMapper { defines createRegularCourse and createFreshmanSeminar and uses them} ATitleToCourseMapper { implements these methods to create one configuration } ATitleToLoggedCourseMapper { implements these methods to create another configuration } extends ATitleToLoggedCourseMapper IS-A ATitleToCourseMapper extends Redundant class with a single user
82
Alternative Factory Method Usage ATitleToCourseMapper { implements createRegularCourse and createFreshmanSeminar and uses them} ATitleToLoggedCourseMapper { overrides these methods to create an extension} extends
83
Factory methods Do not have to be abstract –Though pattern book says they are A concrete class may define and use class creation methods Some subclass of it overrides them The subclass must extend the functionality ATitleToLoggedCourseMapper IS-A ATitleToCourseMapper as LoggedCourse IS-A Course
84
Factory Classes vs. Factory Methods Create a configuration applying to all users of a factory selector Creates local configurations. If class C implements abstract factory method defined in super class S, then configuration applies to C, and all subclasses of C and superclasses between C and S that do not override/implement it
85
Factory Classes vs. Methods public class AFactoryBasedTitleToCourseMapper implements TitleToCourseMapper{ … void fillCourses() { CourseFactory courseFactory = (new ACourseFactorySelector()).getCourseFactory(); RegularCourse introProg = courseFactory.getRegularCourse (); FreshmanSeminar legoRobots = courseFactory.getFreshmanSeminar(); … } public class ATitleToCourseMapper implements TitleToCourseMapper{ … RegularCourse getRegularCourse() {return new ARegularCourse();} FreshmanSeminar getFreshmanSeminar() {return new AFreshmanSeminar();} void fillCourses() { RegularCourse introProg = getRegularCourse (); FreshmanSeminar legoRobots = getFreshmanSeminar(); … } Lots of methods possible, which may return incompatible objects Single factory method simply acts as factory selector.
86
Electronics Example Need for factories –VCR RGB goes with TV RGB –VCR SVideo goes with TV SVideo RGB Factory –TV RF and VCR RF SVideo Factory –Svideo TVs & VCR Need for façade –Want to simulate a single combo unit, using VCR as channel tuner for TV Methods –Constructor asks vcr to connect to TV and sets TV channel to vcr’s CHANNEL –power() powers both components –getChannel(), setChannel(), record() and play() Asks vcr to do the operation
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.