Home

About Me

Documents and Papers

Architectures

Design Patterns
Creational
Behavioral
Structural

Abstract Factory Creational Design Pattern

 

Previous page: Factory Pattern

Next page: Singleton Pattern

Name: Abstract Factory - Creational Design Pattern

Motivation:
Provide an interface for creating families of related or dependant objects without specifying their concrete classes. For instance if one wishes to offer multiple "looks" and "feels" to a product, but the product should not know which motif it is using. This would then allow for the motif to be easily altered at run-time. It should also be used "when a system should be independent of how its products are created, composed, and represented." (p. 88) [4]. Furthermore it aids in grouping related families of products, as we will show in the example below - and beyond grouping it can also enforce that these products are only used in their intended groups. The pattern also supports the principle of information hiding since the client is only offered / knows about the interface, the client does not know anything about the actual data structure of a concrete product, and additionally does not know which concrete product it is dealing with at any given time..

Applicability: TBA

Participants: 

The IPresentationFactory interface is implemented by the concrete factories. It defines the operations that they must implement when creating their "products". In our case we are creating various looks and feels for the UI of mobile devices. Thus the interface must define factory operations that are relevant to a UI.

The concrete factories are in our case LargeDeviceFactory and SmallScreenDeviceFactory. They both implement the interface IPresentationFactory.

The abstract classes Box and Button are our two products, (naturally in a real-life scenario one would have far more UI elements than just a Box and a Button). The factories LargeDeviceFactory and SmallScreenDeviceFactory produce their separate versions of these two products.

These versions of the products exist in the form of the classes SymbianBtn and SymbianMsg (those are manufactured by the LargeDeviceFactory), whilst the products created by SmallScreenDeviceFactory are called MiniBtn and MiniMsg.

The Client class is the consumer in our little example - actually this consumer isn't a very fussy one at all, he doesn't really care to know what sort of products he receives he just knows he wants a button class and a message class that he can perform a set of pre-defined operations on. The client goes off to the factory and receives a message (box) object and a button object, he doesnt know what sort they are - he only knows the interfaces they implement and thus the operations they provide.


Sample Code:

//this is the IPresentationFactory interface - implemented by the concrete
//factories
public interface IPresentationFactory
{
  public Button CreateButtons();
  public Box CreateMessageBoxes();
}

//the two concrete factories follow
public class LargeDeviceFactory implements IPresentationFactory
{
  public Button CreateButtons()
  { return new SymbianBtn(); }
  public Box CreateMessageBoxes()
  { return new SymbianMsg(); }
}

public class SmallScreenDeviceFactory implements IPresentationFactory
{
  public Button CreateButtons()
  {return new MiniBtn(); }
  public Box CreateMessageBoxes()
  {return new MiniMsg();}
}

//below are the two abstract product classes
public abstract class Box
{
  public abstract void setButton(Button btn);
  public void showBox() {;}
}

public abstract class Button
{
  private String text = "";
  public void SetText(String txt)
  {text = txt;}
}

//the concrete product classes are as follows; MiniMsg, MiniBtn,
//SymbianBtn and SymbianMsg
// - these represent the products
//produced at the two concrete factories
public class MiniBtn extends Button { }

public class MiniMsg extends Box
{
  public void setButton(Button btn)
  {
    System.out.println(" a button of type " + btn.getClass().getSimpleName() + " was added to my MiniMsg");
  }
}

public class SymbianBtn extends Button { }

public class SymbianMsg extends Box
{
  public void setButton(Button btn)
  {
    System.out.println(" a button of type " + btn.getClass().getSimpleName() + " was added to my SymbianMsg");
  }
}

//the next class is the Client class - our not so fussy shopper(!) 
public class Client
{
  private Box box;
  private Button button;

  public Client(IPresentationFactory factory)
  {
    box = factory.CreateMessageBoxes();
    button = factory.CreateButtons();
  }

  public void AddButtonToMessage()
  { box.setButton(button); }
}

//the final "class" is just a Main method initiating the client
//(e.g. telling him which factory to go to -
//but the Client does not care to know the details) 
Main()
{
  Client client = new Client(new SmallScreenDeviceFactory());     
  client.AddButtonToMessage();
  client = new Client(new LargeDeviceFactory());
  client.AddButtonToMessage();
}

OUTPUT

a button of type MiniBtn was added to my MiniMsg

a button of type SymbianBtn was added to my SymbianMsg

Known uses and consequences:
The scenarios are outlined above in the first section "Motivation", the consequences of using the pattern as outlined by the GoF (p.89) are on the positive side that "it isolates concrete classes... Because a factory encapsulate the responsibility and the process of creating product objects, it isolates clients from implementation classes". They also point out that "it makes exchanging product families easy" - this is due to the shared interface and the fact that a concrete factory is only created once, making it easy to exchange. A third benefit is that "it promotes consistency among products" - once again this is due to the shared interface of the AbstractFactory. On a negative sidenote the use of this pattern also reduces the extendability of the solution, since if one wishes to add a new product to the factory one would have to alter both the interface IPresentationFactory and add a new abstract class which would have to be created for all existing families.

Related Patterns:
There are other related patterns, such as factory and reflective factory that can be used instead. GoF indentify that the Singleton pattern could be used in connection with this pattern, since on would in most cases only wish to create one instance of each factory type.

 

This site is W3C CSS Validated copyright Paul Austrem (c) 2007This site is W3C XHTML 1.0 Transitional Validated