200 likes | 358 Views
Factory Method. Design Pattern Space. Intent. Define an interface for creating an object, but let subclasses decide which class to instantiate
E N D
Intent • Define an interface for creating an object, but let subclasses decide which class to instantiate • Like other creational patterns, it deals with the problem of creating objects (products) without specifying the exact class of object that will be created • More generally, the term Factory Method is often used to refer to any method whose main purpose is to create objects
Problem • A framework needs to standardize the architectural model for a range of applications, but allow for individual applications to define their own domain objects and provide for their instantiation.
Applicability • The factory pattern can be used when: • The creation of an object makes reuse impossible without significant duplication of code. • The creation of an object requires access to information or resources that should not be contained within the composing class. • The lifetime management of the generated objects must be centralized to ensure a consistent behavior within the application.
Maze Class Version 1 • 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; } }
Problem • How do we make Other Mazes? SolutionIdea 1 - 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 ); 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!
How do we make Other Mazes?Idea 2 - 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(Room r1, Room r2) { return new Door(r1, r2); } 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; } }
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(); }
Implementation Two major varieties • Creator class is an abstract class: • Does not provide default implementation of factory methods abstract class MazeGame { public Maze makeMaze(); public Room makeRoom(int n ); public Wall makeWall(); public Door makeDoor();
Creator is a concrete class • Provides a default implementation for the 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(Room r1, Room r2) { return new Door(r1, r2); } • "Create objects in a separate operation so that subclasses can override the way they're created"
Another Example interface IIceCream { string Functionality(); } class ChocolateIceCream : IIceCream { public string Functionality() { return "Chocolate Ice cream"; } } class VanillaIceCream : IIceCream { public string Functionality() { return "Vanilla Ice cream"; } } classStrawberryIceCream : IIceCream { public string Functionality() { return "Strawberry Ice cream"; } } /* client */ static class Factory { ///This is the Factory method /// public staticIIceCream Get(int id) { switch (id) { case 0: returnnewChocolateIceCream(); case1: returnnewVanillaIceCream(); case 2: returnnewStrawberryIceCream(); default: returnnull; } } }
Consequences • Benefits • More flexible and reusable code by the elimination of instantiation of application-specific classes • Deals only with interface of Product class and can work with any ConcreteProduct class that supports this interface • Implementation Issues • Should the factory method be able to create multiple kinds of products? If so, then the factory method has a parameter (possibly used in an if-else!) to decide what object to create.