CSC/ECE 517 Fall 2012/ch2b 2w57

From Expertiza_Wiki
Revision as of 03:06, 20 November 2012 by Ssivaku4 (talk | contribs) (→‎C#)
Jump to navigation Jump to search

Abstract Factory: A directory of sites

The objective of this wiki is to provide a directory of sites that one would refer to while learning about the Abstract Factory pattern. Therefore, in this wiki, we will be giving an overview of the different features of the Abstract Factory pattern along with links to useful websites that explain each of these features in more detail.


Introduction

The abstract factory pattern is a software creational design pattern that provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes. In normal usage, the client software creates a concrete implementation of the abstract factory and then uses the generic interfaces to create the concrete objects that are part of the theme. The client does not know (or care) which concrete objects it gets from each of these internal factories, since it uses only the generic interfaces of their products. This pattern separates the details of implementation of a set of objects from their general usage and relies on object composition, as object creation is implemented in methods exposed in the factory interface.

The essence of the Abstract Factory Pattern is to "Provide an interface for creating families of related or dependent objects without specifying their concrete classes".

Motivation

Modularization is a big issue in today's programming. Programmers all over the world are trying to avoid the idea of adding code to existing classes in order to make them support encapsulating more general information. Take the case of a information manager which manages phone number. Phone numbers have a particular rule on which they get generated depending on areas and countries. If at some point the application should be changed in order to support adding numbers form a new country, the code of the application would have to be changed and it would become more and more complicated.

In order to prevent it, the Abstract Factory design pattern is used. Using this pattern a framework is defined, which produces objects that follow a general pattern and at runtime this factory is paired with any concrete factory to produce objects that follow the pattern of a certain country. In other words, the Abstract Factory is a super-factory which creates other factories (Factory of factories).

Usage

The factory determines the actual concrete type of object to be created, and it is here that the object is actually created (in C++, for instance, by the new operator). However, the factory only returns an abstract pointer to the created concrete object. This insulates client code from object creation by having clients ask a factory object to create an object of the desired abstract type and to return an abstract pointer to the object. As the factory only returns an abstract pointer, the client code (that requested the object from the factory) does not know – and is not burdened by – the actual concrete type of the object that was just created. However, the type of a concrete object (and hence a concrete factory) is known by the abstract factory; for instance, the factory may read it from a configuration file. The client has no need to specify the type, since it has already been specified in the configuration file. In particular, this means:

  • The client code has no knowledge whatsoever of the concrete type, not needing to include any header files or class declarations related to it. The client code deals only with the abstract type. Objects of a concrete type are indeed created by the factory, but the client code accesses such objects only through their abstract interface.
  • Adding new concrete types is done by modifying the client code to use a different factory, a modification that is typically one line in one file. (The different factory then creates objects of a different concrete type, but still returns a pointer of the same abstract type as before – thus insulating the client code from change.) This is significantly easier than modifying the client code to instantiate a new type, which would require changing every location in the code where a new object is created (as well as making sure that all such code locations also have knowledge of the new concrete type, by including for instance a concrete class header file). If all factory objects are stored globally in a singleton object, and all client code goes through the singleton to access the proper factory for object creation, then changing factories is as easy as changing the singleton object.

Structure

UML Diagram

The following diagram shows the UML representation of the Abstract Factory.


The following sites show more UML diagrams with explanantions:

http://www.codeproject.com/Articles/331304/Understanding-and-Implementing-Abstract-Factory-Pa

http://apwebco.com/gofpatterns/creational/AbstractFactory.html

Examples

In this section, we show implementation examples of the Abstract Factory in different languages. The output of each should be either "I'm a WinButton" or "I'm an OSXButton" depending on which kind of factory was used. Note that the Application has no idea what kind of GUIFactory it is given or even what kind of Button that factory creates. This same code can be found at http://en.wikipedia.org/wiki/Abstract_factory_pattern#Example

C++

/* GUIFactory example */

#include <iostream>

class Button {
public:
    virtual void paint() = 0;
    virtual ~Button() { }
};

class WinButton : public Button {
public:
    void paint() {
        std::cout << "I'm a WinButton";
    }
};

class OSXButton : public Button {
public:
    void paint() {
        std::cout << "I'm an OSXButton";
    }
};

class GUIFactory {
public:
    virtual Button* createButton() = 0;
    virtual ~GUIFactory() { }
};

class WinFactory : public GUIFactory {
public:
    Button* createButton() {
        return new WinButton();
    }

    ~WinFactory() { }
};

class OSXFactory : public GUIFactory {
public:
    Button* createButton() {
        return new OSXButton();
    }
         
    ~OSXFactory() { }
};

class Application {
public:
    Application(GUIFactory* factory) {
        Button* button = factory->createButton();
        button->paint();
        delete button;
        delete factory;
    }
};

GUIFactory* createOsSpecificFactory() {
    int sys;
    std::cout "\nEnter OS type (0: Windows, 1: MacOS X): ";
    std::cin >> sys;

    if (sys == 0) {
        return new WinFactory();
    } else {
        return new OSXFactory();
    }
}

int main() {
    Application application(createOsSpecificFactory());
}

C#

/* GUIFactory example -- */

using System;
using System.Configuration;

namespace AbstractFactory 
{
    public interface IButton 
    {
        void Paint();
    }

    public interface IGUIFactory 
    {
        IButton CreateButton();
    }

    public class OSXButton : IButton // Executes fourth if OS:OSX
    {
        public void Paint() 
        {
            System.Console.WriteLine("I'm an OSXButton");
        }
    }

    public class WinButton : IButton // Executes fourth if OS:WIN
    {
        public void Paint() 
        {
            System.Console.WriteLine("I'm a WinButton");
        }
    }

    public class OSXFactory : IGUIFactory // Executes third if OS:OSX
    {
        IButton IGUIFactory.CreateButton() 
        {
            return new OSXButton();
        }
    }

    public class WinFactory : IGUIFactory // Executes third if OS:WIN
    {
        IButton IGUIFactory.CreateButton() 
        {
            return new WinButton();
        }
    }

    public class Application 
    {
        public Application(IGUIFactory factory) 
        {
            IButton button = factory.CreateButton();
            button.Paint();
        }
    }

    public class ApplicationRunner 
    {
        static IGUIFactory CreateOsSpecificFactory()  // Executes second
        {
            // Contents of App{{Not a typo|.}}Config associated with this C# project
            //<?xml version="1.0" encoding="utf-8" ?>
            //<configuration>
            //  <appSettings>
            //    <!-- Uncomment either Win or OSX OS_TYPE to test -->
            //    <add key="OS_TYPE" value="Win" />
            //    <!-- <add key="OS_TYPE" value="OSX" /> -->
            //  </appSettings>
            //</configuration>
            string sysType = ConfigurationSettings.AppSettings["OS_TYPE"];
            if (sysType == "Win") 
            {
                return new WinFactory();
            } 
            else 
            {
                return new OSXFactory();
            }
        }

        static void Main(string[] args) // Executes first
        {
            new Application(CreateOsSpecificFactory());
            Console.ReadLine();
        }
    }
}

Comparison with other patterns

Factory Pattern

The Factory Method Pattern is an object-oriented creational design pattern to implement the concept of factories and deals with the problem of creating objects (products) without specifying the exact class of object that will be created. The essence of this pattern is to "Define an interface for creating an object, but let the classes that implement the interface decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.

Also known as Virtual Constructor, the Factory Method is related to the idea on which libraries work: a library uses abstract classes for defining and maintaining relations between objects. One type of responsibility is creating such objects. The library knows when an object needs to be created, but not what kind of object it should create, this being specific to the application using the library. The Factory method works just the same way: it defines an interface for creating an object, but leaves the choice of its type to the subclasses, creation being deferred at run-time.

The main difference between a "factory method" and an "abstract factory" is that the factory method is a single method, and an abstract factory is an object. The following websites further explain the difference between Abstract Factory and Factory Method in detail.

http://stackoverflow.com/questions/5739611/differences-between-abstract-factory-pattern-and-factory-method

http://stackoverflow.com/questions/1001767/what-is-the-basic-difference-between-factory-and-abstract-factory-patterns

http://www.codeproject.com/Articles/35789/Understanding-Factory-Method-and-Abstract-Factory

http://www.dofactory.com/topic/1284/abstract-factory-vs-factory-method.aspx

http://stackoverflow.com/questions/4209791/design-patterns-abstract-factory-vs-factory-method

Bridge Pattern

The bridge pattern is a design pattern used in software engineering which is meant to "decouple an abstraction from its implementation so that the two can vary independently". The bridge uses encapsulation, aggregation, and can use inheritance to separate responsibilities into different classes.

The motivation behind the Bridge Pattern is that sometimes an abstraction may need to have different implementations: Consider an object that handles persistence of objects over different platforms using either relational databases or file system structures (files and folders). A simple implementation might choose to extend the object itself to implement the functionality for both file system and RDBMS. However this implementation would create a problem: Inheritance binds an implementation to the abstraction and thus it would be difficult to modify, extend, and reuse abstraction and implementation independently.

An Abstract Factory pattern can be used create and configure a particular Bridge, for example a factory can choose the suitable concrete implementor at runtime.

The difference between Abstract Factory and Bridge is further explained in the following sites.

http://wgao.blogspot.com/2004/11/bridge-pattern-and-abstract-factory.html

http://stackoverflow.com/questions/7700854/abstractfactory-versus-bridge-pattern

http://www.felix-colibri.com/papers/design_patterns/factory_and_bridge_patterns/factory_and_bridge_patterns.html

Builder Pattern

The builder pattern is an object creation software design pattern. The intention is to abstract steps of construction of objects so that different implementations of these steps can construct different representations of objects. Often, the builder pattern is used to build products in accordance with the composite pattern.

The motivation behind the builder pattern is that the complexity of classes and objects which increases as the complexity of the application increases. Complex objects are made of parts produced by other objects that need special care when being built. An application might need a mechanism for building complex objects that is independent from the ones that make up the object.

The builder pattern allows a client object to construct a complex object by specifying only its type and content, being shielded from the details related to the object's representation. This way the construction process can be used to create different representations. The logic of this process is isolated form the actual steps used in creating the complex object, so the process can be used again to create a different object form the same set of simple objects as the first one.

The main difference between Abstract Factory and Builder is that in the case of the Abstract Factory, the client uses the factory's methods to create its own objects whereas in the Builder's case, the Builder class is instructed on how to create the object and then it is asked for it, but the way that the class is put together is up to the Builder class

The difference between Builder pattern and the Abstract Factory pattern is explained in detail in the following sites.

https://sites.google.com/site/sureshdevang/abstract-factory-vs-builder-design-patterns

http://stackoverflow.com/questions/3687299/abstract-factory-factory-method-builder

http://www.oodesign.com/builder-pattern.html

Strategy Pattern

The strategy pattern (also known as the policy pattern) is a particular software design pattern, whereby algorithms behaviour can be selected at runtime. Formally speaking, the strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

The motivation behind the Strategy Pattern is that there are situations when classes differ only in their behavior. In such cases, it is a good idea to isolate the algorithms in separate classes in order to have the ability to select different algorithms at runtime.

The main difference between Abstract Factory and Strategy is that Abstract Factory is a creational pattern whereas Strategy is a behavioral pattern.

http://stackoverflow.com/questions/4926278/what-the-diffrence-between-strategy-design-pattern-and-abstract-factory-pattern

http://geekswithblogs.net/SanjayU/archive/2009/04/15/another-abstract-factory-amp-strategy-pattern-explanation.aspx


Prototype Pattern

The prototype pattern is a creational design pattern used in software development when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects. The motivation behind this pattern is to:

  • avoid subclasses of an object creator in the client application, like the abstract factory pattern does.
  • avoid the inherent cost of creating a new object in the standard way (e.g., using the 'new' keyword) when it is prohibitively expensive for a given application.

Abstract Factory classes are often implemented with Factory Methods, but they can be implemented using Prototype. This concept is further explained in the following sites.

http://stackoverflow.com/questions/5739240/questions-about-the-prototype-pattern

http://www.oodesign.com/prototype-pattern.html

http://sourcemaking.com/design_patterns/prototype

References

  • ^ [|Gamma, Erich[1]]; Richard Helm, Ralph Johnson, John M. Vlissides (2009-10-23). "Design Patterns: Abstract Factory". informIT. Archived from the original on 2009-10-23. Retrieved 2012-05-16. "Object Creational: Abstract Factory: Intent: Provide an interface for creating families of related or dependent objects without specifying their concrete classes."
  • a b Freeman, Eric; Freeman, Elisabeth; Kathy, Sierra; Bert, Bates (2004). Hendrickson, Mike. ed (paperback). Head First Design Patterns. 1. O'REILLY. p. 156. ISBN 978-0-596-00712-6. Retrieved 2012-09-12.