Go Design Patterns
Go Design Patterns
“Gang of Four”
Design Patterns
Larman, chapters 25 and 26
CSE432
Object-Oriented Software Engineering
Glenn D. Blank, Lehigh University
Pure Fabrication
Another GRASP design pattern
They are:
“Descriptions of communicating objects and classes
that are customized to solve a general design problem in a
particular context.”
Three Types of GoF Patterns
Creational patterns:
Deal with initializing and configuring objects
Structural patterns:
Composition of classes or objects
Decouple interface and implementation of classes
Behavioral patterns:
Deal with dynamic interactions among societies of objects
How they distribute responsibility
Structural patterns
Assemble objects to realize new functionality
Exploit flexibility of object composition at run-time
Not possible with static class composition
Example: Proxy
Proxy acts as convenient surrogate or placeholder
for another object.
Examples?
Remote Proxy: local representative for object in a
different address space
Virtual Proxy: represent large object that should be
loaded on demand
Protected Proxy: protect access to the original object
Structural Patterns
Adapter:
Converts interface of a class into one that clients expect
Bridge:
Links abstraction with many possible implementations
Composite:
Represents part-whole hierarchies as tree structures
Decorator:
Attach additional responsibilities to object dynamically
Facade:
Simplifies the interface for a subsystem
Flyweight:
Shares many fine-grained objects efficiently
Proxy:
Provides a surrogate or placeholder for another object to control
access to it
Adapter pattern
Problem: How to resolve incompatible interfaces or
provide a stable interface to similar components
with different interfaces?
Solution: Convert original interface component into
another one through an intermediate adapter.
TaxMasterAdapter GoodAsGoldTaxPro
Adapter
«interface» «interface»
IAccountingAdapter ICreditAuthorizationService
Adapter
postReceivable( CreditPayment )
postSale( Sale ) requestApproval(CreditPayment,TerminalID, MerchantID)
... ...
«interface»
IInventoryAdapter
SAPAccountingAdapter GreatNorthernAccountingAdapter
...
:Register : SAPAccountingAdapter
makePayment
...
SOAP over
HTTP
postSale( sale )
xxx «actor»
: SAPSystem
Fig. 26.2
Benefits of Adapter pattern
Reduces coupling to implementation specific details
Polymorphism and Indirection reveals essential
behavior provided
Including name of design pattern in new class (e.g.,
TaxMasterAdapter) in class diagrams and code
communicates to other developers in terms of
known design patterns
Creational Patterns
Singleton: Guarantee access to a singular (sole) instance
Simple Factory: Create specialized, complex objects
Abstract Factory: Create a family of specialized factories
Factory Method: Define an interface for creating an
object, but let subclasses decide which class to instantiate
Builder: Construct a complex object step by step
Prototype: Clone new instances from a prototype
Lazy initialization: Delay costly creation until it is needed
Singleton pattern (creational)
A class with just instance and provide a global point of access
Global Variables can be dangerous!
(side effects, break information hiding)
class Singleton
{ public:
static Singleton* getInstance();
protected: //Why are the following protected?
Singleton();
Singleton(const Singleton&);
Singleton& operator= (const Singleton&);
private: static Singleton* instance;
};
Singleton *p2 = p1->getInstance();
Simple Factory pattern
Context/Problem
Who should be responsible for creating objects
when there are special considerations, such as
complex logic,a desire to separate the creation
responsibilities for better cohesion, and so forth
Solution
Create a Pure Fabrication to handle the creation
Factory can create different
objects from a file
ServicesFactory note that the factory methods
return objects typed to an
accountingAdapter : IAccountingAdapter interface rather than a class, so
inventoryAdapter : IInventoryAdapter that the factory can return any
taxCalculatorAdapter : ITaxCalculatorAdapter implementation of the interface
getAccountingAdapter() : IAccountingAdapter
getInventoryAdapter() : IInventoryAdapter
getTaxCalculatorAdapter() : ITaxCalculatorAdapter
...
if ( taxCalculatorAdapter == null )
{
// a reflective or data-driven approach to finding the right class: read it from an
// external property
}
return taxCalculatorAdapter;
Figure 26.5
Advantages of Factory Objects?
Separates responsibility of complex creation into
cohesive helper classes
Hides complex creation logic, such as
initialization from a file
Handles memory management strategies,
such or recycling or caching
Use Singleton to create a Factory
UML notation: this '1' can optionally be used to
indicate that only one instance will be created (a
singleton)
1
ServicesFactory
// static method
public static synchronized ServicesFactory getInstance()
{
if ( instance == null )
instance = new ServicesFactory()
return instance
} Figure 26.6
Adapter, Factory and Singleton
working together
1
:Store
:ServicesFactory
create
create :Register
accountingAdapter =
getAccountingAdapter
create : SAPAccounting
Adapter
accountingAdapter:
:Register
SAPAccountingAdapter
makePayment
create(cashTendered) : Payment SOAP over
HTTP
postSale( sale )
xxx «actor»
: SAPSystem
Figure 26.8
Behavioral Patterns
Chain of Responsibility:
Request delegated to the responsible service provider
Command:
Request or Action is first-class object, hence storable
Iterator:
Aggregate and access elements sequentially
Interpreter:
Language interpreter for a small grammar
Mediator:
Coordinates interactions between its associates
Memento:
Snapshot captures and restores object states privately
{ {
return s.getPreDiscountTotal() * percentage pdt := s.getPreDiscountTotal()
} if ( pdt < threshold )
return pdt
else
return pdt - discount Figure 26.9
}
Observer pattern
Intent:
Define a one-to-many dependency between objects
so that when one object changes state, all its dependents
are notified and updated automatically
Used in Model-View-Controller framework
Model is problem domain
View is windowing system
Controller is mouse/keyboard control
How can Observer pattern be used in other
applications?
JDK’s Abstract Window Toolkit (listeners)
Java’s Thread monitors, notify(), etc.
Structure of Observer Pattern
Subject Observer
} +detach(in Observer)
ConcreteObserver
ConcreteSubject
-subjectSate * +update()
+getState() 1