Download presentation
Presentation is loading. Please wait.
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; public interface Course extends TreeNode { public String getTitle(); public String getDepartment(); public int getNumber(); public void init (String theTitle, String theDept); }
5
New Course Interface package courseTree; public interface LoggedCourse extends Course { public int getNumberOfQueries(); }
6
Old 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
New 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
Old Regular Course Interface package courseTree; public interface RegularCourse extends Course { public void init (String theTitle, String theDept, int theCourseNum); }
9
New Regular Course Interface package courseTree; public interface LoggedRegularCourse extends LoggedCourse { public void init (String theTitle, String theDept, int theCourseNum); }
10
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); } LoggedRegularCourse IS-A RegularCourse
11
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
12
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
13
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
14
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 empty interface
15
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; }
16
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 ALoggedRegularCourse is not ARegularCourse!
17
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
18
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
19
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
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 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
22
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
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(); public LoggedCourse init (String theTitle, String theDept); } Course LoggedCourse RegularCourse LoggedRegularCourse Method headers differ only in return type Overloading ambiguity, multiple inheritance not allowed
24
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
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 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{}
27
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; }
28
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) {…}
29
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 { …. }
30
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 { …. }
31
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.
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 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; } Using interfaces as types Oblivious to actual classes
34
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")); }
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
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()
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; … 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)); … }
41
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); … }
42
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); … }
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; … 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); … }
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(); }
51
Factory Pattern Factory Interface Factory Class 1Factory Class 2 implements
52
Alternative Factory Pattern Abstract Factory Class Factory Class 1Factory Class 2 extends
53
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
54
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
55
Programmer Selection Multiple toolkits provided to programmer. 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 Programmer-defined FactorySelector switches between two classes to change implementation
56
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
57
Factory Uses Multiple implementation of AWT toolkit for each window system. –Microsoft Windows. –X Windows
58
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!
59
Reducing Main Class through Facades Things to exclude –“computation” Things to include –Input/Output –Object instantiation Unless done byfactory –Object composition Main class still monolithic Facades –Do object composition
60
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); }
61
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
62
Main class with Façade (edit) 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); }
63
Main class with Façade (edited) package main; … public class AFactoryBasedCourseDisplayer{ static Facade courses = new AFacade(); 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); }
64
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); }
65
Façade interface package facades; import courseTree.Course; public interface TitleToCourseMapper { public String getTitle(); public void setTitle (String newVal); public Course getCourse(); }
66
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); }
67
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); }
68
Façade class Done with getters and setters for generality purposes Helps with creating GUI interfaces in future Provide getters and setters in your facades
69
Facade pattern RegularCourse FreshmanSeminar CourseList Facade
70
Facade pattern Component1 Component2 ComponentN Facade
71
Façade pattern Compose objects into a single unit exposing methods relevant to that unit E.g. scanner, parser, program tree, code generator objects combined into one compiler object –Takes program text as input –Produces code as output –Passes text to scanner, which passes tokens to parser, which creates program tree, which is processed by code generator, which produces output Compiler user not aware of internal components Componentizing code is a pain as components must be combined Facades removes this problem, creating a simple façade to complex internals
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
Alternative Factory Method Usage ATitleToCourseMapper { implements createRegularCourse and createFreshmanSeminar and uses them} ATilteToLoggedCourseMapper { overrides these methods to create an extension} extends
85
Façade super class public class ATitleToCourseMapper implements TitleToCourseMapper{ … RegularCourse getRegularCourse() { return new ARegularCourse(); } FreshmanSeminar getFreshmanSeminar() { return new AFreshmanSeminar(); } void fillCourses() { RegularCourse introProg = getRegularCourse (); FreshmanSeminar legoRobots = getFreshmanSeminar();… }
86
Logged course subclass public class ATitleToLoggedCourseMapper extends ATitleToCourseMapper{ RegularCourse getRegularCourse() { return new ALoggedRegularCourse(); } FreshmanSeminar getFreshmanSeminar() { return new ALoggedFreshmanSeminar(); } Overridden methods
87
Generalized Factory Method Pattern Abstract/Concrete Class { defines and maybe implements object creation methods} Concrete Class { overrides these implementaions to create an extension} extends Concrete Class { overrides these implementaions to create an extension}
88
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
89
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
90
Factory Classes and 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 getCoursefactory() {return new ARegularCourseFactory();} void fillCourses() { CourseFactory courseFactory = getCourseFactory(); RegularCourse introProg = courseFactory.getRegularCourse (); FreshmanSeminar legoRobots = courseFactory.getFreshmanSeminar(); … } Single factory method simply acts as factory selector.
91
Combining factories and factory methods Abstract/Concrete Class { defines and maybe implements method to choose factory} Concrete Class { implements this methods to create some configuration } Concrete Class { implements this method to create some configuration} extends
92
Electronics Example VCR interface –setChannel(), getChannel(), power(),record(), play(), connectToTV() –CHANNEL constant TV interface –power(), setChannel(), getChannel() VCR with RF connector –setRGB() TV with RF connector interface –getRGB() TV with S-Video connector interface –getSVideo() VCR RGB –Implements connectToTV in terms of getRGB() VCR SVideo –Implements connectToTV() in terms of getSVideo()
93
Electronics Example Need for factories –VCR RF goes with TV RF –VCR SVideo goes with RV Svideo RGB Factory –TV RF and VCR RF SVideo Factory –Svideo TVs & VCR Need for façade –Want to simulate a single combo unit Methods –Constructor asks vcr to connect to TV and sets TV channel to vcr’s CHANNEL –power() powers both components –getChannel(), setChannel(), rcord() and play() Asks vcr to do the operation
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.