CS 635 Advanced Object-Oriented Design & Programming Spring Semester, 2001 Factory Method & Prototype |
||
---|---|---|
© 2001, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 07-Mar-01 |
Factory Method
A template method for creating objects
Example - Maze Game
Classes for Mazes
Now a maze game has to make a maze
Maze Class Version 1 class MazeGame { public Maze createMaze() { Maze aMaze = new Maze(); Room r1 = new Room( 1 ); Room r2 = new Room( 2 ); Door theDoor = new Door( r1, r2); aMaze.addRoom( r1 ); aMaze.addRoom( r2 ); etc. return aMaze; } }
How do we make other Mazes?
Subclass MazeGame, override createMaze
class BombedMazeGame extends MazeGame { public Maze createMaze() { Maze aMaze = new Maze(); Room r1 = new RoomWithABomb( 1 ); Room r2 = new RoomWithABomb( 2 ); Door theDoor = new Door( r1, r2); aMaze.addRoom( r1 ); aMaze.addRoom( r2 ); etc.
Note the amount of cut and paste!
How do we make other Mazes?
Use Factory Method
class MazeGame { public Maze makeMaze() { return new Maze(); } public Room makeRoom(int n ) { return new Room( n ); } public Wall makeWall() { return new Wall(); } public Door makeDoor() { return new Door(); } public Maze CreateMaze() { Maze aMaze = makeMaze(); Room r1 = makeRoom( 1 ); Room r2 = makeRoom( 2 ); Door theDoor = makeDoor( r1, r2); aMaze.addRoom( r1 ); aMaze.addRoom( r2 ); etc return aMaze; } }
Now subclass MazeGame override make methods
CreateMaze method stays the same
class BombedMazeGame extends MazeGame { public Room makeRoom(int n ) { return new RoomWithABomb( n ); } public Wall makeWall() { return new BombedWall(); }
Applicability
Use when
Consequences
Implementation
Two Major Varieties
abstract class MazeGame { public Maze makeMaze(); public Room makeRoom(int n ); public Wall makeWall(); public Door makeDoor(); etc. } class MazeGame { public: virtual Maze* makeMaze() = 0; virtual Room* makeRoom(int n ) = 0; virtual Wall* makeWall() = 0; virtual Door* makeDoor() = 0;
Implementation - Continued Parameterized Factory Methods
Let the factory method return multiple products
class Hershey { public Candy makeChocolateStuff( CandyType id ) { if ( id == MarsBars ) return new MarsBars(); if ( id == M&Ms ) return new M&Ms(); if ( id == SpecialRich ) return new SpecialRich(); return new PureChocolate(); }
class GenericBrand extends Hershey { public Candy makeChocolateStuff( CandyType id ) { if ( id == M&Ms ) return new Flupps(); if ( id == Milk ) return new MilkChocolate(); return super.makeChocolateStuff(); } }
C++ Templates to Avoid Subclassing
template <class ChocolateType> class Hershey { public: virtual Candy* makeChocolateStuff( ); } template <class ChocolateType> Candy* Hershey<ChocolateType>::makeChocolateStuff( ) { return new ChocolateType; } Hershey<SpecialRich> theBest;
Java forName and Factory methods
With Java's reflection you can use a Class or a String to specify which type of object to create
Using a string replaces compile checks with runtime errors
class Hershey { private String chocolateType; public Hershey( String chocolate ) { chocolateType = chocolate; } public Candy makeChocolateStuff( ) { Class candyClass = Class.forName( chocolateType ); return (Candy) candyClass.newInstance(); } Hershey theBest = new Heshsey( "SpecialRich" );
Clients Can Use Factory Methods
class CandyStore { Hershey supplier; public restock() { blah if ( chocolateStock.amount() < 10 ) { chocolateStock.add( supplier.makeChocolateStuff() ); } blah
Prototype
Intent
Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype
Applicability
Use the Prototype pattern when
Implementation/Sample Code
Simple Example
class Prototype { public Prototype clone() { code to make a copy of current Prototype object return clone; } // add what ever else you want the class to do } class Protoplasm extends Prototype { public Prototype clone() { code to make a copy of current Protoplasm object return clone; } // add more other stuff } ClientCodeMethod( Prototype example ) { Prototype myCopy = example.clone(); // do some work using myCopy }
Cloning Issues
How to in C++ - Copy Constructors class Door { public: Door(); Door( const Door&); virtual Door* clone() const; virtual void Initialize( Room*, Room* ); // stuff not shown private: Room* room1; Room* room2; } Door::Door ( const Door& other ) //Copy constructor { room1 = other.room1; room2 = other.room2; } Door* Door::clone() const { return new Door( *this ); }
How to in Java - Object clone()
protected Object clone() throws CloneNotSupportedException
class Door implements Cloneable { public void Initialize( Room a, Room b) { room1 = a; room2 = b; } public Object clone() throws CloneNotSupportedException { return super.clone(); } Room room1; Room room2; }
Shallow Copy Verse Deep Copy
Original Objects
Shallow Copy
Shallow Copy Verse Deep Copy
Original Objects
Deep Copy
Template or Boilerplate Objects
May wish to specify how an object differs from a standard configuration
Example: Insurance policy
Consequences