1 Software Components Creational Patterns. 2 Types of design patterns Design patterns can be...

Post on 01-Jan-2016

232 views 3 download

Tags:

transcript

1

Software Components

Creational Patterns

2

Types of design patterns

• Design patterns can be (roughly) grouped into three categories:

• Creational patterns– Constructing objects

• Structural patterns– Controlling the structure of a class

• Behavioral patterns– Deal with how the object behaves

Creational patterns

• Design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation

• Make a system independent of the way in which objects are created, composed and represented

4

Creational Patterns

• Patterns used to abstract the process of instantiating objects.– class-scoped patterns

• uses inheritance to choose the class to be instantiated

– Factory Method

– object-scoped patterns• uses delegation

– Abstract Factory– Builder– Prototype– Singleton

5

Factory Method• Define an interface for creating an object, but let

subclasses decide which class to instantiate.• e.g., app framework

factory method

Factory Method Pattern• Problem

– You want a type to create another related type polymorphically– E.g., a container should create appropriate begin and end iterators

• Context– Each type knows which related type it should create

• Solution core– Polymorphic creation– E.g., declare abstract method that derived classes override– E.g., provide traits and common interface as in the STL (what we’ll use)

• Consequences– Type that’s created matches type(s) it’s used with– E.g., appropriately positioned deque<Security *>::iterators are

produced by the deque<Security *> begin() and end() methods

class Book : public Product{;}

class Computer : public Product{;}

class ProductFactory{public:

virtual Product* Make(int type){

switch (type){

case 0: return new Book;()

case 1: return new Computer;()

]...[ } } }

Abstract Factory

Abstract Factory

• Intent: –Provide an interface for creating families of related or dependent objects without specifying their concrete classes

Abstract Factory

• Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

• The real-world example demonstrates the creation of different animal worlds for a computer game using different factories.

• Although the animals created by the Continent factories are different, the interactions among the animals remain the same.

Abstract Factory: An Example

• Manage addresses and phone numbers– You hard-coded it for Egypt data– At some point, you wanted to extend it

to incorporate any address / phone number

– So you subclassed• DutchAddress, JapanesePhoneNumber, etc.

– But now, how do you create them?

Abstract Factory Example

• Your company supplies a product which will be resold by several different vendors. The vendor may not want your company name and logo displayed, but instead their name and logo.

• Abstract Factory could be used to create various objects with the appropriate text and logo shown in the user interface.

Abstract Factory

Abstract Factory: Participants

• AbstractFactoryDeclares an interface for operations that create abstract products

• ConcreteFactory Implements the operations to create concrete product objects: usuallyinstantiated as a Singleton

• AbstractProductDeclares an interface for a type of product object; Concrete Factories produce the concrete products

• ConcreteProduct Defines a product object to be created by the corresponding concrete factory

Pizza Factory Example• this time more simple and easier to understand, is the

one of a pizza factory, which defines method names and returns types to make different kinds of pizza. The abstract factory can be named AbstractPizzaFactory, RomeConcretePizzaFactory and MilanConcretePizzaFactory being two extensions of the abstract class. The abstract factory will define types of toppings for pizza, like pepperoni, sausage or anchovy, and the concrete factories will implement only a set of the toppings, which are specific for the area and even if one topping is implemented in both concrete factories, the resulting pizzas will be different subclasses, each for the area it was implemented in

19

abstract class AbstractProductA}

public abstract void operationA1();

public abstract void operationA2();

{

class ProductA1 extends AbstractProductA}

ProductA1(String arg)}

System.out.println("Hello "+arg);

{ // Implement the code here

public void operationA1() } {;

public void operationA2() } {;

{

class ProductA2 extends AbstractProductA}

ProductA2(String arg)}

System.out.println("Hello "+arg);

{ // Implement the code here

public void operationA1() } {;

public void operationA2() } {;

{

abstract class AbstractProductB}

//public abstract void operationB1();

//public abstract void operationB2();

{

class ProductB1 extends AbstractProductB}

ProductB1(String arg)}

System.out.println("Hello "+arg);

{ // Implement the code here

{

class ProductB2 extends AbstractProductB}

ProductB2(String arg)}

System.out.println("Hello "+arg);

{ // Implement the code here

{

abstract class AbstractFactory}

abstract AbstractProductA createProductA();

abstract AbstractProductB createProductB();

{

class ConcreteFactory1 extends AbstractFactory}

AbstractProductA createProductA()}

return new ProductA1("ProductA1");

{

AbstractProductB createProductB()}

return new ProductB1("ProductB1");

{

{

class ConcreteFactory2 extends AbstractFactory}

AbstractProductA createProductA()}

return new ProductA2("ProductA2");

{

AbstractProductB createProductB()}

return new ProductB2("ProductB2");

{

{

//Factory creator - an indirect way of instantiating the factories

class FactoryMaker}

private static AbstractFactory pf=null;

static AbstractFactory getFactory(String choice)}

if(choice.equals("a"))}

pf=new ConcreteFactory1();

{else if(choice.equals("b"))}

pf=new ConcreteFactory2();

{ return pf;

{

{

// Client

public class Client}

public static void main(String args][)}

AbstractFactory pf=FactoryMaker.getFactory("a");

AbstractProductA product=pf.createProductA();

//more function calls on product

{

{

ConsequencesConsequences

1. Concrete class isolation (Good)• Client does not interact with the

implementation classes• Client only manipulates instances through

the abstract interfaces

ConsequencesConsequences

2. Product families easily exchanged (Good)

• Only have to change the concrete factory• Can be done at run time

ConsequencesConsequences

3. Products are more consistent (Good)• Helps the products in each product family

consistently be applied together (assuming they work well together)

• Only one family at a time

ConsequencesConsequences

4. Difficult to support new kinds of products (Bad)

• Extending existing abstract factories to make new products is difficult and time consuming

• The family of products available is fixed by Abstract Factory interface

BuilderBuilder

BuilderBuilder

• Intent–Separate the construction of a

complex object from its representation so that the same construction process can create different representations

34

Builder: Collaborations

• Client creates Director object and configures it with a Builder

• Director notifies Builder to build each part of the product (as it interprets the external format)

• Builder handles requests from Director and adds parts to the product

• Client retrieves product from the Builder

Builder: Applicability

• Use Builder when:– The algorithm for creating a complex object

should be independent of the parts that make up the object and how they’re assembled

– The construction process must allow different representations for the object being constructed

– The building process can be broken down into discrete steps (difference between Builder and Abstract Factory)

Builder: Participants• Builder

Specifies an abstract interface for creating parts of a Product object

• ConcreteBuilder Constructs and assembles parts of the product by implementing the Builder interface

• DirectorConstructs an object using the Builder interface

• Product Represents the complex object under construction

Includes classes that define the constituent parts

Gives interfaces for assem-bling the parts

41

Implementation IssuesImplementation Issues

• Builder needs a very general interface

• Builder(s) may need access to a variety of components

• No abstract product class (products are too different, commonly)

ConsequencesConsequences

1. Varying a product’s internal representation (Good)

• The Director doesn’t see the product’s construction, only the Builder does

ConsequencesConsequences

2. Isolates code for construction and representation (Good)

• The Client only retrieves the product• The Client doesn’t know anything about the

internal construction of the product• Question: Multiple directors?

ConsequencesConsequences

3. Step by step construction (Good?)• The Client only retrieves the product• The Client doesn’t know anything about the

internal construction of the product• Question: Multiple directors?

Singleton

Singleton

• Do we need to limit the no of objects of a class

47

48

Singleton

• Intent: – Ensure that a class only has one instance, and

provide a global point of access to it

• Applicability: – There must be exactly one instance of a class,

and it must be accessible to clients from a well-known access point

– When the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code

50

Singleton

Singleton Pattern• Problem

– Want to ensure a single instance of a class, that’s shared by all uses throughout a program (e.g., the Portfolio)

• Context– Need to address initialization versus usage ordering

• Solution core– Provide a global access method (static member function)– First use of the access method instantiates the class– Constructors for instance can be hidden (made private)– Can hide destructor too if a “fini” method is also provided

• Consequences– Object is never created if it’s never used– Object is shared efficiently among all uses

• Intent– Specify the kinds of objects to create using a

prototypical instance, and create new objects by copying this prototype

• Applicability– System must be independent of how products are

created, composed, and represented (usually true of Creational patterns)

AND– Classes to instantiate are specified at run-time– To avoid building a class hierarchy of factories for

a class hierarchy of products– Instances of classes have only a few different

combinations of state

• Structure

• Participants– Prototype – declares an interface for cloning

itself– ConcretePrototype – implements an operation

for cloning itself– Client – creates a new object by asking a

prototype for a clone of itself

Prototype Pattern• Problem

– Need to duplicate objects with different dynamic types

• Context– Virtual constructors are not available (e.g., in C++)– However, polymorphic method invocations are supported

• Solution core– Provide a polymorphic method that returns an instance of

the same type as the object on which the method is called– Polymorphic method calls copy constructor, returns base

class pointer or reference to concrete derived type

• Consequences– Emulates virtual copy construction behavior– Allows anonymous duplication of heterogeneous types

Example

Maze Game

58

Maze example

• Building a maze for a computer game

• A maze is a set of rooms• A room knows its neighbours

– Another room– A wall– A door

59

Maze classes

Creating Mazespublic class MazeGame{ public static void main(String args[]) {

Maze m = new MazeGame().createMaze(); }

public Maze createMaze() { Room r1 = new Room(1); Room r2 = new Room(2); Door d = new Door(r1,r2); r1.setSide(Direction.North, new Wall()); r1.setSide(Direction.East, d); r1.setSide(Direction.West, new Wall()); r1.setSide(Direction.South, new Wall()); r2.setSide(Direction.North, new Wall()); r2.setSide(Direction.West, d); r2.setSide(Direction.East, new Wall()); r2.setSide(Direction.South, new Wall()); Maze m = new Maze(); m.addRoom(r1); m.addRoom(r2); return m; }}

r1 r2

d

61

Creational Patterns• If createMaze() calls virtuals to construct components

– Factory Method

• If createMaze() is passed a parameter object to create rooms, walls, – Abstract Factory

• If createMaze() is passed a parameter object to create and connect-up mazes– Builder

• If createMaze is parameterized with various prototypical rooms, doors, walls, … which it copies and then adds to the maze– Prototype

• Need to ensure there is only one maze per game, and everybody can access it, and can extend or replace the maze without touching other code.– Singleton

Potential PatternsPotential Patterns

• Virtual functions instead of constructors for– Rooms– Doors– Walls

• Make a subclass of MazeGame to redefine these functions

• Factory Method

Potential PatternsPotential Patterns

• CreateMaze is passed an object as a parameter, which is used to change the classes used to make– Rooms– Doors– Walls

• Abstract Factory

Potential PatternsPotential Patterns

• CreateMaze is passed an object that can create a maze all by itself, then you can use inheritance to change parts of the maze:– Rooms– Doors– Walls

• Builder

Potential PatternsPotential Patterns

• CreateMaze is parameterized by various prototypical:– Rooms– Doors– Walls

• You can replace these prototypical objects with different ones to change the maze

• Prototype