Solving the Maze problem....public class MazeGame { public Maze createMazeMazeFactory factory { Maze aMaze = factory.makeMaze;... Solving the Maze problem..../ Bombed version only needs
Trang 1Design Pattern
Trang 2Design Patterns
“Each pattern describes a problem which occurs over and over again
in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.”
Christopher Alexander,
A Pattern Language: Towns/Buildings/Construction, 1977
“A design pattern names, abstracts, and identifies the key aspects of a common design structure that make it useful for creating a reusable object oriented design.”
Erich Gamma et al., Design Patterns:
Elements of Reusable Object-Oriented Software
Trang 3Benefits of design patterns
Capture the knowledge of experienced developers
Publicly available “repository”
Newcomers can learn them and apply them to their design
Yield a better structure of the software (modularity, extendibility)
Facilitate discussions between programmers and managers
Trang 4Organizing the Catalog
Purpose Creational Structural Behavioral
Adapter (object)BridgeCompositeDecoratorFlyweightFacadeProxy
Chain of ResponsibilityCommandIteratorMediatorMementoObserverStateStrategyVisitor
Scope: domain over which a pattern applies
Purpose: reflects what a pattern does
Trang 5Creational design patterns
Trang 6Structural design patterns
Trang 7Behavioral design patterns
Communication between objects
How:
Through inheritance or composition
Trang 8 participating classes and/or objects
and their responsibilities
Description of a design pattern
Trang 9Creational Patterns
Trang 10Creational Patterns: Maze Game Case Study
Maze as a set of rooms A room knows its neighbors; possible
neighbors are another room, a wall, or a door to another room
The following diagram shows only the parts of these classes that are important for creating a maze.
Trang 11Abstract Factory Pattern
Trang 12Abstract Factory Pattern
Intent
Provide an interface for creating families of related or dependent
objects without specifying their concrete classes
Applicability
When clients cannot anticipate groups of classes to instantiate
A system should be independent of how its products are created,
composed, and represented
A system should be configured with one of multiple families of
Trang 13Structure
Trang 14 flexibility : isolates clients from implementation classes
abstraction : hides product's composition
It makes exchanging product families easy
Because an abstract factory creates a complete family of products, the whole product family changes at once by changing the concrete factory
It promotes consistency among products.
Supporting new kinds of products is difficult
Trang 15 Factories as singletons:
An application typically needs only one instance of a ConcreteFactory per product family
Creating the products
define a factory method for each product in a concrete factory
Defining Extensible Factories
Adding a new kind of product requires changing the AbstractFactory interface and all the classes that depend on it
A more flexible but less safe design is to add a parameter to operations that create objects:
could be a identifier, or anything else that specifies the kind of product to
be created
Trang 16Creating The Maze with Abstract Factory
Trang 17Solving the Maze problem
// default implementation needed, thus
// abstract and concrete factory
class MazeFactory {
public Maze makeMaze() {
return new Maze();
}
public Wall makeWall() {
return new Wall();
}
public Room makeRoom(int n) {
return new Room(n);
}
public Door makeDoor(Room r1, Room r2) {
return new Door(r1, r2);
}
}
Trang 18Solving the Maze problem
public class MazeGame {
public Maze createMaze(MazeFactory factory) { Maze aMaze = factory.makeMaze();
Trang 19Solving the Maze problem
/ Bombed version only needs to redefine two functions
public class BombedMazeFactory extends MazeFactory { public BombedMazeFactory();
public Wall MakeWall() {
return new BombedWall();
}
public Room MakeRoom(int n) {
return new RoomWithABomb(n);
}
}
// To build a maze with bombs we simply call
// CreateMaze with a bombed maze factory as a parameter
MazeGame game = new MazeGame();
BombedMazeFactory bFactory = new BombedMazeFactory(); game.createMaze(bFactory);
Trang 20Factory method Pattern
Trang 21 Application class is responsible for creation and management of
Trang 22 Application defines a abstract function createDocument()
MyApplication makes sure that createDocument() will create a
product (Document) of the correct type.
Trang 23 a class can't predict the class of objects it must create.
a class wants its subclasses to specify the objects it creates.
classes delegate responsibility to one of several helper
subclasses, but do not know which helper subclass is the delegate.
Trang 24Factory Method - Structure
defines the interface of objects the factory method creates
declares the factory method, or define a default implementation of the factory
method.
overrides the factory method to return
an instance of a ConcreteProduct
Trang 25Factory Method Consequences
Concrete types are isolated from the client code
Provides hooks for subclasses
A standard technique for subclasses to affect their parents' behavior
Connects parallel class hierarchies
see next slide for example
Potential disadvantage
clients might have to subclass the Creator class just to
create a particular ConcreteProduct object
Trang 26Connecting Parallel Hierarchies
Trang 27Factory Method Implementation
Two major varieties
Creator declares ABSTRACT factory method,
ConcreteCreator implements it
Creator defines a default implementation for factory
method
Parameterized factory methods
lets the factory method to create multiple kinds of objects
factory methods takes a parameter: a kind of object to create
all products have to share a Product interface
Trang 28Solving the Maze problem…
Trang 29Builder Pattern
Trang 30The Builder pattern – Motivation
A reader for the RTF (Rich Text Format) document
exchange format should be able to convert RTF to many text formats: plain ASCII text or into a text widget…
Number of possible conversions is open-ended, so it should
be easy to add a new conversion without modifying the
reader
Solution
configure the RTFReader class with a TextConverter object
TextConverter are responsible both for performing the data conversion and for representing the token in a particular format
Subclasses of TextConverter specialize in different conversions and formats: an ASCIIConverter, a TeXConverter, …
Each kind of converter class takes the mechanism for creating and
assembling a complex object and puts it behind an abstract interface
Trang 31Motivation
Trang 32Builder pattern
Intent
Separate the construction of a complex object from its representation so
that the same construction process can create different representations
Structure
Trang 33Builder pattern – Applicability
Use the Builder pattern 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 that's constructed
There are many possible reasons:
Step by step construction of a target object when the parameters for a constructor are acquired gradually
want to simply reduce the size of a class that has too many methods
Trang 34Builder pattern - Consequences
It lets you vary a product's internal representation
The builder object provides the an abstract interface for constructing the product This interface hides the representation of the internal structure
of the product, as well as how the product gets assembled
By defining a new concrete builder you can change both of these
It isolates code for construction and representation
Reusability of construction code – different Directors can reuse a
ConcreteBuilder to build new product variants
Enhances modularity and encapsulation - classes that define the products internal structure do not appear in Builder’s interface
It gives you finer control over the construction process
the Builder constructs the product step-by-step under the director’s
control
Trang 35The Maze - Builder
public interface MazeBuilder {
void buildMaze();
void buildRoom(int room);
void buildDoor(int roomFrom, int roomTo); Maze getMaze();
}
Trang 36MazeGame: CreateMaze method
The builder hides the internal representation – that is
classes that define rooms, doors and walls – of the maze, and how these parts are assembled to form the final maze.
public class MazeGame {
public Maze createMaze(MazeBuilder builder) {
Trang 37CreateMaze method
The builder interface is reusable in assembling different kinds of
mazes, as an example lets create a complex maze
public class MazeGame
public Maze createComplexMaze(MazeBuilder builder){ builder.buildMaze();
Trang 38public class SimpleMazeBuilder implements MazeBuilder {
private Maze currentMaze;
public void buildMaze() {
currentMaze = new Maze();
room.setSide(North, new Wall);
room.setSide(South, new Wall);
room.setSide(East, new Wall);
room.setSide(West, new Wall);
}
}
Trang 39SimpleMazeBuilder (con't)
public void BuilDoor(int n1, int n2) {
// need to get already assembled parts from the maze
Room r1 = currentMaze.getRoomNo(n1);
Room r2 = currentMaze.getRoomNo(n2);
Door d = new Door(r1, r2);
// fix the part that is currently being built
Trang 40Client of SimpleMazeBuilder
Maze maze;
MazeGame game;
// get concrete builder
SimpleMazeBuilder builder = new SimpleMazeBuilder();
// build the maze
game.createMaze(builder);
// retrieve the result
maze = builder.getMaze();
to create a simple maze
Trang 41Prototype Pattern
Trang 42 when the classes to instantiate are specified at run-time
avoid building a class hierarchy of factories that parallels the class hierarchy of products
when instances of a class can have one of only a few
different combinations of state.
It may be more convenient to have the proper number of prototypes and clone them rather than instantiate the class manually each time with appropriate state.
Trang 43Structure
Trang 44 Adding and removing products at run-time
A new concrete product class is introduced by registering a prototype instance with the client
Reduced subclassing
avoid parallel hierarchy for creators
Specifying new objects by varying values of prototypes
Specifying new objects by varying the structure of prototypes
Configuring an application with classes dynamically
Trang 45Implementation Issues
Using a Prototype mananger
number of prototypes isn't fixed but varies dynamically
keep a registry → prototype manager
clients request the manager to store and retrieve prototypes
associative store, based on matching a key
Implementing the clone() operation
Most languages provide some support for cloning objects.
A shallow copy is simple and often sufficient to clone a prototype.
Cloning prototypes with complex structures usually
requires a deep copy.
Trang 46Shallow Copy
Trang 47Deep Copy
Trang 48Solving the Maze Problem
class MazePrototypeFactory implements MazeFactory {
private Maze prototypeMaze;
private Room prototypeRoom;
private Wall prototypeWall;
private Door prototypeDoor
public MazePrototypeFactory(Maze m, Wall w, Room r, Door d){
_prototypeMaze = m; _prototypeWall = w;
_prototypeRoom = r; _prototypeDoor = d;
}
// all member functions for creating maze components are
// similar: each clones a prototype and then initializes it // Here are two definitions as an example
public Wall makeWall() {
return prototypeWall.clone();
}
public Door makeDoor (Room r1, Room r2) {
Door door = prototypeDoor.clone();
door.initialize(r1, r2);
return door;
Trang 49clone() method: Shallow copy
public class Door extends MapSite {
private Room room1;
private Room room2;
public void initialize(Room r1, Room r2) {
return super.clone();
} catch(CloneNotSupportedException cnse) { System.out.println(cnse.getMessage()); return null;
}
Trang 50clone() method: Deep copy
public class Door extends Wall {
private Room room1;
private Room room2;
public Door(Room r1, Room r2) {
Trang 51Solving the Maze Problem
// Creating the factories
MazePrototypeFactory simpleMazeFactory =
new MazePrototypeFactory (new Maze(), new Wall(),
new Room(), new Door());
MazePrototypeFactory bombedMazeFactory =
new MazePrototypeFactory(new Maze(), new BombedWall(), new RoomWithABomb(), new Door());
// Creating a maze for a game
MazeGame game1, game2;
// you get a simple maze
Maze maze1 = game1.createMaze(simpleMazeFactory);
// and a bombed maze
Maze maze2 = game2.createMaze(bombedMazeFactory);
Trang 52The Singleton Pattern
Trang 53 If more than one instantiated:
Incorrect program behavior, overuse of resources, inconsistent results
Alternatives:
Use a global variable
Downside: assign an object to a global variable then that object might be created when application begins If application never ends up using it and object is resource intensive > waste!
Use a static variable
Downside: how do you prevent creation of more than one class object?
Trang 54serving one company.
Use the Singleton pattern when
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
Trang 55Singleton Pattern Defined
• The Singleton Pattern ensures a class has only one instance, and provides a global point of access to it.
Trang 56public class Singleton {
private static Singleton uniqueInstance;
// other useful instance variables