CISC 323 Intro to Software Engineering
Week 6: Design Patterns
CISC 323 Intro to Software Engineering Week 6: Design Patterns CISC - - PowerPoint PPT Presentation
CISC 323 Intro to Software Engineering Week 6: Design Patterns CISC 323 Intro to Software Engineering Lecture 6-1 Introduction to Design Patterns
Week 6: Design Patterns
Lecture 6-1 Introduction to Design Patterns
– Requirements analysis determines desired quality attributes of system – When designing system, attempt to
✣ ✤ ✥✧✦ ★ ✩ ✪ ✫✭✬ ✮ ✯ ✦ ✮✰ ✱ ✫ ✯ ✪ ✰ ✲ ✳ ✴✧✦ ✯ ✦ ✵ ✶ ✮ ✷ ✪ ✩ ✬ ✮ ✩ ✩ ✯ ✪ ✸ ✶ ✩ ✦ ✰ ✹ ✮ ✬ ★ ✱ ✩ ✸ ✦ ✹✦ ✩ ✺ ✻ ✦ ✥✭✶ ✼ ✦ ✯ ✪ ✰ ✲ ✩ ✴ ✯ ✱ ✶ ✽ ✴✥✧✦ ✰ ✪ ✽ ★ ✼ ✴ ✱ ✪ ✼ ✦ ✰– Some attributes amenable to mathematical expression (performance, availability), others less so (modifiability)
a very complex algorithm, reducing modifiability
replicate data sources, reducing security
required targets for quality attributes
– At what point is security sufficient? – At what point is system sufficiently fast? – … Etc.
large-scale design of software systems
useful to apply micro-architectures to help design these components
– Sometimes called design patterns
structure code in order to solve a particular class of problem
can be expressed in terms of classes, associations
least one quality attribute, perhaps at the expense of others
– A data source is shared by a number of clients – Multiple clients depend on the value of the data source – Modifiability attribute important
Forms-based interface for calculating expense reports.
Items depend on value of exchange rate. If exchange rate changes, these values should change too.
Exchange Rate $Cdn cost of hotel $US cost of hotel $Cdn cost of meals $US cost of meals depends depends depends depends
all components that depend on it
Exchange Rate $Cdn cost of hotel $US cost of hotel $Cdn cost of meals $US cost of meals depends depends depends depends
contains data on which a set of client components depend (e.g., current exchange rate)
subscribe to changes in the data
publishes any changes in the data
Exchange Rate $Cdn cost of hotel (1) Client component subscribes to changes in exchange rate (2) Source component publishes changes in exchange rate
Exchange Rate $Cdn cost of hotel (1) subscribe (2) publish
Subscriber Publisher
determined on a case-by-case basis
Exchange Rate $Cdn cost of hotel (1) subscribe = connectAsTarget (2) publish = raiseEvent
Subscriber Publisher
// Target implements this method. It is called by the // event connector whenever a new event is fired. public interface EventTarget { public void performEvent (EventObject e); }
import java.util.EventObject; public class ExchangeRateChangedEvent extends EventObject { private float newExchangeRate; public int getNewExchangeRate () { return newExchangeRate; } public ExchangeRateChangedEvent ( Object source, float newRate) { super (source); newExchangeRate = newRate; } }
public class EventConnector { //There are zero or more targets represented as a vector private Vector targets = new Vector(); // When a new event is raised, the "performEvent" method of // each target is invoked public void raiseEvent (EventObject e) { for (int i=0; i<targets.size(); i++) { EventTarget t = (EventTarget) targets.elementAt (i); t.performEvent (e); } } //Each target must register itself as a target of this //connector. public void connectAsTarget (EventTarget targetComponent) { targets.add(targetComponent); } }
extendibility of systems
– At the expense of interaction complexity – which may make analysis more difficult
frameworks
environments (e.g. IBM Eclipse) where a variety of tools can be easily integrated
connectAsTarget connectAsTarget raiseEvent (change in state initiated by outside source or Publisher) performEvent performEvent
– General rule -- design pattern must be seen in at least three real systems before it is considered to be a design pattern
Lecture 6-2 Adapter, Façade, Abstract Factory, and Flyweight Design Patterns
– Sometimes a class implements functionality similar to what an application requires, but not the correct interface for that application – E.g. We wish to implement a BookList class implementing a list of text book used in a course
int getNumBooks() Book getBook (int n) void addBook (Book newBook)
– These operations are very similar to the
– Implement BookList from scratch
✁ ✂☎✄ ✆✝ ✞✟ ✠☎✡ ✝ ☛ ✝ ☞ ☞ ✌ ☞ ✆ ☞ ✌ ✞ ✝– Use Vector
✁ ✍ ✌ ✞ ✎ ✏ ✑ ✝ ✏ ✒ ✝ ✟ ✠ ☞ ✝ ✒ ✠ ✞ ✏ ✝ ☞ ✓✕✔ ✖ ✝ ✓ ✌ ☞ ✗ ✌ ✌ ✘ ✙ ✠ ✟ ✏– Adapt Vector to BookList interface
– Class adapter
✁ ✗ ✔ ✟ ✝ ✒ ✌ ✞ ✠ ✞ ✤ ✝ ☞ ✠ ✏ ✔ ✞ ✖ ✝– Object adapter
✁ ✗ ✔ ✟ ✝ ✒ ✌ ✞ ✔ ✑ ✑ ☞ ✝ ✑ ✔ ✏ ✠ ✌ ✞BookList.java
import java.util.Vector; public class BookListClassAdapter extends Vector implements BookList { public int getNumBooks() { return size(); } public Book getBook(int n) { return (Book) elementAt(n); } public void addBook(Book newBook) { for (int i=0; i<getNumBooks(); i++) { Book b=getBook(i); if (b.isSameBook (newBook)) { b.setQuantity (b.getQuantity() + newBook.getQuantity()); return; } } add (newBook); } }
BookListClassAdapter.java
public class SampleClient { public static void main (String [] args) { Book b = new Book (…); BookList bl = new BookListClassAdapter (); bl.addBook (b); System.out.println (“Book list has ” + bl.getNumBooks() + “ books”); } }
SampleClient.java
BookListClassAdapter directly
import java.util.Vector; public class BookListObjectAdapter implements BookList { private Vector books = new Vector(); public int getNumBooks() { return books.size(); } public Book getBook(int n) { return (Book) books.elementAt(n); } public void addBook(Book newBook) { for (int i=0; i<getNumBooks(); i++) { Book b=getBook(i); if (b.isSameBook (newBook)) { b.setQuantity (b.getQuantity() + newBook.getQuantity()); return; } } books.add (newBook); } }
BookListObjectAdapter.java
public class SampleClient { public static void main (String [] args) { Book b = new Book (…); BookList bl = new BookListObjectAdapter (); bl.addBook (b); System.out.println (“Book list has ” + bl.getNumBooks() + “ books”); } }
SampleClient.java
– Adapter class provides clean interface to clients of adapted object
– Takes advantage of adapted class for reuse
– Takes advantage of tested code
– Sometimes part of a system is itself implemented as a subsystem, consisting of a set of objects – Rather than revealing subsystem structure to rest
to subsystem as a whole
– A student information system provides access to functions on
✁ ✂ ✄✆☎ ✝✟✞ ✝✡✠ ☛✆☞✌ ✝ ✞ ☎ ✍ ☞ ☞✌ ✍ ✎ ✏✆☞ ☛ ✑ ✌ ☎ ✒ ✑✔✓ ☞✌ ✕ ✎ ✠ ✍ ✞ ☞ ✖ ✂ ✄✆☎ ✝ ✕ ✎ ✠ ✍ ✞ ☞ ✞ ☎ ✒ ✑✔✓ ☞✌ ✞ ✝ ✠ ☛✆☞✌ ✝ ✑ ✞ ☞✌ ✍ ✎ ✏✆☞ ☛ ✑ ✌ ✖ ✂ ✄✆☞ ✍ ☞ ☎ ✒ ✑✔✓ ☞✌ ✕ ✎ ✠ ✍ ✞ ☞ ✑ ✞ ✗ ☞ ✑ ✌ ✒ ✄✆☞ ✏ ☛– Implemented via three classes
✖ ✘ ✎ ✠ ✍ ✞ ☞ ✞ ✙ ✑ ✌ ✚ ✎ ✍ ✛☎ ✝ ✑ ✎ ✌ ✎ ✌ ✕ ✎ ✠ ✍ ✞ ☞ ☞✌ ✍ ✎ ✏ ✏ ✛☞✌ ✝ ✞ ✖ ✜ ✝✡✠ ☛✆☞✌ ✝ ✞ ✙ ✑ ✌ ✚ ✎ ✍ ✛☎ ✝ ✑ ✎ ✌ ✎ ✌ ✞ ✝ ✠ ☛✆☞✌ ✝ ✞ ✢ ✕ ✎ ✠ ✍ ✞ ☞ ✞ ✖ ✣ ☎ ✕ ✑ ✏ ✑ ✝ ✑ ☞ ✞ ✙ ✑ ✌ ✚ ✎ ✍ ✛☎ ✝ ✑ ✎ ✌ ✎ ✌ ✏ ✎ ✕ ☎ ✝ ✑ ✎ ✌ ✎ ✚ ✕ ✎ ✠ ✍ ✞ ☞ ✞class Courses { … public StudentList getEnrollment (CourseId c) { … } … } class Students { … public CourseList getCourses (StudentId s) { … } } class Facilities { … public LectureHallId getLectureHall (CourseId c) { … } }
Courses.java Students.java Facilities.java
Student Information Subsystem
Student Information Subsystem
public class StudentInformation System { Courses cs; Students ss; Facilities fs; … public StudentList getEnrollment (CourseId c) { return cs.getEnrollment (c); } public CourseList getCourses (StudentId s) { return ss.getCourses (s); } public LectureHallId getLectureHall (CourseId c) { return fs.getLectureHall (c); } }
StudentInformationSystem.java
– By removing external links to subsystem components, impact of changes to subsystem components limited to subsystem itself
– Slight performance cost of extra call indirection through façade
✁ ✂☎✄ ✆ ✝ ✞✟ ✠ ✡ ✆ ✡ ✄ ☛ ✆ ☞ ✟ ✌ ✞ ✍ ✞ ✆ ✌ ✟ ✞ ✞ ✄ ✎ ✏ ✠ ✞ ✑ ✠ ✒ ✠ ✞✓ ✔ ✆ ✕ ✓ ✆ ✖☎✗ ✓ ✆ ✟ ✠ ✍ ✄ ☛ ✡ ✓ ✘ ✘✙ ✓ ✗ ✆ ☞ ✟ ☞☎✚ ✌ ✠ ✛ ✠ ✍ ✜ ✆ ✏ ✌ ✞ ✌ ✌ ✢ ✆ ✡ ✠ ✎ ✠ ✘ ✘ ✞structural problems in programs
– Adapter -- structures programs to aid reuse – Façade -- localizes references to a subsystem, aiding modifiability
– Creational patterns -- help in object creation – Behavioural patterns -- help manage runtime behaviour of program
✥ ✦ ✧ ★✩ ✪ ✫ ✬✭ ✫ ✧ ★ ✫✮ ✯ ✪ ★✱✰ ✪ ✫ ✲✳ ✰ ✰ ✴ ✵ ✶ ✦ ✩ ✰– Imagine you have a book ordering system in which you need to maintain a list of books
✥ ✦★✧ ✧ ✩ ✪ ✫ ✬ ✭ ✮ ✬ ✫ ✫ ✭✧ ✯ ✰ ✬ ✪ ✯ ✪ ✯✱ ✬ ✰ ✪ ✰ ✮✳✲ ✴ ✬ ✵ ✰ ✶ ✧ ✷ ✴ ✸ ✹ ✦ ✺ ✴ ✻ ✥ ✼✦★✧ ✧ ✩ ✽ ✪ ✫ ✰ ✪ ✫ ✬ ✮ ✪ ✫ ✰ ✧ ✾✿ ✧ ✧ ✩ ✫ ✴ ✪ ✯ ✭ ✮ ✵ ❀ ✪ ✯✱ ✬ ❁ ✵ ✬ ✯ ✰ ✪ ✰❃❂ ❄❆❅ ❇ ✾ ✧ ✷ ✲ ✬ ✭ ✶ ✿ ✧ ✧ ✩– Initially, you wish to maintain a simple Vector – However, after the system has been delivered, you decide you want a data structure that also permits books to be represented in sorted order
import java.util.Vector; public class BookListClassAdapter extends Vector implements BookList { public int getNumBooks() { return size(); } public Book getBook(int n) { return (Book) elementAt(n); } public void addBook(Book newBook) { for (int i=0; i<getNumBooks(); i++) { Book b=getBook(i); if (b.isSameBook (newBook)) { b.setQuantity (b.getQuantity() + newBook.getQuantity()); return; } } add (newBook); } }
Here is an initial implementation of a BookList
– Option 1: Modify BookList so that every time a book is entered, the Vector is sorted
✥ ✦✤✧ ★✩ ✪ ✫✭✬ ✮✯ ✰ ✱ ✲ ✳✴ ✮ ✵ ✯ ✶✷ ✳ ✸ ✬ ✹ ✬ ✬ ✺ ✫ ✱ ✴ ✸ ✮ ✰ ✯ ✴ ✴ ✱ ✸ ✴ ✳ ✰✻ ✥ ✼ ★✽ ✩ ✪ ✾ ✬ ✿❀ ✮ ✳ ✸ ✬ ✹ ✬ ✬ ✺ ✫ ✱ ✴ ✸ ❁ ✯ ❂ ✶ ✬ ✸ ❃ ✳ ✯ ❄ ✯ ✱ ✰ ✯ ❃ ✰ ✳ ✪ ✹ ✬ ✬ ✺ ✫ ✱ ✴ ✸ ❁ ✯ ❂ ❃ ✳ ✿ ✴ ✳ ❅ ✱ ✶ ✬ ✸ ✵ ✳ ❀ ❆ ❀ ✬ ✷ ❀ ✯ ❁✴❈❇ ✬ ✸ ✵ ✳ ❀ ✴ ✿ ❃ ✴ ❂ ✴ ✸ ✳ ❁ ✴ ✬ ✻ ✴ ✯ ❁ ✳ ❆ ❀ ✬ ✷ ❀ ✯ ❁ ❇ ✴ ✬ ✸ ✵ ✯ ✸ ✮ ✵ ✯ ✶✷ ✳ ✱ ✶ ✮ ✰ ✯ ✴ ✴ ✻ ✿ ✶ ✮ ✸ ✱ ✬ ✶ ✯ ✰ ✱ ✸ ❂ ✮ ✬ ✿ ✰ ❅ ✵ ✯ ❄ ✳ ❉ ✱ ❅ ✳ ❀ ✱ ❁ ❆ ✯ ✮ ✸ ✸ ✵ ✯ ✶ ❆ ✰ ✯ ✶ ✶ ✳ ❅ ✪ ❊ ✯ ✶✷ ✳ ❀ ✬ ✻ ❄ ✳ ❀ ✴ ✱ ✬ ✶ ❆ ❀ ✬ ✰ ✱ ✻ ✳ ❀ ✯ ✸ ✱ ✬ ✶ ❇ ❉ ✵ ✳ ❀ ✳ ❅ ✱ ✻ ✻ ✳ ❀ ✳ ✶ ✸ ❄ ✳ ❀ ✴ ✱ ✬ ✶ ✴ ✬ ✻ ✹ ✬ ✬ ✺ ✫ ✱ ✴ ✸ ❉ ✱ ✸ ✵ ❅ ✱ ✻ ✻ ✳ ❀ ✳ ✶ ✸ ✻ ✿ ✶ ✮ ✸ ✱ ✬ ✶ ✯ ✰ ✱ ✸ ❂ ✯ ❆ ❆ ✳ ✯ ❀ ✱ ✶ ❅ ✱ ✻ ✻ ✳ ❀ ✳ ✶ ✸ ❆ ❀ ✬ ✷ ❀ ✯ ❁ ✴ ❋ ❋ ✱ ✶ ✮ ❀ ✳ ✯ ✴ ✳ ✴ ❆ ❀ ✬ ❃ ✰ ✳ ❁ ✴ ❉ ✱ ✸ ✵ ❁ ✯ ✱ ✶ ✸ ✳ ✶ ✯ ✶ ✮ ✳– Create a BookList interface with the required functionality of maintaining a list of books – Create an abstract factory class that creates an instance of the correct kind of BookList
VectorBookList to SortingVectorBookList implementation, need to ensure that wherever we create a book list, we replace “new VectorBookList()” with “new SortingVectorBookList()”
– What if source to classes creating book lists is not available?
BookListFactory.java VectorBookListFactory.java Client.java
The client is provided with an object of type
VectorBookList or a SortingVectorBookList, depending on which factory was used.
BookListFactory Client uses VectorBookListFactory SortingVectorBookListFactory <<interface>> BookList uses VectorBookList SortingVectorBookList creates creates
The client is provided with an object of type
VectorBookList or a SortingVectorBookList, depending on which factory was used.
BookListFactory Client uses VectorBookListFactory SortingVectorBookListFactory <<interface>> BookList uses VectorBookList SortingVectorBookList creates creates
The client sees an object of type BookListFactory, so does not need to know whether it is using a VectorBookListFactory
BookListFactory Client uses VectorBookListFactory SortingVectorBookListFactory <<interface>> BookList uses VectorBookList SortingVectorBookList creates creates
– Increased through use of indirection in creation process – Creator does not need to know exactly what type
applications where large numbers of objects required
mechanism
represent a set of rows, and within each row a set of columns
set of characters
an object
tens of thousands of characters would require tens of thousands of objects
a p p a r e n t
a p p a r e n t a b c d e f g h i k l m n
q r s t u v w x y z
can be shared by many instances of object
✤ ✥✧✦ ★ ✦✩ ✪ ✫✭✬ ✮ ✬ ✪ ✯✱✰ ✮ ✲✬ ✳ ✰ ✩ ✴✶✵ ✯ ✲✷ ✯✱✸ ✷ ✹ ✺ ✯ ✺ ✷ ✲ ✩ ✻ ✷ ✲ ✯to a particular instance
✤ ✥✧✦ ★ ✦✩ ✸ ✷ ✹ ✺ ✯ ✺ ✷ ✲ ✩ ✻ ✷ ✲ ✯a p p a r e n t a b c d e f g h i k l m n
q r s t u v w x y z
create (intrinsicData)
“a” to create instance of character “a”
– Systems with tens/hundreds of thousands or more
memory use – Flyweight objects reduce this expense
– Encapsulation of system functionality no longer as clear – Separation of intrinsic/extrinsic state into different
Lecture 6-3 Composite, Iterator, and Builder Design Patterns
– To compose object into tree structures that represent part-whole hierarchies – Lets clients treat individual objects and compositions of objects uniformly
– You want to represent part-whole hierarchies of
– You want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly.
containers)
★ ✍✯ ✥ ✢ ✒✕ ★ ✍✰ ✛ ✢ ✚ ✏ ✱ ★ ✮Given a frame containing multiple panes, each with multiple buttons/labels/checkboxes…
causes everything to be painted.
frame is likewise propagated down.
Leaf
Client Component
addComponent() removeComponent() getChild() Composite
addComponent() removeComponent() getChild() 0..* 0..* +children
– Client uses component class interface to interact with objects in composite structure. – If recipient is:
✁ ✂☎✄ ✆ ✝ ✞ ✟ ✄ ✠ ✡ ✄ ☛ ☞ ✌ ✆✍ ✎✏ ✄ ✎ ✎ ✑ ✟ ✄ ✒ ☞ ✏ ✓ ✁ ✔✖✕ ✗✘ ✕ ☛ ✑ ☞✙✄ ✞ ✟ ✄ ✠ ✡ ✄ ☛ ☞ ✝ ✕ ✟✚ ✆ ✟ ✎ ✄ ✎ ☞ ✕ ✒ ✌ ✑ ✏ ✎ ✟ ✄ ✍not just an example of polymorphism?
✥ ✦★✧ ✩✪ ✫ ✬✧ ✩✭ ✮✯ ✭ ✬ ✰ ✱ ✧ ✲ ✭ ✧ ✬✳ ✴ ✱ ✵ ✫ ✬ ✱ ✫ ✬✧ ✯ ✭ ✶✸✷ ✮ ✭ ✹ ✯ ✺ ✰ ✬ ✮ ✱ ✭ ✩ ✹ ✧ ✪ ✱ ✧ ✻ ✪ ✹ ✰ ✭ ✫ ✬ ✱ ✷ ✯ ✧ ✬ ✭ ✼ ✭ ✽ ✵ ✧ ✩ ✱ ✬ ✼ ✹ ✭ ✮ ✱ ✺ ✧ ✪ ✩ ✭ ✮ ✮ ✭ ✳ ✰ ✳ ✱ ✧ ✹ ✼ ✪ ✩ ✧✿✾ ✰ ✱ ✪ ✶ ✬ ✭ ✲ ✧ ✬ ✩ ✹ ✰ ✽❀✧ ✬ ✱ ✺ ✧ ✩ ✹ ✧ ✪ ✱ ✰ ✭ ✳ ✭ ✼ ✪ ✩✭ ✳ ✱ ✪ ✰ ✳ ✧ ✹ ✩ ✶ ✪ ✬ ✬ ✱ ✺ ✪ ✱ ✽ ✭ ✱ ✺ ✺ ✭ ✶ ✲ ✬ ✪ ✩ ✭ ✶ ✶ ✧ ✩ ✱ ✰ ✭ ✳ ✭ ✼ ✱ ✺ ✧ ✬✧ ✭ ✽ ✵ ✧ ✩ ✱ ✬ ✪ ✳ ✲ ✪ ✶ ✬ ✭ ✫ ✬✧ ✬ ✱ ✺ ✧ ✬ ✪ ✮ ✧ ✰ ✳ ✱ ✧ ✹ ✼ ✪ ✩ ✧ ✪ ✬ ✱ ✺ ✧ ✭ ✽ ✵ ✧ ✩ ✱ ✬ ✰ ✱ ✺ ✭ ✶ ✲ ✬✿❁ ✥ ❂ ✺ ✪ ✱ ✰ ✬ ✾ ✱ ✺ ✧ ✩✭ ✮✯ ✭ ✳ ✧ ✳ ✱ ✰ ✳ ✱ ✧ ✹ ✼ ✪ ✩ ✧ ✰ ✬ ✳ ✭ ✱ ✰ ✮✯ ✶ ✧ ✮ ✧ ✳ ✱ ✧ ✲ ✽ ✷ ✲ ✰ ✼ ✼ ✧ ✹ ✧ ✳ ✱ ✱ ✷ ✯ ✧ ✬ ✭ ✼ ✶ ✧ ✪ ✻ ✧ ✬ ✾ ✽ ✫ ✱ ✪ ✶ ✬ ✭ ✽ ✷ ✱ ✺ ✧ ✩ ✭ ✮✯ ✭ ✬ ✰ ✱ ✧ ❃ ✺ ✰ ✩ ✺ ✺ ✭ ✶ ✲ ✬ ✶ ✧ ✪ ✻ ✧ ✬ ❁ ❂ ✺ ✧ ✹ ✧ ✼ ✭ ✹ ✧✿✾ ✱ ✺ ✧ ✩ ✶ ✰ ✧ ✳ ✱ ✩✪ ✳ ✫ ✬✧ ✱ ✺ ✧ ✯ ✹ ✰ ✮ ✰ ✱ ✰ ✻ ✧ ✶ ✧ ✪ ✼ ✪ ✳ ✲ ✱ ✺ ✧ ✩✭ ✮✯ ✭ ✬ ✰ ✱ ✧ ✩✭ ✶ ✶ ✧ ✩ ✱ ✰ ✭ ✳ ✭ ✼ ✶ ✧ ✪ ✻ ✧ ✬ ✰ ✳ ✱ ✧ ✹ ✩ ✺ ✪ ✳ ❄ ✧ ✪ ✽✶✸✷ ✾ ✪ ✳ ✲ ✧ ✪ ✬ ✰ ✶✸✷ ✽ ✫ ✰ ✶ ✲ ✩✭ ✮✯ ✶ ✧ ❅ ✬ ✱ ✹ ✫ ✩ ✱ ✫ ✹ ✧ ✬ ✹ ✧ ✩ ✫ ✹ ✬ ✰ ✻ ✧ ✶ ✷ ❁[Gamma et al, pp 257-271]
✁ ✂ ✪ ✳ ✷ ✬ ✱ ✹ ✫ ✩ ✱ ✫ ✹ ✧ ✬ ✹ ✧ ✄ ✫ ✰ ✹ ✧ ✬ ✫ ✯ ✯ ✭ ✹ ✱ ✼ ✭ ✹ ✰ ✱ ✧ ✹ ✪ ✱ ✰ ✳ ❄ ✭ ✻ ✧ ✹ ✪ ✶ ✶ ✧ ✶ ✧ ✮ ✧ ✳ ✱ ✬ ✭ ✼ ✱ ✺ ✧ ✬ ✱ ✹ ✫ ✩ ✱ ✫ ✹ ✧ ✁ ☎★✭ ✹ ✧ ❅ ✪ ✮✯ ✶ ✧✿✾ ✰ ✱ ✧ ✹ ✪ ✱ ✰ ✳ ❄ ✭ ✻ ✧ ✹ ✩✭ ✳ ✱ ✧ ✳ ✱ ✬ ✭ ✼ ✪ ✻ ✧ ✩ ✱ ✭ ✹✆for (int i=0; i < v.size(); i++) { … Object o = v.elementAt(i); … }
Move to next element in list Current element First element Last element
visit each element in a container class
– I.e. over any class that contains a collection of elements
public interface Enumeration { // Returns true as long as there are more // elements to visit boolean hasMoreElements(); // Returns next element to visit Object nextElement(); }
✽ ✾ ✭ ✶ ✺ ✩ ✷ ✩ ✫ ✩ ✧ ✮ ✿ ✯ ✷ ✷ ✻ ✩ ✬ ✩ ✮ ✪ ✬ ✧ ✩ ✳ ✻ ✸ ❀❁ ❂ ❃ ❄ ❅ ❁ ❆ ❁ ❀ ❃ ✩ ❇ ✭ ✶ ✮ ✷ ✸ ✰ ✧ ✶ ✩ ✽ ❈ ✬ ✳ ✩ ✬ ✰ ✵ ✲ ✯ ✴ ✯ ✮ ✭ ✮ ✯ ✰ ✧ ✧ ✰ ✮ ✴ ✱ ✩ ✶ ✯ ✵ ✯ ✩ ✳// Returns all elements in the Vector public Enumeration elements();
✯ ✰★✱ ✲★✳ ✴ ✵ ✪ ✳ ✶✷ ✧ ✮// Returns all elements in the Hashtable. // That is, returns all values that have been // entered into the hashtable via put public Enumeration elements();
by calling the Vector’s elements method
✁ ✂☎✄ ✆ ✝✟✞ ✠ ✡☛ ☞✟✌ ✍ ✎ ✏✒✑ ✡✓ ✎ ☞ ✑ ✔ ✡ ☞✟✕ ✔ ✖ ✡☛ ☞ ✕ ✔✗elements of Vector via Enumeration’s methods
for (Enumeration e = v.elements(); e.hasMoreElements();) { Object o = e.nextElement(); … }
– Enumeration elements () – Must return an implementation of the Enumeration interface – Iterator must successively return values in vector
How we might implement an enumeration in a vector. (Not necessarily how it is really implemented.)
import java.util.Vector; class VectorEnumeration { // Represents where we are in the vector private int currentElement = 0; // The vector we are iterating through private Vector v; public boolean hasMoreElements () { return (currentElement < v.size()); } public Object nextElement () { Object returnElement = v.get (currentElement); currentElement++; return returnElement; } public VectorEnumeration (Vector v) { this.v = v; } }
Abstract representation
Concrete representation
Concrete iterator for specific container class - e.g. iterator for Vector is different from iterator for hashtable Enumeration interface
– Separates iteration behaviour from specifics of container class – Therefore can change container class without impacting code that iterates over it
– May be some minor performance penalty through indirection in iterator
– Separate the construction of a complex object from its representation
– The algorithm for creating a complex object should be independent of the parts that make up the object and how they’re assembled – The construction process must allow different representations for the object that’s constructed
ConcreteBuilder buildPart() getProduct() Product Director Builder buildPart() <<creates>>
configures it with the desired Builder object
and adds parts to the product
builder
aClient : Client aDirector : Director aConcreteBuilder : ConcreteBuilder new ConcreteBuilder() new Director(aConcreteBuilder) construct() buildPartA() buildPartB() buildPartC() getResult()
– It lets you vary a product’s internal representation – It isolates code for construction and representation – It gives you finer control over the construction process (object constructed step-by-step under the director’s control)
– N/A
work together
commonly occurring problems in design
✘reference
together to solve complex problems
given pattern, which must be carefully weighed.