Chapter 24: Applying GoF Design Patterns

1 / 23
About This Presentation
Title:

Chapter 24: Applying GoF Design Patterns

Description:

... four authors : Erich Gamma, Richard Helm, Ralph Johnson, John Vissides who wrote ... A 'classic' of software engineering, that is timeless. ... – PowerPoint PPT presentation

Number of Views:455
Avg rating:3.0/5.0
Slides: 24
Provided by: christop139

less

Transcript and Presenter's Notes

Title: Chapter 24: Applying GoF Design Patterns


1
Chapter 24 Applying GoF Design Patterns
  • 24.1. Introduction
  • The Gang of Four (GoF) are four authors Erich
    Gamma, Richard Helm, Ralph Johnson, John Vissides
    who wrote a very influential book on Object
    Oriented design Patterns
  • Design patterns elements of reusable
    object-oriented software
  • Addison Wesley, 1995, ISBN 0201633612.

A "classic" of software engineering, that is
timeless. It presents 23 patterns useful during
object design. It is more of a follow-up to this
course on OO Design.
2
  • 24.2 Adapter
  • Many of the GoF patterns are in fact
    specialisations of the generic GRASPs in other
    words, Larmans patterns are more general than
    many ordinary patterns
  • That is not surprising more than 500 patterns
    have been documented most overlap and/or are
    refinements of others
  • It is nevertheless a good opportunity to review
    the general solution applied
  • The POSs problem of dealing with many tax
    calculators which was solved by applying the
    Polymorphism pattern is actually an example of
    the Adapter pattern.
  • Problem How to resolve incompatible interfaces,
    or provide a stable interface to similar
    components with different interfaces?
  • Solution Convert the original interface of a
    component into another interface, through an
    intermediate adapter object.

3
  • This solution basically adds a level of
    indirection within the application

4
  • Dynamically, a particular adapter instance will
    be instantiated for the chosen external service
  • (SOAP Simple Object Access Protocol, is a
    protocol for exchanging XML-based messages over a
    computer network, normally using HTTP.)

5
  • In conclusion, Adapter supports Protected
    Variations with respect to changing external
    interfaces or third-party packages through the
    use of an Indirection object that applies
    interfaces and Polymorphism.
  • 24.3 Factory
  • In the prior Adapter pattern solution for
    external services with varying interfaces, who
    creates the adapters? And how to determine which
    class of adapter to create, such as
    TaxMaster-Adapter or GoodAsGoldTaxProAdapter?
  • A naive solution, would be that some domain
    object creates them, but this obviously would
    lower their cohesion (and also breaks the
    separation of concern principle).
  • A solution, is to apply the Factory pattern, in
    which a Pure Fabrication "factory" object is
    defined to create objects.

6
  • This has the following advantages
  • Separate the responsibility of complex creation
    into cohesive helper objects.
  • Hide potentially complex creation logic.
  • Problem Who should be responsible for creating
    objects when there are special considerations,
    such as complex creation logic, a desire to
    separate the creation responsibilities for better
    cohesion, and so forth?
  • Solution Create a Pure Fabrication object called
    a Factory that handles the creation.
  • Example

7
(No Transcript)
8
  • Note that in the ServicesFactory, the logic to
    decide which class to create is resolved by
    reading in the class name from an external source
    and then dynamically loading the class. This is
    an example of a partial data-driven design. This
    design achieves Protected Variations with respect
    to changes in the implementation class of the
    adapter. Without changing the source code in this
    factory class, we can create instances of new
    adapter classes by changing the property value.
  • Factories are often accessed with the Singleton
    pattern.
  • 24.4 Singleton
  • First, observe that only one instance of the
    factory is needed within the process. Second,
    quick reflection suggests that the methods of
    this factory may need to be called from various
    places in the code, as different places need
    access to the adapters for calling on the
    external services. Thus, there is a visibility
    problem How to get visibility to this single
    ServicesFactory instance?

9
  • One solution is pass the ServicesFactory instance
    around as a parameter to wherever a visibility
    need is discovered for it, or to initialize the
    objects that need visibility to it, with a
    permanent reference. This is possible but
    inconvenient an alternative is the Singleton
    pattern.
  • Problem Exactly one instance of a class is
    allowed it is a "singleton." Objects need a
    global and single point of access.
  • Solution Define a static method of the class
    that returns the singleton.
  • Example

10
  • Thus, the key idea is that class X defines a
    static method getInstance that itself provides a
    single instance of X.
  • With this approach, a developer has global
    visibility to this single instance, via the
    static getInstance method of the class.

11
  • public class Register
  • public void initialize()
  • do some work
  • // accessing the singleton Factory via the
  • // getInstance call
  • accountingAdapter ServicesFactory.getInstan
    ce().getAccountingAdapter()
  • do some work
  • // other methods
  • // end of class

12
  • 24.5 Strategy
  • The next design problem to be resolved is to
    provide more complex pricing logic, such as a
    store-wide discount for the day, senior citizen
    discounts, and so forth.
  • The pricing strategy (which may also be called a
    rule, policy, or algorithm) for a sale can vary.
    During one period it may be 10 off all sales,
    later it may be 10 off if the sale total is
    greater than 200, and myriad other variations.
    How do we design for these varying pricing
    algorithms?
  • Problem How to design for varying, but related,
    algorithms or policies? How to design for the
    ability to change these algorithms or policies?
  • Solution Define each algorithm/policy/strategy
    in a separate class, with a common interface.

13
  • Example

14
  • At any one time there is only one pricing
    strategy, but it can change very often (e.g.
    every hour).
  • In a collaboration diagram the Sale object
    delegates some of the work to the pricing
    strategy object

15
  • The corresponding Design Class Diagram is

16
  • There could be many different kinds of pricing
    strategy and in addition they must be changeable
    at runtime. It therefore makes sense to use the
    Factory pattern to create a Pure Fabrication
    class responsible for maintaining the current
    pricing strategy.
  • As with the ServicesFactory, it can read the name
    of the implementation class of the pricing
    strategy from a system property (or some external
    data source), and then make an instance of it.
  • This is uses the data-driven approach one can
    change the current pricing strategy at start up
    time but also at run time.
  • A different factory is used (rather than reuse
    the previous ServicesFactory) because the purpose
    is quite different (helps maintaining the
    cohesion of the Factories)

17
  • Note that because of the frequently changing
    pricing policy, it is not desirable to keep the
    local created strategy instance in a field of the
    PricingStrategyFactory (unlike in the
    ServicesFactory), but rather to re-create one
    each time, by reading the external property for
    its class name, and then instantiating the
    strategy.

18
  • Of course as with most factories, the
    PricingStrategyFactory will be a singleton (one
    instance) and accessed via the Singleton pattern.
  • When a Sale instance is created, it can ask the
    factory for its pricing strategy

19
  • Finally, we need to consider the initial discount
    values (e.g. the discount percentage).
  • Best to factor out these in an external data
    store (a database, a script file, an xml file
    etc.) accessed at run-time. This is again
    data-driven design.
  • Hence, Protected Variations with respect to
    dynamically changing pricing policies has been
    achieved with the Strategy and Factory patterns.
    Strategy builds on Polymorphism and interfaces to
    allow pluggable algorithms in an object design.
  • We have also used the Singleton pattern and
    applied data-driven design where possible.

20
  • 24.6 Factories in C
  • As seen, Factories allow us to create instance(s)
    of a class that we do not know at compilation
    time. A factory is responsible for
    creating/destroying a set of objects and
    providing references to them on request.
  • In fact we would like to write
  • class Object / ... /
  • class Rocket public Object / ... /
  • class Npc public Object / ... /
  • type aType Rocket
  • //anonymously and dynamically allocate
  • Object pObject new aType
  • unfortunately that is not possible (compiler
    wont let you).
  • A simple and common approach to writing a factory
    is to create an enumerated type that represents
    the different classes of object you can create

21
  • enum GameObjectType
  • PLAYER,
  • ENEMY,
  • POWERUP,
  • WEAPON,
  • // ... rest of the objects...
  • GameObject ObjectFactoryCreate(GameObjectType
    type)
  • switch (type)
  • case PLAYER return new Player()
  • case ENEMY return new Enemy()
  • case POWERUP return new Powerup()
  • case WEAPON return new Weapon()
  • default assert( ObjectFactoryCreate
    unknown type)
  • This is not very flexible (hardcoded) it is
    impossible to add new object types without
    modifying the code ...

22
  • If more flexibility is required then we should
    move to a data driven solution to implementing
    the Factory.
  • e.g. by using strings compares rather than the
    enumeration type.

23
  • 24.7 Conclusions
  • There are many other patterns that might be
    useful Composite, Façade, Observer/Publisher
    (Event Modeller to enforce Model View Separation
    Principle).
  • In practice we must absolutely remember that our
    ultimate goal is not just code that works, but
    also - especially for highly variable projects
    such as games code that is also maintainable
    and extensible.
  • Basic, data-driven designs is probably your best
    friend to achieve this (see Protected Variations
    design pattern).
  • Factories play a crucial role in game development
    and are essential to data driven designs as we
    are need to constantly create new objects of all
    sorts of different types that we cannot predict
    ahead of time.
Write a Comment
User Comments (0)