Design Patterns...

Discussion in 'Java' started by secret, Sep 24, 2003.

  1. secret

    secret Guest

    I've been reading the GoF book and it clicks (at last) as I'm reading it.
    However, I think I (and maybe many others) would benefit greatly from
    hearing about some real world uses of the patterns. What problems did they
    actually help solve. Understanding the multitude of GUI examples in the
    book does not help me to see applications in other areas and I fear that I
    wouldn't recognize a relevant occasion to use some of them if I came across
    it.

    Here are some of the patterns to jog your memory...

    Creational Patterns...
    Abstract Factory,
    Builder,
    Factory Method,
    Prototype,
    Singleton

    Structural Patterns
    Adapter,
    Bridge
    Composite
    Decorator
    Facade
    Flyweight
    Proxy

    Behavioural Patterns
    Chain of Responsibility
    Command
    Interpreter
    Mediator
    Memento
    Observer
    State
    Strategy
    Template Method
    Visitor
    State Machine

    Some of them are more self-explanatory than others, but real world examples
    would be appreciated in any of them...

    alan
    secret, Sep 24, 2003
    #1
    1. Advertising

  2. secret wrote:

    > I've been reading the GoF book and it clicks (at last) as I'm reading it.
    > However, I think I (and maybe many others) would benefit greatly from
    > hearing about some real world uses of the patterns. What problems did they
    > actually help solve. Understanding the multitude of GUI examples in the
    > book does not help me to see applications in other areas and I fear that I
    > wouldn't recognize a relevant occasion to use some of them if I came across
    > it.
    >
    > Here are some of the patterns to jog your memory...
    >
    > Creational Patterns...
    > Abstract Factory,
    > Builder,
    > Factory Method,
    > Prototype,


    Prototype (with Factory Method):

    In a DNS client application, there is a class hierarchy for the various
    types of DNS Resource Records. When constructing an object representing
    a DNS response, it is necessary to obtain Resource Record objects of the
    appropriate classes, based on the DNS resource record type and class codes.

    The chosen solution was to give the ResourceRecord base class a
    newInstance() method that creates and returns (as it says) a new
    instance of ResourceRecord based on the parameters specific to a
    particular raw record. Subclasses override this method appropriately,
    providing instances of their own class. To construct the resource
    record object the client looks up the class / type combination in a Map,
    obtaining from it the appropriate prototype object, and then invokes the
    newInstance method of the prototype. (And this is all performed inside
    a Factory object, an implementation of one of the patterns you didn't
    mention.)

    Advantages:

    (1) User can easily configure classes for new resource record types, or
    alternative classes for supported resource record types.

    (2) The client code is decoupled from specific resource record
    implementations.

    (3) No use of reflection.

    > Singleton


    Singleton:

    [Comment: this one is overused in my experience, perhaps because it is
    fairly easy to understand. This pattern should be applied only when it
    is _necessary_ that there be only one instance.]

    As a somewhat abstract description of another real example, take a case
    where a collection of objects in potentially many threads need to draw
    unique numbers from a continuous sequence (serial numbers, for
    instance). Suppose also that these disparate objects have no direct
    knowledge of each other. In order that all possible objects that use
    the same sequence, the sequence is encapsulated in a Singleton object.
    When an object needs a number from the sequence, it obtains the (one)
    instance of the Singleton and invokes the appropriate method on it.

    > Structural Patterns
    > Adapter,


    Adapter:

    A user must write tests for two different implementations of the same
    basic functionality. Instead of two completely different test suites,
    the user writes one suite and for each implementation one adapter class
    so that the test suite can work with either one.

    > Bridge
    > Composite
    > Decorator


    Decorator:

    [From JUnit] a JUnit TestSuite instance defines one or more tests to be
    run. For each one there is a setup step, a test step, and tear down
    step; these are run sequentially. TestSuite implements an interface
    Test, via which the group of tests is executed. If it is desired to
    perform a setup and/or teardown procedure for the whole suite, then the
    TestSuite can be decorated by a TestSetup that defines them; TestSetup
    also implements Test and wraps a TestSuite.

    > Facade
    > Flyweight
    > Proxy
    >
    > Behavioural Patterns
    > Chain of Responsibility
    > Command
    > Interpreter
    > Mediator
    > Memento
    > Observer
    > State
    > Strategy


    Strategy:

    [From Java Collections] The Comparator interface and all its
    implementations. The Collections and Arrays classes provide generic
    methods by which to sort objects; the specific sort order is directed by
    a Comparator instance. Different Comparators give you potentially
    different sort orders.

    > Template Method


    Template Method:

    [Also from Java Collections] The AbstractCollection class defines an
    entire Collection implementation in terms of abstract iterator() and
    size() methods, and a stub add(Object) method. These three (especially
    the first two) are template methods -- a concrete subclass can override
    just those and thereby fully implement Collection in any manner desired.

    Other AbstractXXX classes among the Collection classes work similarly.

    > Visitor
    > State Machine



    John Bollinger
    John C. Bollinger, Sep 24, 2003
    #2
    1. Advertising

  3. secret

    secret Guest

    Thanks John, that's fantastic. Very helpful.

    alan

    "John C. Bollinger" <> wrote in message
    news:bkt63f$kgt$...
    > secret wrote:
    >
    > > I've been reading the GoF book and it clicks (at last) as I'm reading

    it.
    > > However, I think I (and maybe many others) would benefit greatly from
    > > hearing about some real world uses of the patterns. What problems did

    they
    > > actually help solve. Understanding the multitude of GUI examples in the
    > > book does not help me to see applications in other areas and I fear that

    I
    > > wouldn't recognize a relevant occasion to use some of them if I came

    across
    > > it.
    > >
    > > Here are some of the patterns to jog your memory...
    > >
    > > Creational Patterns...
    > > Abstract Factory,
    > > Builder,
    > > Factory Method,
    > > Prototype,

    >
    > Prototype (with Factory Method):
    >
    > In a DNS client application, there is a class hierarchy for the various
    > types of DNS Resource Records. When constructing an object representing
    > a DNS response, it is necessary to obtain Resource Record objects of the
    > appropriate classes, based on the DNS resource record type and class

    codes.
    >
    > The chosen solution was to give the ResourceRecord base class a
    > newInstance() method that creates and returns (as it says) a new
    > instance of ResourceRecord based on the parameters specific to a
    > particular raw record. Subclasses override this method appropriately,
    > providing instances of their own class. To construct the resource
    > record object the client looks up the class / type combination in a Map,
    > obtaining from it the appropriate prototype object, and then invokes the
    > newInstance method of the prototype. (And this is all performed inside
    > a Factory object, an implementation of one of the patterns you didn't
    > mention.)
    >
    > Advantages:
    >
    > (1) User can easily configure classes for new resource record types, or
    > alternative classes for supported resource record types.
    >
    > (2) The client code is decoupled from specific resource record
    > implementations.
    >
    > (3) No use of reflection.
    >
    > > Singleton

    >
    > Singleton:
    >
    > [Comment: this one is overused in my experience, perhaps because it is
    > fairly easy to understand. This pattern should be applied only when it
    > is _necessary_ that there be only one instance.]
    >
    > As a somewhat abstract description of another real example, take a case
    > where a collection of objects in potentially many threads need to draw
    > unique numbers from a continuous sequence (serial numbers, for
    > instance). Suppose also that these disparate objects have no direct
    > knowledge of each other. In order that all possible objects that use
    > the same sequence, the sequence is encapsulated in a Singleton object.
    > When an object needs a number from the sequence, it obtains the (one)
    > instance of the Singleton and invokes the appropriate method on it.
    >
    > > Structural Patterns
    > > Adapter,

    >
    > Adapter:
    >
    > A user must write tests for two different implementations of the same
    > basic functionality. Instead of two completely different test suites,
    > the user writes one suite and for each implementation one adapter class
    > so that the test suite can work with either one.
    >
    > > Bridge
    > > Composite
    > > Decorator

    >
    > Decorator:
    >
    > [From JUnit] a JUnit TestSuite instance defines one or more tests to be
    > run. For each one there is a setup step, a test step, and tear down
    > step; these are run sequentially. TestSuite implements an interface
    > Test, via which the group of tests is executed. If it is desired to
    > perform a setup and/or teardown procedure for the whole suite, then the
    > TestSuite can be decorated by a TestSetup that defines them; TestSetup
    > also implements Test and wraps a TestSuite.
    >
    > > Facade
    > > Flyweight
    > > Proxy
    > >
    > > Behavioural Patterns
    > > Chain of Responsibility
    > > Command
    > > Interpreter
    > > Mediator
    > > Memento
    > > Observer
    > > State
    > > Strategy

    >
    > Strategy:
    >
    > [From Java Collections] The Comparator interface and all its
    > implementations. The Collections and Arrays classes provide generic
    > methods by which to sort objects; the specific sort order is directed by
    > a Comparator instance. Different Comparators give you potentially
    > different sort orders.
    >
    > > Template Method

    >
    > Template Method:
    >
    > [Also from Java Collections] The AbstractCollection class defines an
    > entire Collection implementation in terms of abstract iterator() and
    > size() methods, and a stub add(Object) method. These three (especially
    > the first two) are template methods -- a concrete subclass can override
    > just those and thereby fully implement Collection in any manner desired.
    >
    > Other AbstractXXX classes among the Collection classes work similarly.
    >
    > > Visitor
    > > State Machine

    >
    >
    > John Bollinger
    >
    >
    secret, Sep 25, 2003
    #3
  4. secret

    Harald Hein Guest

    "secret" wrote:

    > I've been reading the GoF book and it clicks (at last) as I'm
    > reading it. However, I think I (and maybe many others) would
    > benefit greatly from hearing about some real world uses of the
    > patterns. What problems did they actually help solve.
    > Understanding the multitude of GUI examples in the book does not
    > help me to see applications in other areas and I fear that I
    > wouldn't recognize a relevant occasion to use some of them if I
    > came across it.


    You don't need a pattern if you don't recognize an opportunity to use a
    pattern. No joke! A common beginner's error is to look out for
    opportunities to apply patterns and then plaster a whole application
    with all kinds of patterns. Which just adds overhead and complexity.

    A pattern give you a certain flexibility in your application. If you
    don't need that flexibility, you are just adding overhead.

    First you need to have a problem at hand! If you see one in your code,
    you try to define the problem (something a lot of posters who post here
    with brain-dead "help!!! XYZ does not work!!!" posts fail to manage at
    all). Defining the problem includes listing the requiements for a
    solution. Then you search for a solution satisfying the requirements.
    While you do this, you also think about the patterns you know. Maybe
    one fixes the problem. But, every pattern comes with a price. So you
    also evaluate if you are willing to pay the price. If you are, go for
    it. If not, continue to search.

    The key to master patterns is not to apply them whenever possible. The
    key is to stay away from them when not needed.

    > Some of them are more self-explanatory than others, but real world
    > examples would be appreciated in any of them...


    Every example in the GoF book is a real-world example. In fact, every
    pattern description ends with a list of known usages. But ok, here are
    some more:

    > Abstract Factory,


    This is almost a meta-meta pattern. Instead of just having a factory
    which shields object creation from the user, one also allows to
    select/replace the factory itself. So you actually end up with a two-
    step procedure:

    1) Select factory at some point in time - maybe even hiden from you
    2) Creat specific object from the range of objects the factory
    can create

    Sometimes, step 1) is also done using a factory. So you end up with a
    three step-procedure starting with a factory creating a factory ...

    If you need this pattern, you usually need it badly. Otherwise, stay
    away from it.

    Last time I used this when I had to incooperate communication with two
    legacy systems into a new application. Both systems did the same thing,
    but with a completely different communication protocol. So the first
    step was to provide adapters for both systems to map the
    communication with both of them to a unified interfaces. The rest of
    the system only knew how to work with the unified interfaces.

    The second step was to provide two separate factories that could
    generate the adapter objects. Both factories implemented the same
    interface. The interface served as the abstract factory (I didn' use an
    abstract base class, because there was no implementation to share).

    At the start of the system a simple factory method was used to select
    the factory class, based on user input, user rights, pre-configurations
    and availability of the external systems.

    > Builder,


    I had to create an application that was supposed to create a lot of
    reports. Due to the amount of data it was not possible to store all
    data neded for the reports until the end of the application. So
    unfortunately, the reports had to be generated while the application
    ran. And it had to support a lot of different report formats.

    So the application got a reporting interface which dispatched the
    intermediate results delivered to the interface to concrete builder
    implementations for the different reporting formats. The Builders
    generated the reports on the fly as soon as they had enough data for
    their specific report format.

    > Factory Method,


    Usually used in conjunction with someting else. E.g the usage of the
    flyweight pattern described below was done using a factory method. The
    creation of a particular factory class in the abstract factory example
    was also done using a factory method.

    > Prototype,


    I sometimes see people using this pattern when they don't know it. E.g.
    when people mimic copy constructors:

    class MyClass {
    /** Initialize new object from old object **/
    public MyClass(MyClass other) {
    this.someValue = other.someValue;
    }
    }

    All it would take to make this an application of the prototype pattern
    more obvious would be some renaming:

    class MyClass {
    /** Use a prototype to initialize new object **/
    public MyClass(MyClass prototype) {
    this.someValue = prototype.someValue;
    }
    }

    This is nice, but not very poweful. So you e.g. end up with a factory
    like this:

    class MyFactory {
    public setPrototype(MyClass prototype) {
    this.prototype = prototype;
    }
    public creatMyClass() {
    return new MyClass(this.prototype);
    }
    }

    You coud do the same using cloning instead of this copy-constructor
    fakeing.

    I really don't remember when I used it this way last time. It just
    happens. I do remember that I used something similar in a constructor,
    where the default data for objects was read from a properties file.
    Instead of reading the properties file every time when a new object of
    that type was constructed I just read the data once and buffered it.
    The buffer was a "half initialized" object. But that implementation
    would more count as an application of the "first-time in" pattern:

    class MyClass {
    static MyClass default_ = null;
    public MyClass() {
    if(default_ == null) {
    // first-time in, get default data
    default_ = readDataFromPropertyFile();
    }
    this.someValue = default_.someValue;
    this.anotherValue = default_.anotherValue;
    }
    }

    > Singleton


    Overused. As a beginner, stay away from it! If you ever implement it in
    a thread-save way, DO NOT optimize it with he double-check lock
    pattern. Double-check lock can't work reliable due to Java's memory
    model,

    > Adapter,


    See my abstract factory example. In order to integrate the legacy
    systems, both interfaces to the systems need to be unified. This was
    done with a set of adapters.

    > Flyweight


    In a certain engineering program I needed thousands of objects to
    represent the data (think of a simulation). Each object had a set of
    attributes holding its configuration state and its specific data. Due
    to the nature of the application usually almost all objects had the
    same configuration state, which never changes during the application.

    Instead of having the 25 or so different configuration state variables
    in each object, each object only had one referenc to a configuration
    state object from a pool of flyweights. The state objects were
    immutable. When a new data object was created, the pool was queried for
    a state object (using a factory method). If a matching one existed the
    reference to the matching one was returned. If non existed, a new one
    was created, added to the pool and returned.

    > Visitor


    In a planning application a lot of different calculations had to be
    done on the data. And I knew from the beginning that once the
    first calculations were implemented people would ask for more. So
    instead of implementing the calculations with the data-holding objects,
    they all got a visitor interface.

    On top of that there was a simple "query engine". All this engine did
    was to (a) find the right entry into the huge pile of data (based on
    some start date, project name, etc.), (b) configured a visitor to do
    the necessary navigation inside the data (which trails to follow, end
    date, etc.), and (c) started the visitor on the first object. After
    some time the visitor returned with the right result.

    It was really fun to sit on top of this pile of data and just fire
    visitor calculation requests into it.
    Harald Hein, Sep 25, 2003
    #4
  5. secret

    Roedy Green Guest

    On Wed, 24 Sep 2003 19:26:26 GMT, "secret" <> wrote
    or quoted :

    >What problems did they
    >actually help solve.


    Have a look at pattern usage in the Java class libraries.

    see http://mindprod.com/jgloss/border.html for simple use of a
    factory.

    See JTable for Model View Controller (well not quite).

    See Iterator for Iterator.

    see http://mindprod.com/jgloss/parser.html and follow to Qiotix to see
    the visitor pattern.

    --
    Canadian Mind Products, Roedy Green.
    Coaching, problem solving, economical contract programming.
    See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
    Roedy Green, Sep 25, 2003
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Josh28
    Replies:
    0
    Views:
    449
    Josh28
    Nov 29, 2004
  2. Siz
    Replies:
    1
    Views:
    7,061
    Catherine Lowery
    Dec 12, 2004
  3. crichmon
    Replies:
    4
    Views:
    466
    Mabden
    Jul 7, 2004
  4. Tim Smith
    Replies:
    2
    Views:
    839
    Tim Smith
    Dec 15, 2004
  5. John
    Replies:
    0
    Views:
    581
Loading...

Share This Page