gang of four
DESCRIPTION
gTRANSCRIPT
![Page 1: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/1.jpg)
More Design Patterns
Wednesday, 31 October 12
![Page 2: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/2.jpg)
More Design Patterns
• 1. Adapter
• 2. Factory Method (& Abstract Factory)
• 3. Singleton
• 4. Observer
• 5. Command (& Command-Holder)
Wednesday, 31 October 12
![Page 3: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/3.jpg)
1. Adapter
• problem:
• you want to re-use an existing off-the-shelf component in your design, but it doesn’t quite fit your needs
• its code cannot be changed
• solution:
• create an Adapter class which can act as an intermediary
Wednesday, 31 October 12
![Page 4: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/4.jpg)
Real Life Example
• problem:
• a socket wrench can turn 25mm bolts (has female 25mm socket)
• you want to turn a 12mm bolt (has male 12mm head)
• solution:
• attach a ‘25mm (male) to 12mm (female)’ adapter to the wrench
• now your wrench can turn 12mm bolts. Yay!
Wednesday, 31 October 12
![Page 5: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/5.jpg)
Coding Example: Rectangle
• a LegacyRectangle takes (topLeft, topRight, width, height) as parameters
• but the client wants to pass (topLeft, topRight, lowerLeft, lowerRight)
• we can build an adapter (or wrapper) Rectangle class which allows this:
• the wrapper takes the client’s request and repackages it for LegacyRectangle
from http://sourcemaking.com/design_patterns/adapter
Wednesday, 31 October 12
![Page 6: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/6.jpg)
How to Apply
• identify the classes which need to connect
• the client and the adaptee
• identify the interface which the client requires
• design a wrapper class which provides the interface required by the client:
• it will have an instance of the adaptee as an attribute
• it will map the client interface to the adaptee interface
• the client can now use the new interface provided by the wrapper class to access the functionality of the adaptee class.
Wednesday, 31 October 12
![Page 7: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/7.jpg)
Comment
• adapter is a form of polymorphism (see Grasp Part 2)
• adapters are used when there is an existing, immutable component
• if the component is mutable then consider changing the code or using an interface (see polymorphism steering example)
Wednesday, 31 October 12
![Page 8: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/8.jpg)
2. Factory Method
• problem:
• how do we create different kinds of subclass without:
• exposing the instantiation logic to the client?
• forcing the client to be aware of the different subtypes?
• solution:
• we use a Factory class which creates concrete subtypes for the client
Wednesday, 31 October 12
![Page 9: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/9.jpg)
Implementation
• the client needs a new Product, so it asks the factory object for a new Product, providing information about the type of Product it needs
• the factory instantiates a new Concrete Product and returns it to the client (casted to abstract Product class)
• the client uses the Products it is given as abstract Products without being aware of their concrete implementation
• we can add more products (subtypes) without altering the client’s code
from http://www.oodesign.com/factory-pattern.html
Wednesday, 31 October 12
![Page 10: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/10.jpg)
Example: Shapes
• a graphical application:
• client: drawing framework
• products: shapes
• abstract Shape class defines the draw and move operations which must be implemented by the concrete shapes
• for example, the user selects to create a circle and specifies its radius
• the framework receives the parameters “circle” and “2.5” and asks the factory to create a shape based upon them
• the factory creates a new Circle and returns it to the client cast as an abstract Shapeadapted from http://www.oodesign.com/factory-pattern.html
DrawingFramewk
Shape
Circle createShape( String type, double [] parameters)
Wednesday, 31 October 12
![Page 11: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/11.jpg)
Abstract Factory Pattern
extends the factory method by providing the interface to create a family of related objects without needing to explicitly refer to their classes:
declares an interface for operations which create abstract Products
implements operations to make concrete Products
declares an interface for a type of Product object
• defines a Product which will be created by the corresponding Concrete Factory• implements the AbstractProduct interface
uses the interfaces declared by the AbstractFactory and AbstractProduct classes
adapted from http://www.oodesign.com/factory-pattern.html
Wednesday, 31 October 12
![Page 12: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/12.jpg)
Implementation
• AbstractFactory:
• determines the actual types of each concrete object and creates them
• returns abstract pointers to the objects created
• Client:
• knows nothing about the actual object’s creation
• has no need for class declarations relating to the concrete types
• Example: a global vending system:
• Orders are created and need to record customers’ Address and ContactPhoneNumber
• those objects will have differing formats depending upon which country the customer lives in
• so we can create factories for each country (or format), and point the Order class to the correct one based upon the customer’s place of residence
Wednesday, 31 October 12
![Page 13: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/13.jpg)
Issues
• Pros:
• isolates creation of objects from the client, making manipulation easier
• when we need to exchange product families, the only change we need to make in the client code is to make it use the new factory
• Cons:
• adding new products to existing factories is difficult
• because we have to change the AbstractFactory interface and all its subtypes
Wednesday, 31 October 12
![Page 14: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/14.jpg)
3. Singleton
• problem:
• sometimes we just want a single instance of a class
• examples:
• a print handler
• a factory which issues unique ids to the objects which it creates
• so what do we do if several clients need to be able to see a single instance of a class and only a single instance?
• solution:
• we create a Singleton which provides a global and single point of access to the class
Wednesday, 31 October 12
![Page 15: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/15.jpg)
But what is the problem?
• if lots of clients need visibility to a single instance of a class, then we could just achieve that by:
• passing the reference to it around all those classes
• initialise all objects which need visibility with a permanent reference
• both do-able, but very inconvenient
• it’s far easier to instead provide a globally visible access point to the single instance
• providing we take care to ensure its uniqueness...
• which leads to one final question:
• if we only need one instance of a class in our design, used by many objects, then who should create it?
• let it create itself!
• and provide that single instance through a static getInstance() method
Wednesday, 31 October 12
![Page 16: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/16.jpg)
Example
MoleculeFactory
instance : MoleculeFactory
- MoleculeFactory()+ getInstance() : MoleculeFactory
public static MoleculeFactory getInstance(){
if ( instance == null ){
instance = new MoleculeFactory();}return instance;
}
the underlining tells us that the attribute or method is static
• the constructor is private• so other objects can only create an instance of this class through the publicly visible getInstance() method
Wednesday, 31 October 12
![Page 17: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/17.jpg)
Lazy or Eager?
• notice that the single instance is not initialised until the getInstance method is called
• this is Lazy Initialisation
• why not use eager initialisation instead?
• lazy initialisation is preferred because:
• creation work is avoided if the instance is never actually accessed during runtime
• initialisation could require complex or conditional creation logic
Lazy Initialisation:
public static MoleculeFactory getInstance(){
if ( instance == null ){
instance = new MoleculeFactory();}return instance;
}
Eager Initialisation
instance = new MoleculeFactory();...public static MoleculeFactory getInstance(){
return instance;}
Wednesday, 31 October 12
![Page 18: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/18.jpg)
Use Static Methods?
• why don’t we just make all of the singleton’s methods static and publicly visible, thus avoiding instantiation altogether?
• using a instance with non-static methods is better:
• it permits subclassing
• it permits overriding, which (usually non-polymorphic) static methods don’t allow
• can avoid the “cannot make a static reference to the non-static method [blah]” coding error
Wednesday, 31 October 12
![Page 19: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/19.jpg)
Issues
• a global access point means that the singleton is explicitly represented by its class name at many points in the code
• if we replace or rename it then every reference to it must be replaced or renamed too
• if the singleton implements the Serializable interface then it is possible to create multiple instances through serialization then deserialization
• implementing readResolve() avoids this
Wednesday, 31 October 12
![Page 20: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/20.jpg)
Issues
• need extra care to ensure that only one instance is initialised if your code is multi-threaded
• use a lock. In java:
• public static synchronized MoleculeFactory getInstance()
• although double-locking is better
Wednesday, 31 October 12
![Page 21: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/21.jpg)
4. Observer
• problem:
• a lot of objects need to know when a change happens to another object’s state
• solution:
• define a one-to-many dependency between objects so that when the state of one object (the subject) changes then all the dependant objects (the observers) are automatically notified
Wednesday, 31 October 12
![Page 22: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/22.jpg)
But what is the problem?
• sometimes tightly coupling a lot of classes to a subject class is a bad idea:
• we have to write code to explicitly update those classes whenever the subject changes, maybe spread across several methods or classes
• if more classes need to change then we have to add more code to our program to follow any changes to the subject
• not every observing class will need to update every time
• so keeping a track of which classes need to update and when is difficult
• it would be better if the subject simply:
• allowed other objects to subscribe to it, and then
• notified its subscribers whenever its state changes
Wednesday, 31 October 12
![Page 23: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/23.jpg)
Observer PatternObserver
<<interface>>
notify( Subject, Object) : void
Subject<<abstract>>
observers : ArrayList<Observer>
register( Observer) : voidunregister( Observer) : voidnotifyObservers( Object) : void
public interface Observer{
public void notify( Subject subject, Object argument);}
abstract class Subject{
protected ArrayList<Observer> observers;public void register( Observer obs){
observers.add( obs);}public void unregister( obs){
observers.remove( obs);}public void notifyObservers( Object argument){
Iterator iterator = observers.iterator();while ( iterator.hasNext() ){
Observer observer = iterator.next();observer.notify( this, argument);
}}
}
Wednesday, 31 October 12
![Page 24: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/24.jpg)
Example: ebay listings
• whenever the current highest bid for an item ends:
• the item’s display listing will need to be updated
• so too will the persistent record
• watchers will need to be notified
• by email
• through their account summary
• the seller, current highest bidder and previous highest bidder need to be told too
• the nature and frequency of these updates will depend upon each customer’s contact preferences
• so, potentially a lot of conditional code to create and handle
• but the observer pattern vastly simplifies this
Wednesday, 31 October 12
![Page 25: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/25.jpg)
Example: ebay listings
Observer<<interface>>
notify( Subject, Object) : void
Subject<<abstract>>
observers : ArrayList<Observer>
register( Observer) : voidunregister( Observer) : voidnotifyObservers( Object) : void
Item
itemId : IDdescription: StringcurrentHighestBid: Money
...
DisplayListingUI
...
...
Customer
...
...
Seller
...
...
ItemsDB
...
...
• when the value of currentHighestBid changes, responsibility for which observers need to act and how is handled by the observers themselves• Item merely tells them that its state has changed
• since Item only implements an interface it can also be sub-typed• but what if we want to make Customer and Seller subtypes of User?
observe
Wednesday, 31 October 12
![Page 26: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/26.jpg)
Benefits
• coupling is minimised:
• the subject doesn’t know anything about its observers
• only that it has a list of observers
• the observers don’t know about each other
• but behave as if they do
• when one changes, so does another
• so we achieve abstract, minimised coupling
Wednesday, 31 October 12
![Page 27: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/27.jpg)
Benefits
• updates can be broadcast:
• when the subject changes it notifies all observers
• without needing to specify each receiver
• and we can add or remove as many observers as we like
• reactions can be conditional:
• observers get to choose which notifications to respond to, how to respond and which to ignore
• in the ebay example this can be on an object-by-object basis for the customer class
Wednesday, 31 October 12
![Page 28: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/28.jpg)
Problems
• timing issues:
• in a multi-threaded program observers might update out of desired order
• for example, web page says ‘item in stock’ before the database gets updated
• we might accidentally notify observers before we have finished updating the subject (easier to do than you’d think)
• without care we could also cause recursive notifications
Wednesday, 31 October 12
![Page 29: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/29.jpg)
Problems
• performance issues:
• an update could cause a cascade of notifications (especially where some observers are also subjects for their own sets of observers)
• we can mitigate this by allowing observers to register to specific events within the subject
• subject is an abstract class, not an interface:
• java won’t allow multiple (abstract) inheritance
• if your subject must be a sub-type of another class then you’ll need to explicitly code the Subject methods and list of observers into it
Wednesday, 31 October 12
![Page 30: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/30.jpg)
Problems
• who should call notifyObservers()?
• it could be a private method, called by the subject
• but that could be inefficient
• for example: multiple successive changes happen to the subject’s state
• we could let clients call the method instead
• but that makes errors more likely
Wednesday, 31 October 12
![Page 31: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/31.jpg)
5. Command
• problem:
• one class in the user interface is usually responsible for listening to user actions
• it often also becomes the repository for all the logic which responds to user actions
• this leads to large, incohesive classes
• it violates the principle of separation of concerns
• solution:
• assign responsibility for the responses to small, functionally distinct Command classes
Wednesday, 31 October 12
![Page 32: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/32.jpg)
Command Interface
• all the working code resides within, or is called from, the execute() method
• this presents a common interface to clients, reducing the need for conditional handling of different methods for different objects
public interface Command{
public void execute();}
Wednesday, 31 October 12
![Page 33: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/33.jpg)
Example: Control Buttons
start pause resume
without using Command:
inside the main UI class:
public void ActionPerformed( Event event){
if ( event.getSource.equals( startButton) ){
simulation.start();}else if ( event.getSource.equals( pauseButton) ){
simulation.pause();}else if ( event.getSource.equals( resumeButton) ){
simulation.resume();}.... // and so on for all other UI events
}
using Command:
inside the main UI class:
public void ActionPerformed( Event event){
((Command) event.getSource()).execute();}
inside a typical button class:
public StartButton extends JButton implements Command{
public void execute(){
simulation.start();}
}
Wednesday, 31 October 12
![Page 34: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/34.jpg)
...better, but still problems
• we have separated the details of the commands from the main UI
• but they are still tightly coupled to the individual UI components which trigger them
• and we might want to trigger a command from multiple components
• or even from some other source (e.g. control code)
• we might want to alter the command triggered by a component
• so we should use the CommandHolder interface
Wednesday, 31 October 12
![Page 35: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/35.jpg)
CommandHolder Interface
• all the working code now resides within separate Command classes
• the CommandHolder classes (usually UI components) only need to know that they hold a Command, not what it does
• when a client requests a Command from a CommandHolder using getCommand(), the CommandHolder simply passes the Command to the client
public interface CommandHolder{
public void setCommand( Command command);public Command getCommand();
}
Wednesday, 31 October 12
![Page 36: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/36.jpg)
Example: Control Buttonsstart pause resume
using CommandHolder:
inside the main UI class:
public void ActionPerformed( Event event){
((Command) event.getSource().getCommand()).execute();}
typical button class:
public StartButton extends JButton implements CommandHolder{
Command myCommand;public void setCommand( Command command){
this.command = command;}public Command getCommand(){
return Command;}
}
typical Command class:
public StartCommand implements Command{
public void execute(){
simulation.start();}
}
and because we can easily swap the command held by a button, we have the opportunity to replace the three buttons with one, de-cluttering the user interface
Wednesday, 31 October 12
![Page 37: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/37.jpg)
Benefits
• application logic fully separated from the UI
• allows contextual use of components:
• can switch the commands which they invoke, even disable them
• allows commands to be maintained and invoked away from the UI
• if we record the list of commands so far invoked then we can often implement an Undo command
Wednesday, 31 October 12
![Page 38: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/38.jpg)
To conclude
• the five (and a bit) patterns investigated here build upon the core GRASP principles
• taken together they can lead to clean, cohesive, lightly coupled code
• easy to read
• easy to re-use
• easy to change
• you can create your own java libraries for some of the interfaces
• as always, use appropriately
• some small, one-off projects won’t need this degree of flexibility
Wednesday, 31 October 12
![Page 39: Gang of Four](https://reader034.vdocuments.mx/reader034/viewer/2022051621/55cf8f0a550346703b9850c1/html5/thumbnails/39.jpg)
References & Further Reading
• Adapter
• http://sourcemaking.com/design_patterns/adapter
• Factory Method
• http://www.oodesign.com/factory-pattern.html
• http://www.oodesign.com/abstract-factory-pattern.html
• Singleton
• http://www.ibm.com/developerworks/java/library/j-dcl/index.html
• Observer Pattern
• http://www.research.ibm.com/designpatterns/example.htm
• Command Holder
• Java Design Patterns: A Tutorial (JW Cooper 2000)
Wednesday, 31 October 12