Presentation is loading. Please wait.

Presentation is loading. Please wait.

Department of Information Engineering 395 Design patterns What is a pattern? –Pattern describes a problem which occurs over and over again in our environment,

Similar presentations

Presentation on theme: "Department of Information Engineering 395 Design patterns What is a pattern? –Pattern describes a problem which occurs over and over again in our environment,"— Presentation transcript:

1 Department of Information Engineering 395 Design patterns What is a pattern? –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,... Christopher Alexander (architecture theorist)

2 Department of Information Engineering 396 Patterns are common Design catalogs –Script writers –Fashion designers –Interior designers –Architects Patterns are common tricks used by the profession –Don’t reinventing the wheel –Simply copy a proven design

3 Department of Information Engineering 397 “Design Pattern” by Gamma et al 23 common design patterns divided into 3 groups 1.How to create objects (creational patterns) 2.How to group them (structural patterns) 3.How to use them (behavior patterns) –Two general approaches in patterns –Class inheritance –Object delegation

4 Department of Information Engineering 398 Each pattern has –Name –Problem statement –Solution –Consequences Importance of the name –To facilitate communication between developers

5 Department of Information Engineering 399 Exercises Simple quiz – A list of open-end questions – ONS

6 Department of Information Engineering 400 Two fundamental principles in OO Programming Programming to an Interface, not an Implementation –so that you can change the implementation easily in future, the interface is just like a socket Favour object composition over class inheritance –To promote more flexible reuse –Don’t overuse inheritance (only for classes that share the same behavior)

7 Department of Information Engineering 401 Example: Maze game To write a maze adventure game The game –A maze has-a number of rooms –A room has four sides (North, East, South, West) –A player enters a side If the side is a door, it leads to another room If the side is a wall, the player is hurt –The player wins if a way leaving the maze is found

8 Department of Information Engineering 402 The objects MazeGame, Maze, Room, Door, Side Polymorphism –Group Room, Door and Side under the abstract base class MapSite Base class virtual function –Enter() How to build the maze using OO concepts?

9 Department of Information Engineering 403 Is-a relation A Room is-a kind of MapSite A Door is-a kind of MapSite A Wall is-a kind of MapSite Is-a suggests class inheritance MapSite RoomDoor Wall Is-a

10 Department of Information Engineering 404 Is-a relation Skeleton code class MapSite { //ABSTRACT class public virtual void Enter(){} } class Room : MapSite { //CONCRETE class public override void Enter(){…} //implementation } Room.Enter() - enter a room Door.Enter() - enter the room beyond the door Wall.Enter() - get hurt, stay at the same room

11 Department of Information Engineering 405 Has-a relation A maze has-a number of rooms A room has four sides A room may have several smaller rooms Has-a suggests object composition

12 Department of Information Engineering 406 A UML diagram describing the maze structure Maze AddRoom() RoomNo() ArrayList _rooms MapSite Enter() Room Enter() SetSide() GetSide() RoomNo Wall Enter() Door Enter() rooms Recursion. Known as Composite pattern Has-a

13 Department of Information Engineering 407 Object composition Maze is composed of (has-a) Rooms Room is composed of Doors, Walls and Rooms. class Maze { private ArrayList _rooms=new ArrayList(); //a typeless container that holds the rooms } class Room : MapSite { public override void Enter() {//...} private MapSite[] _sides = new MapSite[4]; }

14 Department of Information Engineering 408 Wall, Door class Wall : MapSite { public override void Enter() {...} } class Door : MapSite { private Room _room1; private Room _room2; public Door(Room r1, Room r2) {...} public override void Enter() {...} } static void Main() {... MazeGame game = new MazeGame(); _aMaze = game.CreateMaze(); //create the maze... }

15 Department of Information Engineering 409 MazeGame.CreateMaze() creates a simple maze N Room 1 Room 2 _aMaze _rooms r1 _side[0] _side[1] _side[2] _side[3] r2... aWall aDoor(r1,r2) aWall Objects structure

16 Department of Information Engineering 410 Maze MazeGame.CreateMaze() { Maze aMaze = new Maze(); //create a maze object Room r1 = new Room(1); //create rooms Room r2 = new Room(2); Door theDoor = new Door(r1, r2); //create door r1.SetSide(North, new Wall()); //add wall to room r1.SetSide(East, theDoor()); //add door to room r1.SetSide(South, new Wall()); r1.SetSide(West, new Wall()); //... init r2 like r1 aMaze.AddRoom(r1);//add to container aMaze.AddRoom(r2); return aMaze; }

17 Department of Information Engineering 411 What is wrong with CreateMaze() ? MazeGame Maze MazeGame.CreateMaze() { Maze aMaze = new Maze(); Room r1 = new Room(1); Room r2 = new Room(2); Door theDoor = new Door(r1, r2);... return aMaze; }

18 Department of Information Engineering 412 What if... in future, we would like –to CREATE a different kind of room? –to CREATE a different kind of door? –to CREATE a different kind of wall? We need to change the code in CreateMaze()

19 Department of Information Engineering 413 This is what we have to do – break the old code ! MazeGame Maze MazeGame.CreateMaze() { Maze aMaze = new Maze(); Room r1 = new EnchantedRoom(1); Room r2 = new EnchantedRoom(2); Door theDoor = new DoorNeedSpell(r1, r2); return aMaze; }

20 Department of Information Engineering 414 Solutions? Class inheritance –Factory method Object delegation –Abstract factory –Builder –Prototype

21 Department of Information Engineering 415 Factory method Replace new by virtual function –Virtual function can be overrided by the subclass, so that different objects can be created MazeGame Maze MazeGame.CreateMaze() { Room r1 = MakeRoom(1); //... } //base class default MakeRoom() Room MazeGame.MakeRoom(int n) { return new Room(n); }

22 Department of Information Engineering 416 Let subclass to override the factory method MazeGame Maze MazeGame.CreateMaze() { Room r1 = MakeRoom(1); } EnchantedMazeGame //override base class MakeRoom() Room EnchantedMazeGame.MakeRoom(int n) { return new EnchantedRoom(n, SpellDoor()) }

23 Department of Information Engineering 417 Change one line and have a different MazeGame public class Form1 : Form Maze _aMaze; static void Main() { using (Form1 form = new Form1()) { form.InitializeGame(); Application.Run(form); } private void InitializeGame() { //MazeGame game = new MazeGame(); MazeGame game = new EnchantedMazeGame(); _aMaze = game.CreateMaze(); //create the maze } //... code for the event handlers }

24 Department of Information Engineering 418 Factory Method Define an interface (the virtual functions) for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. Also known as virtual constructor

25 Department of Information Engineering 419 Framework, toolkit and application What is the difference between framework, toolkit and application? –Framework has the highest degree of reuse, and is the most flexible –Application is the least flexible

26 Department of Information Engineering 420 What is a framework? A framework is an abstract type of software that captures the design decisions that are common to its application domains –e.g. what is the similarity between a circuit design editor, and musical score editor? –Both manipulate graphical objects An abstract software (framework) that can support both applications?

27 Department of Information Engineering 421 A general framework for graphical processing AbstractFramework NewDoc(){ AbstractGraphic g; g = CreateGraphic(); } MyGraphicApplication CreateGraphic() //factory method { return new MyGraphic(); } AbstractGraphic Move(); Scale(); MyGraphic Framework

28 Department of Information Engineering 422 A framework for graphical processing The concrete MyGraphic object can be any graphic symbols, e.g. musical notes, circuit symbols These objects can be manipulated by a uniform set of operations (e.g. Move(), Scale(), etc) Code in framework knows how to manipulate the abstract base class AbstractGraphic object The concrete subclass object ( MyGraphic ) is created differently for different application

29 Department of Information Engineering 423 A musical score editor AbstractFramework NewDoc(){ AbstractGraphic g; g = CreateGraphic(); } MyMusicScoreApplication CreateGraphic() //factory method { return new MyMusicScore(); } AbstractGraphic Move(); Scale(); MyMusicScore Framework

30 Department of Information Engineering 424 A electronic circuit editor AbstractFramework NewDoc(){ AbstractGraphic g; g = CreateGraphic(); } MyCircuitApplication CreateGraphic() //factory method { return new MyCircuit(); } AbstractGraphic Move(); Scale(); MyCircuit Framework

31 Department of Information Engineering 425 Thinking in two levels –Abstract level (framework level) I (framework) don’t care what the symbols (objects) are about ! My job is just to move, to scale, to draw, and to print the symbols How to draw/print the symbols? That is the job of the symbols themselves (think like a boss!) –Concrete level All the (dirty) real work is done by me (concrete objects)

32 Department of Information Engineering 426 What is a framework? Framework emphasizes design reuse rather than code reuse Framework contains the main program, users customize the framework by providing the concrete subclasses Modern systems have layers of frameworks that cooperate with each other

33 Department of Information Engineering 427 Toolkit Toolkit is just a set of reusable classes, providing the functionality Emphasize code reuse Users write the main program, toolkit provides reusable code Framework is harder to code than toolkit Toolkit is harder to code than application

34 Department of Information Engineering 428 Pros and cons of class inheritance Pros –Simpler than object delegation, codes are easier to follow Cons –Static binding, fixed at compilation time, cannot be changed at run-time –Need to create new subclass Ways to reduce the number of subclasses?

35 Department of Information Engineering 429 Parameterized factory methods The method takes a parameter that identifies the kind of product Parameterized factory methods reduce the number of subclasses that are needed Use –In document applications, different document type has different file extent (.doc,.xml,.txt,...)

36 Department of Information Engineering 430 Parameterized factory methods class Creator { public virtual Product Create(int id){} } class ConcreteCreator : Creator { public override Product Create(int id) { if (id==A) return new ProductA; if... return base.Creator(id); }

37 Department of Information Engineering 431 Use Generic to avoid subclassing Problem with factory methods –For every new product, you need to subclassing the Creator for creating the product Use Generics to void subclassing –The code for the subclass is automatically generated by the compiler In the following example, GenericCreator is just a template, compiler uses it to generate the code

38 Department of Information Engineering 432 Use Generic to avoid subclassing class Creator { public virtual Product Create(){} } class GenericCreator : Creator { public override Product Create(){ return new T(); } Main() { Creator myCreator = new GenericCreator (); Product p = myCreator.Create(); //factory method }

39 Department of Information Engineering 433 The code generated class GenericCreator : Creator { public override Product Create(){ return new ProductA(); }

40 Department of Information Engineering 434 Create objects by Object Delegation MazeGame CreateMaze(f) { //f is a factory object Maze aMaze = new Maze(); Room r1 = f.MakeRoom(1); Room r2 = f.MakeRoom(2); //... return aMaze; } AbstractFactory MakeRoom(int n) ConcreteFactory MakeRoom(int n) { return new Room(n); } delegate MakeRoom is a factory method

41 Department of Information Engineering 435 Abstract Factory In many applications, we don’t change just one type of object, but, rather, a family of objects This can be done by using a factory object To select a different game at run-time –Just change the (concrete) factory object f Abstract Factory provides an interface for creating families of related or dependent objects without specifying their concrete classes

42 Department of Information Engineering 436 Example - the Look-and-Feel Problem How to change the look and feel of the desktop at run-time? –e.g. change to MotifWindow, MSWindow, AppleWindow Solution –Choose a concrete factory object MotifFactory, MSFactory, or AppleFactory –The factory object creates the concrete products MSWindow, MSScrollBar,...) –but returns them as abstract products Window, ScrollBar

43 Department of Information Engineering 437 Abstract Factory: client uses an abstract factory GUIFactory to produce abstract products GUIFactory CreateScrollBar() CreateWindow() MotifFactory CreateScrollBar() CreateWindow() client Window MSWindowMotifWindow ScrollBar MSScrollBarMotifScrollBar MSFactory CreateScrollBar() CreateWindow() delegate Is-a

44 Department of Information Engineering 438 Abstract Factory GUIFactory guifactory; //choose a concrete factory object if (strcmp( inputName, “Motif”) == 0 ) { guifactory = new MotifFactory(); } else { guifactory = new MSFactory(); } //factory returns abstract product Window w = guifactory.CreateWindow(); w.Draw(); Different factory creates different concrete product Return the abstract product, upcasting, polymorphism

45 Department of Information Engineering 439 Builder Problem –To build a complex object, e.g. a building, an aircraft The complex object has different representations –i.e. we can look at the object at different ways –e.g. different representations of an aircraft Its look Its total weight Its total cost

46 Department of Information Engineering 440 Builder What to reuse? –The construction of the object is complex –Want to reuse the construction process so as to create different representations Solution? –Separate the construction of a complex object from its representation so that the same construction process can create different representations

47 Department of Information Engineering 441 Builder MazeGame CreateMaze(builder) { builder.BuildMaze(); builder.BuildRoom(1); builder.BuildRoom(2); //... return builder.GetMaze(); } AbstractBuilder buildRoom(int n) ConcreteBuilder buildRoom(int n) { return new Room(n); } delegate Construction Representation

48 Department of Information Engineering 442 Builder Change the concrete Builder, get a different product Example –CountBuilder To count the number of parts (rooms, doors) used in the maze –SimpleBuilder Return a simplified graphical maze object that is good for low-end mobile phone

49 Department of Information Engineering 443 Intent and its importance Abstract Factory and Builder are different patterns for solving different problems But they have the same code structure !! –They have the same UML diagrams Code is not everything –Should also know the intent of the code

50 Department of Information Engineering 444 Difference between Abstract Factory and Builder Their intent are different Abstract Factory –Provide an interface for creating families of related or dependent objects without specifying their concrete classes Builder –Separate the construction of a complex object from its representation so that the same construction process can create different representations

51 Department of Information Engineering 445 Abstract Factory and Builder Abstract Factory focuses on building a families of parts (either simple or complex), and returns the part immediately –Client assembles the parts into complex object Builder returns the product as a final step –The concrete parts in the complex object is encapsulated inside the Builder –Parts have different representations that are hidden from the client Appearance, weight, cost,... –Change Builder, change representation

52 Department of Information Engineering 446 Problem To build a maze that allows player to choose the composition of the maze at run-time e.g. the maze can be made up of EnchantedRoom, DoorWithSpell and BombedWall The problem is like creating an ice cream object with different combination of favours Use a factory to build these parts so that player can choose the composition dynamically

53 Department of Information Engineering 447 Problem with subclassing AbstractFactory Factory1 Door Wall Room Factory2 DoorWithSpell Wall Room Factory3 Door BombedWall Room Factory4 Door Wall EnchantedRoom Factory5 DoorWithSpell BombedWall Room... Factory8 DoorWithSpell BombedWall EnchantedRoom

54 Department of Information Engineering 448 Combinatorial problem If we have 5 different types of rooms, doors and walls, we have 5*5*5 different combinations –Need to create 125 subclasses ! –Class explosion, a common problem with subclassing A better approach - composition –Construct a prototype object at run-time –The prototype is composed of EnchantedRoom, DoorWithSpell and BombedWall –Prototype is a factory object that manufactures the parts by cloning

55 Department of Information Engineering 449 The Prototype MazePrototypeFactory factory class MazePrototypeFactory : MazeFactory { public MazePrototypeFactory(Maze m, Wall w, Room r, Door d); public virtual Maze MakeMaze(); public virtual Room MakeRoom(int i); public virtual Wall MakeWall(); public virtual Door MakeDoor(Room r1, Room r2); private Maze _prototypeMaze; private Room _prototypeRoom; private Wall _prototypeWall; private Door _prototypeDoor; }

56 Department of Information Engineering 450 To create the prototype object int Main() { MazeGame game; MazePrototypeFactory factory(new Maze(), new BombedWall(), new EnchantedRoom(), new DoorWithSpell()); Maze maze = game.CreateMaze(factory);... } factory Maze _maze = new Maze() Wall _wall = new BombedWall() Room _room = new EnchantedRoom() Door _door = new DoorWithSpell() Construct a Prototype factory object

57 Department of Information Engineering 451 The prototype constructor Create the prototype object by composition MazePrototypeFactory(Maze m, Wall w, Room r, Door d) { _maze = m; //point to an concrete object _wall = w; _room = r; _door = d; } Has-a relation (a prototype has-a maze, wall, room and door) Also known as composition

58 Department of Information Engineering 452 How to use it? We use the prototype factory object like an Abstract Factory object Maze MazeGame.CreateMaze(MazeFactory factory) { Maze aMaze = factory.MakeMaze(); Room r1 = factory.MakeRoom(1);... } So what is inside factory.MakeRoom() ?

59 Department of Information Engineering 453 How to use it? factory.MakeRoom() uses the existing Room object to clone a new EnchantedRoom createMaze(factory) r1=factory.MakeRoom(1) MazeFactory MazePrototypeFactory private Room _room; Room MakeRoom(int i) { r=_room.Clone(); r.Number = i; return r; } EnchantedRoom Room Clone() { Room r=new EnchantedRoom(); //copy attributes from this return r; } A clone of EnchantedRoom Room Room Clone() {}

60 Department of Information Engineering 454 Summary – Creational Patterns Factory Method Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses Abstract Factory Provide an interface for creating families of related or dependent objects without specifying their concrete classes Builder Separate the construction of a complex object from its representation so that the same construction process can create different representations Prototype Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype

61 Department of Information Engineering 455 Singleton How to create one and only one instance of a class, –e.g. a single print queue shared by many printer –a single window server for the user interface The single object must be easily accessible Intent –Ensure a class only has one instance, and provide a global point of access to it

62 Department of Information Engineering 456 The consideration To make the object easily accessible –Use a global/static object Drawback –No guarantee that there is only one instance of the class, e.g. static Singleton object_1 = new Singleton(); static Singleton object _2 = new Singleton(); Problem - two objects of the same class Solution - use a private constructor !

63 Department of Information Engineering 457 Use private constructor and public method sealed class Singleton { protected Singleton(); private static Singleton _instance=null; public static Singleton Instance() { if (_instance==null) { _instance = new Singleton(); } return _instance; } Main() {//to use a Singleton Singleton server1 = Singleton.Instance(); Singleton server3 = new Singleton(); //won’t compile, constructor is protected }

64 Department of Information Engineering 458 Singleton() is private; object can only be created via the function Instance() Instance() controls the number of objects created But Instance() is an object level method –With a private constructor, we have a problem in creating the first object –Without an object, we cannot invoke Instance() Instance() must therefore be a class level ( static ) method

65 Department of Information Engineering 459 Creational patterns –Create objects flexibly Structural patterns –Group objects together to form more complex structure

66 Department of Information Engineering 460 Adapter Problem –A bank is developing a new system with a new interface, how to reuse the old (legacy) system ? client INewSystem NewRequest() OldSystem OldRequest()

67 Department of Information Engineering 461 Solution New Old ClassAdapter New Old ObjectAdapter Class Adapter Object Adapter

68 Department of Information Engineering 462 Class Adapter - by class inheritance client INewSystem NewRequest() OldSystem OldRequest() ClassAdapter NewRequest() { OldRequest() }

69 Department of Information Engineering 463 Class Adapter public class ClassAdapter : OldSystem, INewSystem { public void INewSystem.Request() { base.OldRequest(); //base refers to OldSystem } Main() { INewSystem sys = new ClassAdapter(); }

70 Department of Information Engineering 464 Problems Modern OO languages (C#, Java) only support single implementation inheritance Cannot hide the old implementation –Interface in OldSystem can be exposed by casting class ClassAdapter : private OldSystem, INewSystem Object Adapter does not have these problems Ideal, but not supported in C#

71 Department of Information Engineering 465 Object Adapter client NewSystem NewRequest() Object Adapter NewRequest() adaptee->OldRequest() OldSystem OldRequest() adaptee

72 Department of Information Engineering 466 Object Adapter public class ObjectAdapter : NewSystem { private OldSystem _oldSys = new OldSystem(); public void NewRequest() { _oldSys.OldRequest(); //delegation } Single implementation inheritance Interface of the old system is hidden from client

73 Department of Information Engineering 467 Adapter Also Known as –Wrapper Intent –Convert the interface of a class into another interface clients expect. –Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces

74 Department of Information Engineering 468 Problem –To support a computer game for two different hardware platforms Solution by subclassing Game XBoxGamePSGame abstraction implementations

75 Department of Information Engineering 469 Bridge Problem with extending the abstraction –To add a platform (Nokia phone), need to port the implementation of the game to the new platform A better solution –Separate the platform-specific code from the abstraction (of the game)

76 Department of Information Engineering 470 Bridge Decouple (separate) an abstraction from its implementation so that the two can vary independently Abstraction Implementor Operation() Abstract_1 Abstract_2 Imp_1 Imp_2Imp_3 imp imp.Operation()

77 Department of Information Engineering 471 Game DrawText() DrawRect() GameImp imp ConcreteGame1 DrawBorder() DrawRect() DrawText() GameImp DevDrawText() DevDrawLine() XBoxImp PSImp imp imp.DevDrawLine() Abstraction Implementation

78 Department of Information Engineering 472 Bridge Intent Decouple an abstraction from its implementation so that the two can vary independently The Graphics object in GDI+ is an example of Bridge pattern –GDI+, platform specific code is separated and encapsulated in a Graphics object; –Different Graphics object can be used to represent different graphic card

79 Department of Information Engineering 473 Composite A graphics application has primitives (line, circle), which can be grouped to form a larger component –Component is just a container –Components can be grouped to form an even larger components Problem –How to treat primitives and components uniformly –e.g. if g is a line, g.Draw() will draw a line –if g is a component, g.Draw() will draw all the composition recursively

80 Department of Information Engineering 474 Composite Uniform interface - suggest the use of a base class Graphic Draw() Picture Draw() Circle Draw() Line Draw()

81 Department of Information Engineering 475 Composite A Picture is a Composite (has-a pictures/primitives) –Recursion Graphic Draw() Picture Draw() Circle Draw() Line Draw()

82 Department of Information Engineering 476 Recursive object structure aPicture aLineaCircle aPicture aLineaCircle

83 Department of Information Engineering 477 Composite code example class Graphic { public virtual void Draw(); //... } class Picture : Graphic { private ArrayList graphics; //container public void Draw() { foreach (object o in ArrayList) { Graphic g = (Graphic) o; g.Draw(); //if g is-a line, draw line } //if g is-a picture, recursion }

84 Department of Information Engineering 478 Composite Intent –Compose objects into tree structures to represent part-whole hierarchies. Composite let clients treat individual objects and compositions of objects uniformly Note –Part-whole hierarchies are extremely common, making Composite one of the most useful pattern

85 Department of Information Engineering 479 Decorator Problem –How to create a reader object that can Read a stream from the file Decrypt the stream Perform a formatted read (read an integer, double, etc, from byte stream) –How to build this reader object flexibly?

86 Department of Information Engineering 480 Class inheritance approach Create more specialized objects by subclassing The concrete BinaryRead object –use FileStream code to read the file –use CryptoStream code to decrypt the file –use its own code to do formatted read FileStream CryptoStream BinaryReader Read file inputDecryptFormatted read

87 Department of Information Engineering 481 Class inheritance approach Combinatorial problem, need many subclasses Static binding – can’t change at run-time Object delegation –More flexible than by subclassing –Concept is similar to piping in Unix, a complex object is formed by joining several objects together Structure of a decorator

88 Department of Information Engineering 482 Decorator To create new object by composition and perform a chain of actions –FileStream.Read() then CryptoStream.Read() then BinaryReader.ReadXxx() BinaryReader ReadXxx() Stream _next CryptoStream Read() Stream _next FileStream Read() Stream _next A decorator object

89 Department of Information Engineering 483 Decorator object diagram BinaryReader Stream _next; ReadXxx() { if (!_next) _next.Read(); //…format data } CryptoStream Stream _next; Read() { if (!_next) _next.Read(); //…decrypt data } FileStream Read() { //read data } Has-a relationship Software piping by delegation

90 Department of Information Engineering 484 Decorator class diagram To support composition of indefinite number of objects Stream Read(byte[] buffer, int offset, int count) ConcreteStream Read(...) Stream _next Has-a 1

91 Department of Information Engineering 485 Class diagram of System.IO in C# Stream CryptoStream FileStream TextWriter StreamWriterStringWriter BinaryWriter BufferStream NetworkStream Reader has the same class diagram as Writer Note the decorator pattern

92 Department of Information Engineering 486 The structure of the IO design TextWriter class –For writing characters –StreamWriter – for writing a indefinite sequence of characters BinaryWriter class –Class for writing a binary stream Stream class –For adding different features flexibly using the decorator pattern

93 Department of Information Engineering 487 Example An object that formats, encrypts, and writes to file using System; using System.IO; using System.Security.Cryptography; static void Main(string[] args) { //initialization code skipped FileStream fout = new FileStream(...); CryptoStream cs = new CryptoStream(fout,... ); BinaryWriter bw = new BinaryWriter(cs); bw.Write("hello world");//format, encrypted, write to file bw.Close(); cs.Close(); fout.Close();

94 Department of Information Engineering 488 Decorator Also known as –Wrapper Intent –Attach additional responsibilities to an object dynamically. –Decorators provide a flexible alternative to subclassing for extending functionality Known Uses –I/O objects in C#, Java –graphical user interface (see text)

95 Department of Information Engineering 489 Façade Problem –Objects have too many dependency, how to reduce the dependency? Subsystem

96 Department of Information Engineering 490 Façade Solution –Create Subsystem with a single and unified interface Facade Subsystem

97 Department of Information Engineering 491 Façade Intent –Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use –Façade objects are often Singletons C# internal keyword –A subsystem has public classes and encapsulated private classes –Use internal keyword for encapsulating classes within an assembly, and public keyword for the Façade public class

98 Department of Information Engineering 492 Proxy Problem –Some objects are expensive to create e.g. a large document with many objects (text, images) –Create all the objects at once takes too long Solution –Create a proxy object quickly –Only create the objects when they are needed (visible in the document) Proxy

99 Department of Information Engineering 493 Proxy ImageProxy is an object that can be created very cheaply, it maintains a reference to the image on disk aTextDocument image anImageProxy fileName anImage data in memory on disk

100 Department of Information Engineering 494 Image Proxy client Graphic Draw() ImageProxy Draw() Image image Image Draw() realSubject //draw only on-demand if(image == 0) { image=LoadImage(fileName); } image.Draw() (has-a)

101 Department of Information Engineering 495 Proxy server example client WebServer Get(url)... WebProxy Get(url)... OriginServer Get(url)... //get over the net only on-demand if( url_not_in_cache ) { url=server.Get(url); } return url

102 Department of Information Engineering 496 Proxy application virtual proxy (as in our example) –creates expensive objects on demand –e.g. virtual memory in an OO Unix remote proxy –provides a local representative for an object in a different address space (e.g CORBA, RMI,.NET) protection proxy –control access to the original object (authentication) smart reference –replacement of a bare pointer that performs additional actions, e.g. web page filtering

103 Department of Information Engineering 497 Flyweight A pattern for system that has a large number of tiny objects Scenario –In a word processing application, we have row objects column objects character objects –A column may have several rows, and each row may have many character objects –Use Composite Pattern to model this structure

104 Department of Information Engineering 498 Flyweight Composite Pattern –All objects are treated uniformly by the functions provided in base class Glyph –Captures the tree-structure of the document Glyph Rowcolumn

105 Department of Information Engineering 499 Flyweight Problem –Large number of small objects ! –One page ~ 500 words ~ 2500 characters (objects)

106 Department of Information Engineering 500 Flyweight Solution –Each character object is a singleton shared in a pool

107 Department of Information Engineering 501 An object has Sharable attributes –e.g. the character code Non-sharable attributes –e.g. font type and font size Sharable attributes are stored in Singleton objects, located in a sharable flyweight pool The non-sharable attributes are stored in a context object ( GlyphContext ) Example of non-sharable context –font size, font type

108 Department of Information Engineering 502 Represent the context by a table The table can be implemented using Dictionary that supports the IDictionary interface Dictionary has a collection of key/value pairs –Key = position, string=context int(key)string(value) 1 Times 24 //1 char 2 Times 12 //next 100 char 102 Times-Italic 12 //next 6 char 108 Times 12 //next 194 char...

109 Department of Information Engineering 503 Flyweight To draw a Character object –Glyph.Draw() is not enough Character contains only the sharable attributes, need the GlyphContext object to get the context –Glyph.Draw(GlyphContext) complete information = Glyph + GlyphContext

110 Department of Information Engineering 504 Creational patterns –How to create objects flexibly Structural patterns –How to group objects together Behavioral patterns –How to use objects in a collaborative way –The key - identify the responsibilities of the objects

111 Department of Information Engineering 505 Course Registration System Design a course registration system to support –Course browsing –Course registration –Constraint checking (e.g. pre-requisite) –Course functions (e.g. print course list) Problem –What is the object structure that we should use?

112 Department of Information Engineering 506 Arrange the courses by a tree structure university Law Engineering Science CSE IE IEG3080 composite leaf

113 Department of Information Engineering 507 Composite pattern Node string _name; NodeList //name=Erg,Sci,... Course //name=IEG

114 Department of Information Engineering 508 Problem - GUI framework to support course browsing? Course InfoRegistration Menu bar ALL ART MED SCI ERG ACE CE CS EE SEEM IE Menu item Menu IEG1110 IEG IEG3080

115 Department of Information Engineering 509 Browsing The menu Menu item –ALL, ART, ERG,..., IE,..., IEG3080 Each item has a different Action –ALL will list all courses provided –ART will list all courses in ART faculty –IEG3080 will list course info in IEG3080 ALL ART ERG MED SCI

116 Department of Information Engineering 510 A GUI framework can only provide the following abstract widgets –Menu –MenuItem A Menu has-a number of MenuItems –Select a MenuItem, an action will be executed How to associate the MenuItem with your action? MenuItem Your action GUI framework

117 Department of Information Engineering 511 By class inheritance MenuItem is an abstract base class that has an Execute() Subclass implements Execute() Simple, static binding MenuItem Execute() MyMenuItem Execute() Action() Menu Abstract framework

118 Department of Information Engineering 512 By object delegation MenuItem Command c Clicked() Command CommandA Execute() CommandB Execute() c->Execute() Action1() Action2() Menu Abstract framework

119 Department of Information Engineering 513 Command object Put a Command object inside a MenuItem object –aMenuItem.StoreCommand(Command c) –If MenuItem is clicked, c.Execute() is called A difference between inheritance and delegation –Inheritance binded MenuItem with the action –Delegation decouples the two The decoupling leads to a better reuse of the Command object (it can be used by more than one MenuItem )

120 Department of Information Engineering 514 How to support Undo /Redo ? Each command object supports Execute() and UnExecute() –Clone a command object –Put the cloned object in a command history list Redo => clonedObject.UnExecute() present past commands

121 Department of Information Engineering 515 Command Intent –Encapsulate a request as an object Applications –Each MenuItem has a command object e.g. new MenuItem(new IEG3080()) –The.NET’s delegate is an example of command

122 Department of Information Engineering 516 Problem To check whether a student can register to a course –need to check the course, department, faculty, and university constraints Example of constraints –credit exceeded, pre-requisites not met Problem –Which object is responsible in doing the checking?

123 Department of Information Engineering 517 Chain of Responsibility A simple solution –Pass the request along a chain of responsibility –Each object on the chain shares a common interface It is like getting a form signed but you don’t know who should sign it –So pass the form around until someone could handle it

124 Department of Information Engineering 518 Chain of Responsibility Often applied in conjunction with Composite (i.e. tree structure) client aHandler IEHandler successor ErgHandler successor UniHandler successor SciHandler successor CSHandler successor

125 Department of Information Engineering 519 Chain of Responsibility Handler Request() ConcreteHanlder1 Request() ConcreteHanlder1 Request() successor client

126 Department of Information Engineering 520 Chain of Responsibility Intent –More than one object may handle a request, and the handler is not known –You want to issue a request to one of several objects without specifying the receiver explicitly The structure is similar to a composite pattern –But composite pattern is focused on the structure of the objects –Chain of Responsibility is focused on the behavior of the objects

127 Department of Information Engineering 521 Problem – multicast relationship How to define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically e.g. 10:00am HK time 2:00am London time 10:00pm New York time Central timer Central Timer changes state Notify all other clocks

128 Department of Information Engineering 522 Observer Pattern Key abstraction –Subject (e.g. central timer) –Observers (e.g. different clock) Whenever the Subject changes its state, it notifies (Update()) all the Observers Each Observer responds by getting the up-to- date information (GetState()) from the Subject A new Observer can a ttach itself to the container of the Subject

129 Department of Information Engineering 523 Observer Pattern Subject Attach(Observer) Detach(Observer) Notify() observers Observer Update(subject) ConcreteSubject GetState();... ConcreteObserver Update(subject) Foreach o in observers { o.Update(this); } observerState = subject.GetState(); 1 *

130 Department of Information Engineering 524 The multicast protocol Subject has a list of Observers An Observer uses Attach() and Detach() to add itself to Subject’s list Subject uses Update() to send notification to Observers –Pass itself to Observers as parameters –Observers use the passed Subject to get the new state information

131 Department of Information Engineering 525 GUI problem User uses a mouse to click a button on the screen Window manage detects the mouse click event But how could the manager notify the button handler? Mouse click MyButtonHandler Update() Window manager Button ?

132 Department of Information Engineering 526 Class inheritance Used by early version of MFC and Java (ver 1.0) Mouse click MyButtonHandler Update() Window manager Button Update()

133 Department of Information Engineering 527 Class inheritance User clicks Button, the manager uses the current mouse position to locate Button Manager calls Button.Update() MyButtonHandler inherits the Button interface, MyButtonHandler.Update() is called Limitation –Do not support multicast –Static binding, relationship is fixed at compile time, cannot attach or detach at run time

134 Department of Information Engineering 528 Object delegation Used by current version of Java (the name Listener is used instead of Observer) Advantages –Support multicast and dynamic binding (so that user can attach and detach observer at run time) Mouse click Window manager Button Update() Listener[] list MyButtonHanlder Update() Observer Update()

135 Department of Information Engineering 529 Further improvement on the Observer pattern Problem with Observer –Every event handler must inherit the Observer base class (which provides the Update() interface) –The Subject passes itself as argument to the Observer How to specify the type of the Subject flexibly? Delegate –An improved version of Observer –Use a Command object to encapsulate a pointer to the handler, eliminate Update() and the base class Observer

136 Department of Information Engineering 530 Callback by delegation (in L3 notes) class MyWindow : Form { static void Main() { Application.Run(new MyWindow()); } public MyWindow() { this.MouseUp += new EventHandler(this.Handler()); } //MouseUp is a container private void Handler(object sender,System.EventArgs e){ Console.WriteLine(“call from {0}”,sender.ToString()); } function pointer Handler function Command object

137 Department of Information Engineering 531 C# delegate User can also define a delegate with signature –More flexible, can pass type-safe information –public delegate void MyHandler(Student s); Delegate = Command + Observer pattern Window manager Button Update() Listener[] list MyHandler Handler() Command C# delegate object Command has a pointer to Handler()

138 Department of Information Engineering 532 Mediator Problem –OO encourages distribution of responsibility, but this frequently leads to many connections between objects –The system is difficult to change because each object depends on many other objects

139 Department of Information Engineering 533 Mediator Solution –Promotes loose coupling between objects via a central mediator mediator

140 Department of Information Engineering 534 Mediator Intent –Define an object that encapsulates how a set of objects interact –Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently –Replace many-to-many interactions with one- to-many interactions –If an object is changed, only need to change the Mediator, but not the rest of the objects

141 Department of Information Engineering 535 Example – dialog box A dialog box has a number of widgets –Buttons, menus, and entry fields

142 Department of Information Engineering 536 Dependencies between widgets Select an option in one widget causes changes in other widgets

143 Department of Information Engineering 537 Without mediator –If a widget is changed, need to notify other widgets –Creates dependency between widgets, tight coupling, makes future change difficult With mediator –If a widget is changed, only need to notify the Mediator –Loose coupling, localized change –The Mediator centralizes control, to change the behavior only requires subclassing the Mediator

144 Department of Information Engineering 538 Mediator

145 Department of Information Engineering 539 How to test your code A common generic pattern in testing –Set up the environment –Do some work –Tear down TestCase() { SetUp(); while ( HasMore() ) { Run(); } TearDown(); }

146 Department of Information Engineering 540 Template Method We have a fixed sequence of steps which are invariant, though the implementation of each step may change We may carry out different testing, but the sequence remains the same Template pattern encapsulates the sequence of business logic

147 Department of Information Engineering 541 Template Method Base class defines the template of an algorithm, deferring the implementation to subclasses Subclasses redefine certain steps of an algorithm without changing the algorithm’s structure TestCase() { SetUp();... } SetUp() {... }

148 Department of Information Engineering 542 Note The template method TestCase() is non- virtual –Cannot be overrided by the subclass –So that the fixed sequence cannot be changed Methods inside the template are protected –Intended to be overrided by the subclasses, but are not opened to public

149 Department of Information Engineering 543 Template Method We have seen it before in creating a maze Maze MazeGame.CreateMaze() { Maze aMaze = makeMaze(); Room r1 = makeRoom(1); Room r2 = makeRoom(2); Door theDoor = makeDoor(r1, r2); aMaze.addRoom(r1); aMaze.addRoom(r2);... } A template of creating a maze

150 Department of Information Engineering 544 TCP (transmission control protocol) implementation Problem –How to implement TCP? TCP is complex !! –A connection can be in one of the many states e.g. Listen, Established, SynSent –A connection may receive different requests e.g. active open, close, acknowledge –Different state responds to the request differently

151 Department of Information Engineering 545 TCP state diagram

152 Department of Information Engineering 546 State Listen, Established, Closed is-a kind of State TCPState SynSent EstablishedClosed

153 Department of Information Engineering 547 State Each TCPConnection has-a State TCPConnection TCPState _state TCPState SynSent EstablishedClosed

154 Department of Information Engineering 548 State TCPConnection may receive many requests –e.g. connect, close, acknowledge TCPConnection Connect() Close() Acknowledge() TCPState _state TCPState SynSent EstablishedClosed

155 Department of Information Engineering 549 Should TCPConnection handle the requests? No, requests are state-dependent Delegate the requests to the TCPState objects TCPConnection Connect()... TCPState _state TCPState Connect()... SynSent Connect()... Closed Connect()...

156 Department of Information Engineering 550 How to handle a request? TCPConnection receives a “connect” request –TCPConnection object delegates the request to _ state (the current TCPState object) –No ugly if-then-else block

157 Department of Information Engineering 551 How to handle a request? class TCPConnection { private TCPState _state;//current state void Connect() { _state.Connect(this); //delegate } public void ChangeState(TCPState nextState) { _state = nextState; }

158 Department of Information Engineering 552 To change the state of TCPConnection The concrete object TCPState does the work, then use ChangeState() to change _state in TCPConnection to next state class TCPClosed : TCPState { void ActiveOpen(TCPConnection t) { //... send SYN t.ChangeState(TCPSynSent.Instance); } Static property returning a Singleton of TCPSynSent

159 Department of Information Engineering 553 State For each concrete TCPState, only implement the functions that is meaningful –Meaningless requests can be ignored –Base class TCPState provides the dummy default A do-nothing dummy default public override void TCPState.Connect(TCPConnection t){}

160 Department of Information Engineering 554 Singleton None of the TCPState subclass has local state variables ! If the objects are stateless (have no memory) –Only need one object for each TCPState is enough –Singleton –Singleton object can be accessed directly

161 Department of Information Engineering 555 Singleton socket TCPConnection socket TCPConnection socket TCPConnection TCPState TCPListen TCPClosed... Singleton, shared by all connections

162 Department of Information Engineering 556 Problem How to encapsulate an algorithm so that your software can select between different algorithms flexibly? e.g. –In word processing, choose between the different output formatter (pdf, postscript, rtf) –In action game, fighters can have different algorithm for different fighting level

163 Department of Information Engineering 557 Solution by subclassing But subclassing makes it difficult for an object to change the algorithm at run time The algorithm is statically binded to the concrete object Base Class void Algo(); Derived Class A void Algo(); Derived Class B void Algo();

164 Department of Information Engineering 558 Strategy Object delegation –the base class object is free to change the strategy object at run time Base Strategy _s; void Algo() {_s->Algo();} Strategy void Algo(); Derived class A void Algo(); Derived class B void Algo();

165 Department of Information Engineering 559 State and Strategy Same class diagram, same pattern of code ! –Differed by their intent and dynamics State’s intent –Allow an object to alter its behavior when its internal state changes Strategy’s intent –Define a family of algorithm, encapsulate each one, and make them interchangeable

166 Department of Information Engineering 560 Problem How to add new functionality to a system? –e.g to add a print option to the registration system Solution –Add Print() to the base class Node Search() Print() NodeList Search() Print()... Course Search() Print()...

167 Department of Information Engineering 561 Problem Modify the base class, violate the open-close principle! Solution –Visitor Pattern –Visitor lets you define a new operation without changing the classes of the elements on which it operates

168 Department of Information Engineering 562 How it works Accept() is a general-purpose method that can accept a Visitor object Node Accept(Visitor v) NodeList Accept(Visitor v) Node[] _list Course Accept(Visitor v)

169 Department of Information Engineering 563 Visitor Pattern A node accepts a visitor object –Node.Accept(Visitor v); Node.Accept() immediately returns the call to Visitor and pass itself as the argument –v.Visit(this); //this=the current node Visitor.Visit(Node n) receives the node and does something about it –e.g. print the node, search the node

170 Department of Information Engineering 564 Code example If the concrete node is a Course object Course.Accept(Visitor v) { v.Visit(this);//callback } If the concrete node is a NodeList object NodeList.Accept(Visitor v) { v.Visit(this); //process the list foreach (Node n in _list) { n.Accept(v); //call each node in list }

171 Department of Information Engineering 565 Node Accept(Visitor v) NodeList Course Visitor Visit(Node n) SearchVisitor Visit(Node n) //doSomething PrintVisitor Visit(Node n) //doSomething client

172 Department of Information Engineering 566 Note Node usually has a tree (composite) structure –The visitor object transverses all nodes in the tree –Each node callbacks to the visitor ; visitor provides the new functionality To add new functionality –simply add a new subclass of visitor, –no need to modify the object structure ( Node )

173 Department of Information Engineering 567 Visitor Pattern Refinement –Both Course and NodeList make a callback to the same visitor(Node n) method –Sometime we would like to treat callback from Course and NodeList differently, –e.g. PrintCourseName visitor If callback from a Course node, print the course name If callback from a NodeList, do nothing

174 Department of Information Engineering 568 Visitor Pattern Solution by function overloading –Overload the callback function Visit(), so as to treat Course and NodeList differently class Visitor { public void Visit(Course n) {//...} public void Visit(NodeList n){//...} }

175 Department of Information Engineering 569 Code example If the concrete node is a Course object Course.Accept(Visitor v) { v.Visit(this);//call Visit(Course n) } If the concrete node is a NodeList object NodeList.Accept(Visitor v) { v.Visit(this); //call Visit(NodeList n)... }

176 Department of Information Engineering 570 Double dispatch What we have just seen is an example of double dispatch implemented using the Visitor pattern Single dispatch – Call a function based on Type of one receiver (the object) Name of the function –e.g. obj.Foo() Type of object is known Function name

177 Department of Information Engineering 571 Double dispatch Call a function based on –Type of two receivers –Name of the function –e.g. obj.Foo(obj2) C# and Java support only single dispatch –Polymorphism is limited to the type of one object Type of two receivers of polymorphic type

178 Department of Information Engineering 572 Example of double dispatch Shape class –Base class: Shape –Sub-class: Rectangle, Circle A function to check whether two Shape objects intersect –class Shape { bool virtual Intersect(Shape s) {...} }

179 Department of Information Engineering 573 Why single dispatch is not enough Shape s1 = new Rectangle(); Shape s2 = new Circle(); bool flag = s1.Intersect(s2); What we want –To invoke Rectangle.Intersect(Circle s) What we get –Invoke Rectangle.Intersect(Shape s) –Intersect(Circle s) is not called because s2 is upcasted to Shape Problem –Need to find out the type of s

180 Department of Information Engineering 574 Solution 1: if-then-else block public class Rectangle : Shape { public bool Intersect(Shape s) { //if s is a rectangle, call Intersect(Rectangle s) //else if s is a circle, call Intersect(Circle s) } public bool Intersect(Circle s) {...} } If-then-else block is a bad thing in OO, because your code knows too much about the Shape Languages that support double dispatch can check the type of s2 dynamically and call Intersect(Circle s), but C# (and Java) only supports single dispatch

181 Department of Information Engineering 575 Solution 2: Visitor class Shape { public bool virtual Intersect(Shape s); } class Rectangle : Shape { public bool override Intersect(Shape s) {...}... } s1.Intersect(s2) –s1 is a rectangle, Rectangle.Intersect(Shape) is called –Rectangle.Intersect(Shape s) { s.Intersect(this); //visitor callback } –s is a Circle, this is a Rectangle (function overloading), Circle.Intersect(Rectangle) is called

182 Department of Information Engineering 576 Visitor pattern Shape Intersect(Shape s); Rectangle Intersect(Shape s); Intersect(Rectangle s); Intersect(Circle s); Circle Intersect(Shape s); Intersect(Rectangle s); Intersect(Circle s); return s.Intersect(this) s1.Intersect(s2)

183 Department of Information Engineering 577 Multiple dispatch Can extend the idea to triple or quadruple dispatch; this is known as multiple dispatch There are languages that support multiple dispatch –CLOS, MultiJava Also known as multiple polymorphism

184 Department of Information Engineering 578 Inheritance versus delegation Inheritance –separation of interface and implementation –abstract programming depends on it But Design Pattern favors object composition or delegation over class inheritance Why delegate? –Class should have a well defined responsibility –If a class has too many responsibilities, then we should move some responsibilities to another classes –The simplification reduces the size of the class, making it easier to maintain and to reuse

185 Department of Information Engineering 579 An example from a newsgroup public class HashTable { //... public void addManyElements(Element[] e) { //... } public void addElement(Element e) { //... } } How to have a HashTable that counts the number of its elements?

186 Department of Information Engineering 580 Solution by inheritance public class CountedHashTable : HashTable { //... private int count; public void addManyElements(Element[] e) { base(e); count = count + e.length; } public void addElement(Element e) { base(e); count = count + 1; } } Later it is found that the counter double counted when addManyElements() is called, why?

187 Department of Information Engineering 581 Solution by inheritance This problem is caused by the implementation of addManyElements() in HashTable public void addManyElements(Element[] e) { for (int i = 0; i < e.length; i++) { this.addElement(e[i]); } } This example shows that it is impossible for subclasses to inherit from a class without knowing at least part of its implementation, Therefore inheritance breaks encapsulation !!

188 Department of Information Engineering 582 Solution by delegation / composition A better solution is to use interface and composition public interface IHash { public addManyElements(Element[] e); public addElement(Element e); } public class HashTable : IHash { //... public void addManyElements(Element[] e) { //... } public void addElement(Element e) { //... } }

189 Department of Information Engineering 583 Solution by delegation / composition public class CountedHashTable : IHash { private HashTable hashTable; //has-a private int count; public addManyElements(Element[] e) { hashTable.addManyElements(e); //delegate count = count + e.Length; } public addElement(e) { hashTable.addElement(e); count = count + 1; } }

190 Department of Information Engineering 584 Inheritance vs delegation The example shows that –Inheritance is White-Box reuse –Delegation is Black-Box reuse White box reuse –To reuse it, you need to open the box and know details about the code –Break encapsulation Black box reuse –Closer to our understanding of reusing a component

191 Department of Information Engineering 585 Inheritance vs delegation What the example tells us –Avoid using inheritance for implementation reuse –To correctly reuse an implementation by inheritance, needs to examine the super class –Nobody wants to do this in the industry! –Much safer to reuse implementation by delegation (black box reuse)

192 Department of Information Engineering 586 Inheritance vs delegation So what is the role of inheritance? –To provide a generalization of many concrete classes –E.g. USB and concrete devices From the point of view of the concrete devices –They inheritance the interface (of USB), not the implementation Common sense, right?

193 Department of Information Engineering 587 Case study A multi-players network game –Each player has a fighter object –Player sees through the eyes of the fighter, so that each player has a different view How to write the game? –No need to reinvent the wheel, standard solution exists

194 Department of Information Engineering 588 The nature of the problem –Multiple views, common data A classic problem –A document with different views (word doc, bar chart); if document is changed, all views are updated –A trading room with many terminals, each has a different presentation of the same data A classic solution –MVC pattern –

195 Department of Information Engineering 589 MVC pattern Decompose an application into three parts –Controller (input handler) –View (output handler, the presentation) –Model (internal data and processing) View Controller Model event

196 Department of Information Engineering 590 MVC model Input is managed by the Controller Output is managed by the View State is managed by the Model The MOST important pattern in software architecture –Decouple the input, output, and the data, so that each part can be changed independent from others

197 Department of Information Engineering 591 Patterns in MVC Controller –Strategy pattern –Take care of the UI, different UI uses different controller Model-View –Observer pattern –model is the subject, views are the observers, View –Composite pattern –a CompositeView may contain more Views

198 Department of Information Engineering main patterns – Strategy, Observer, Composite user controller view model 2. change 4. get state 1.event5.draw 3.notify StrategyComposite Observer

199 Department of Information Engineering 593 Class diagram Model Observers[] o Observer Update(subject) View Controller 1 * 1 Subject Attach(observer) Detach(observer) Notify() Strategy Observer Composite

200 Department of Information Engineering 594 Structure of a fighting game Model has a container for all objects –Objects can be fighters, bullets, or simply the background –Responsible for collision detection The Model object notifies the View objects whenever it is changed –In simple game, like our project, there is only one view, so each object (fighter, bullet) can have-a view object directly –Complex game, use Observer pattern

201 Department of Information Engineering 595 Scenario – Fire a bullet If a player fires a shot, the controller handles this event Controller changes the state of the Model by adding a new bullet object to Model’s container –Model checks for collision –If bullet hits an object, the object’s state is updated Model then notifies the View objects that the state has been changed –Each View gets its state from Model and redraws itself

202 Department of Information Engineering 596 Responsibility Suppose a bullet hit an object (e.g. a fighter), –Let’s say the bullet explodes and some blood is spilled Who has the responsibility to explode and make some noise? –Bullet Who has the responsibility to spill blood? –Fighter has the responsibility to know how many cc of blood and in what color that should be spilt

203 Department of Information Engineering 597 Responsibility The most important role of a software designer is to find the right objects and to assign suitable responsibility to the objects e.g. CRC Cards

204 Department of Information Engineering 598 A few words on your project The MODEL is simply a smart container –The container only knows abstract game objects, not the concrete subtypes (e.g. arrows and balls) –Main responsibility is COLLISION DETECTION container

205 Department of Information Engineering 599 Collision detection Each game object has-a rectangle –Two objects are collided if their rectangles intersect with each other –Easy to code ! Use the C# Rectangle class, which has the intersectWith() method Even better, each game object has-a Shape –And use Shape.intersectWith() –The concrete object can have any kind of Shape object, which can be changed at run time

206 Department of Information Engineering 600 What to do with the collided objects? Who should hangle the collision? –NOT the responsibility of the container –Handled by the game objects, distributed responsibility Example –If a GameObject obj is hit, calls obj.collide() –The collision is handled by the concrete object –If obj is-a Arrow, Arrow.collide() do nothing –If obj is-a Ball, Ball.collide() breaks into smaller balls

207 Department of Information Engineering 601 To update the motion of the objects Use a real-time clock –Generates interrupts, say, every 0.1 second to the container –The container asks each of the game objects to update themselves obj.update() Each concrete object knows its motion vector, so it can calculate the new position, and draw itself –Don’t overload the container

208 Department of Information Engineering 602 How to draw the objects? In this simple game, each game object can have a draw(), which knows how to draw itself –But what if we use a different display system, the game object has to be modified For complex system, better use the observer pattern –The display is handled by the view objects –The game objects in the container callback to the view objects, notifying them that something is changed –View objects get data from model (that has the game objects), and redraw themselves –Decouple the presentation and the model

209 Department of Information Engineering 603 GameObject intersect() collide() update() draw() Arrow Ball Shape intersect() Rectangle Circle Container detectCollision() update() draw() Abstract Game Engine Controller keyInput() ConcreteController To have a different game, change the concrete objects

Download ppt "Department of Information Engineering 395 Design patterns What is a pattern? –Pattern describes a problem which occurs over and over again in our environment,"

Similar presentations

Ads by Google