![]() |
CS 635: Advanced Object-Oriented Design & Programming |
|---|
| Reference | slide # 1 |
| Factory Method | slide # 2 |
| ......Maze Class Version 1 | slide # 3 |
| ...Implementation | slide # 7 |
| ......Parameterized Factory Methods | slide # 8 |
| ......C++ Templates to Avoid Subclassing | slide # 8 |
| ......Java forName and Factory methods | slide # 9 |
| ......Clients Can Use Factory Methods | slide # 10 |
| Prototype | slide # 12 |
| ...Intent | slide # 12 |
| ...Applicability | slide # 12 |
| ...Implementation/Sample Code | slide # 13 |
| ...Cloning Issues | slide # 14 |
| ......How to in C++ - Copy Constructors | slide # 14 |
| ......How to in Java - Object clone() | slide # 15 |
| ......Shallow Copy Verse Deep Copy | slide # 16 |
| ...Example of Prototype | slide # 18 |
| ...Consequences | slide # 27 |
| ...Implementation Issues | slide # 27 |
| Abstract Factory | slide # 28 |
| ...How Do Factories create Widgets | slide # 32 |
| ......Method 2) Their Factory Method | slide # 33 |
| ......Method 3) Prototype | slide # 35 |
| ...Applicability | slide # 36 |
| ...Consequences | slide # 36 |

Now a maze game has to make a maze, so we might have something like:
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 );
r1.setSide( North, new Wall() );
r1.setSide( East, theDoor );
r1.setSide( South, new Wall() );
r1.setSide( West, new Wall() );
r2.setSide( North, new Wall() );
r2.setSide( East, new Wall() );
r2.setSide( South, new Wall() );
r2.setSide( West, theDoor );
return aMaze;
}
}

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 );
r1.setSide( North, new BombedWall() );
r1.setSide( East, theDoor );
r1.setSide( South, new BombedWall() );
r1.setSide( West, new BombedWall() );
Note the amount of cut and paste!
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 );
r1.setSide( North, makeWall() );
r1.setSide( East, theDoor );
r1.setSide( South, makeWall() );
r1.setSide( West, makeWall() );
r2.setSide( North, makeWall() );
r2.setSide( East, makeWall() );
r2.setSide( South, makeWall() );
r2.setSide( West, theDoor );
return aMaze;
}
}
CreateMaze method stays the same
class BombedMazeGame extends MazeGame
{
public Room makeRoom(int n )
{
return new RoomWithABomb( n );
}
public Wall makeWall()
{
return new BombedWall();
}
abstract class MazeGame
{
public Maze makeMaze();
public Room makeRoom(int n );
public Wall makeWall();
public Door makeDoor();
class MazeGame
{
public:
virtual Maze* makeMaze() = 0;
virtual Room* makeRoom(int n ) = 0;
virtual Wall* makeWall() = 0;
virtual Door* makeDoor() = 0;
"Create objects in a separate operation so that subclasses can override the way they're created"
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();
}
template <class ChocolateType>
class Hershey
{
public:
virtual Candy* makeChocolateStuff( );
}
template <class ChocolateType>
Candy* Hershey<ChocolateType>::makeChocolateStuff( )
{
return new ChocolateType;
}
Hershey<SpecialRich> theBest;
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" );
class CandyStore
{
Hershey supplier;
public restock()
{
blah
if ( chocolateStock.amount() < 10 )
{
chocolateStock.add(
supplier.makeChocolateStuff() );
}
blah
class Room extends MapSite
{
public Room makeRoom() { return new Room(); }
etc,
}
class RoomWithBomb extends Room
{
public Room makeRoom() { return new RoomWithBomb(); }
etc,
}
etc.
class MazeGame
{
public Room roomMaker;
etc.
public MazeGame( Room rfactory )
{
roomMaker = rfactory;
}
public Maze CreateMaze()
{
Maze aMaze = new Maze();
Room r1 = roomMaker.makeRoom( 1 );
etc.
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
}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 );
}
Creates a clone of the object. A new instance is allocated and a bitwise clone of the current object is place in the new object.
Returns:
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;
}




JavaServer handles the network connection.
Algorithm:
class JavaServer
{
ServerSocket acceptor;
public JavaServer( int portNumber )
{
acceptor = new ServerSocket( portNumber );
}
public void run()
{
while (true)
{
Socket client = acceptor.accept();
InputStream cin = client.getInputStream();
OutputStream cout = client.getOutputStream();
processClientRequest( cin, cout );
}
}
private void processClientRequest( InputStream cin,
OutputStream cout )
{
DateServer handler = new DateServer( cin, cout);
handler.processClientRequest();
}
}
class AirlineReservationJavaServer extends JavaServer
{
public AirlineReservationServer( int portNumber )
{
super( portNumber );
}
private void processClientRequest( InputStream cin,
OutputStream cout )
AirlineReservation handler;
handler = new AirlineReservation( cin, cout );
handler.processClientRequest();
}
}
Declare variables to be instances of the abstract class not instances of particular classes
interface ServerEngine
{
public void processClientRequest(InputStream in,
OutputStream out);
}

abstract class JavaServer
{
ServerSocket acceptor;
public JavaServer( int portNumber )
{
acceptor = new ServerSocket( portNumber );
}
public void run()
{
while (true)
{
Socket client = acceptor.accept();
InputStream cin = client.getInputStream();
OutputStream cout = client.getOutputStream();
ServerEngine requestHandler =
makeServerEngine();
requestHandler.processClientRequest( cin, cout );
}
}
abstract protected ServerEngine makeServerEngine();
}
class AirlineReservationJavaServer extends JavaServer
{
public AirlineReservationServer( int portNumber )
{
super( portNumber );
}
protected ServerEngine makeServerEngine()
{
return new AirlineReservation( );
}
}
class AirlineReservation implements ServerEngine
{
public void processClientRequest(InputStream in,
OutputStream out)
{
blah
}
etc.
}
interface ServerEngine
{
public ServerEngine clone( InputStream in,
OutputStream out );
public void processClientRequest();
}
class JavaServer
{
ServerSocket acceptor;
ServerEngine serverPrototype;
public JavaServer( int portNumber, ServerEngine aCopy)
{
acceptor = new ServerSocket( portNumber );
serverPrototype = aCopy;
}
public void run() {
while (true)
{
Socket client = acceptor.accept();
InputStream cin = client.getInputStream();
OutputStream cout = client.getOutputStream();
ServerEngine requestHandler =
serverPrototype.clone( cin, cout);
requestHandler.processClientRequest( cin, cout );
}
}
}
Driver Programclass DriverProgram
{
public static void main( String args[] )
{
ServerEngine aPrototype = new DateServer();
JavaServer networkListener;
networkListener = new JavaServer( 6666, aPrototype );
networkListener.run();
}
}
We will look at widgets: Windows, Menu's and Buttons
Create an interface( or abstract class) for each widget and an concrete class for each platform:

public void installDisneyMenu()
{
Menu disney = create a menu somehow
disney.addItem( "Disney World" );
disney.addItem( "Donald Duck" );
disney.addItem( "Mickey Mouse" );
disney.addGrayBar( );
disney.addItem( "Minnie Mouse" );
disney.addItem( "Pluto" );
etc.
}How to create the widget?
abstract class WidgetFactory
{
public Window createWindow();
public Menu createMenu();
public Button createButton();
}
class MacWidgetFactory extends WidgetFactory
{
public Window createWindow()
{ code to create a mac window }
public Menu createMenu()
{ code to create a mac Menu }
public Button createButton()
{ code to create a mac button }
}
class Win95WidgetFactory extends WidgetFactory
{
public Window createWindow()
{ code to create a Win95 window }
public Menu createMenu()
{ code to create a Win95 Menu }
public Button createButton()
{ code to create a Win95 button }
}
Etc.public void installDisneyMenu(WidgetFactory myFactory)
{
Menu disney = myFactory.createMenu();
disney.addItem( "Disney World" );
disney.addItem( "Donald Duck" );
disney.addItem( "Mickey Mouse" );
disney.addGrayBar( );
disney.addItem( "Minnie Mouse" );
disney.addItem( "Pluto" );
etc.
}
abstract class WidgetFactory
{
public Window createWindow();
public Menu createMenu();
public Button createButton();
}
class MacWidgetFactory extends WidgetFactory
{
public Window createWindow()
{ return new MacWidow() }
public Menu createMenu()
{ return new MacMenu() }
public Button createButton()
{ return new MacButton() }
}
abstract class WidgetFactory
{
private Window windowFactory;
private Menu menuFactory;
private Button buttonFactory;
public Window createWindow()
{ return windowFactory.createWindow() }
public Menu createMenu();
{ return menuFactory.createWindow() }
public Button createButton()
{ return buttonFactory.createWindow() }
}
class MacWidgetFactory extends WidgetFactory
{
public MacWidgetFactory()
{
windowFactory = new MacWindow();
menuFactory = new MacMenu();
buttonFactory = new MacButton();
}
}
class MacWindow extends Window
{
public Window createWindow() { blah }
etc.
abstract class WidgetFactory
{
private Window windowFactory;
private Menu menuFactory;
private Button buttonFactory;
public Window createWindow()
{ return windowFactory.createWindow() }
public Window createWindow( Rectangle size)
{ return windowFactory.createWindow( size ) }
public Window createWindow( Rectangle size, String title)
{ return windowFactory.createWindow( size, title) }
public Window createFancyWindow()
{ return windowFactory.createFancyWindow() }
public Window createPlainWindow()
{ return windowFactory.createPlainWindow() }
Using factory method allows abstract class to do all the
different ways to create a window.
Subclasses just provide the objects windowFactory,
menuFactory, buttonFactory, etc.
class WidgetFactory
{
private Window windowPrototype;
private Menu menuPrototype;
private Button buttonPrototype;
public WidgetFactory( Window windowPrototype,
Menu menuPrototype,
Button buttonPrototype)
{
this.windowPrototype = windowPrototype;
this.menuPrototype = menuPrototype;
this.buttonPrototype = buttonPrototype;
}
public Window createWindow()
{ return windowFactory.createWindow() }
public Window createWindow( Rectangle size)
{ return windowFactory.createWindow( size ) }
public Window createWindow( Rectangle size, String title)
{ return windowFactory.createWindow( size, title) }
public Window createFancyWindow()
{ return windowFactory.createFancyWindow() }
There is no need for subclasses of WidgetFactory.
public void installDisneyMenu(WidgetFactory myFactory)
{
// We ship next week, I can't get the stupid generic Menu to
// do the fancy Mac menu stuff
// Windows version won't ship for 6 months
// Will fix this later
MacMenu disney = (MacMenu) myFactory.createMenu();
disney.addItem( "Disney World" );
disney.addItem( "Donald Duck" );
disney.addItem( "Mickey Mouse" );
disney.addMacGrayBar( );
disney.addItem( "Minnie Mouse" );
disney.addItem( "Pluto" );
etc.
}