1 / 53

Design Patterns CS 406 Software Engineering I Fall 2001

Design Patterns CS 406 Software Engineering I Fall 2001. Aditya P. Mathur Purdue University. October 30, 2001. Organization. Patterns: Behavioral: Observer Structural: Façade Creational Abstract Factory Factory Method Singleton Excellent reference:

tab
Download Presentation

Design Patterns CS 406 Software Engineering I Fall 2001

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Design PatternsCS 406 Software Engineering IFall 2001 Aditya P. Mathur Purdue University October 30, 2001

  2. Organization Patterns: Behavioral: Observer Structural: Façade Creational Abstract Factory Factory Method Singleton Excellent reference: Design Patterns book by Erich Gamma, et al., Addison-Wesley, 1994. CS 406: Design Patterns

  3. Design Patterns [1] • A solution to a problem that occurs repeatedly in a variety of contexts. • Each pattern has a name. • Use of each pattern has consequences. CS 406: Design Patterns

  4. Design Patterns [2] • Generally at a “higher level” of abstraction. • Not about designs such as linked lists or hash tables. • Generally descriptions of communicating objects and classes. CS 406: Design Patterns

  5. Observer Pattern [1] • Need to separate presentational aspects with the data, i.e. separate views and data. • Classes defining application data and presentation can be reused. • Change in one view automatically reflected in other views. Also, change in the application data is reflected in all views. • Defines one-to-many dependency amongst objects so that when one object changes its state, all its dependents are notified. CS 406: Design Patterns

  6. Relative Percentages A B C D A X 15 35 35 15 D B Y 10 40 30 20 C Z 10 40 30 20 A B C D A=10% B=40% C=30% D=20% Application data Change notification Requests, modifications Observer Pattern [2] CS 406: Design Patterns

  7. observers Observer Update() Subject For all x in observers{ x  Update(); } attach (Observer) detach (Observer) Notify () Concrete Observer Concrete Subject subject Update() GetState() SetState() observerState subjectState observerState= subject  getState(); Observer Pattern [3] CS 406: Design Patterns

  8. :ConcreteSubject :ConcreteObserver-1 :ConcreteObserver-2 SetState() Notify() Update() GetState() Update() GetState() Class collaboration in Observer CS 406: Design Patterns

  9. Abstract class defining the Observer interface. Note the support for multiple subjects. Observer Pattern: Observer code class Subject; class observer { public: virtual ~observer; virtual void Update (Subject* theChangedSubject)=0; protected: observer (); }; CS 406: Design Patterns

  10. Abstract class defining the Subject interface. Observer Pattern: Subject Code [1] class Subject { public: virtual ~Subject; virtual void Attach (observer*); virtual void Detach (observer*) ; virtual void Notify(); protected: Subject (); private: List <Observer*> *_observers; }; CS 406: Design Patterns

  11. Observer Pattern: Subject Code [2] void Subject :: Attach (Observer* o){ _observers -> Append(o); } void Subject :: Detach (Observer* o){ _observers -> Remove(o); } void Subject :: Notify (){ ListIterator<Observer*> iter(_observers); for ( iter.First(); !iter.IsDone(); iter.Next()) { iter.CurrentItem() -> Update(this); } } CS 406: Design Patterns

  12. Observer Pattern: A Concrete Subject [1] class ClockTimer : public Subject { public: ClockTimer(); virtual int GetHour(); virtual int GetMinutes(); virtual int GetSecond(); void Tick (); } CS 406: Design Patterns

  13. Observer Pattern: A Concrete Subject [2] ClockTimer :: Tick { // Update internal time keeping state. // gets called on regular intervals by an internal timer. Notify(); } CS 406: Design Patterns

  14. Override Observer operation. Override Widget operation. Observer Pattern: A Concrete Observer [1] class DigitalClock: public Widget, public Observer { public: DigitalClock(ClockTimer*); virtual ~DigitalClock(); virtual void Update(Subject*); virtual void Draw(); private: ClockTimer* _subject; } CS 406: Design Patterns

  15. Observer Pattern: A Concrete Observer [2] DigitalClock ::DigitalClock (ClockTimer* s) { _subject = s; _subjectAttach(this); } DigitalClock ::~DigitalClock() { _subject->Detach(this); } CS 406: Design Patterns

  16. Check if this is the clock’s subject. Observer Pattern: A Concrete Observer [3] void DigitalClock ::Update (subject* theChangedSubject ) { If (theChangedSubject == _subject) { Draw(); } } void DigitalClock ::Draw () { int hour = _subject->GetHour(); int minute = _subject->GeMinute(); // etc. // Code for drawing the digital clock. } CS 406: Design Patterns

  17. Observer Pattern: Main (skeleton) ClockTimer* timer = new ClockTimer; DigitalClock* digitalClock = new DigitalClock (timer); CS 406: Design Patterns

  18. When to use the Observer Pattern? • When an abstraction has two aspects: one dependent on the other. Encapsulating these aspects in separate objects allows one to vary and reusethem independently. • When a change to one object requires changing others and the number of objects to be changed is not known. • When an object should be able to notify others without knowing who they are. Avoid tight coupling between objects. CS 406: Design Patterns

  19. Observer Pattern: Consequences • Abstract coupling between subject and observer. Subject has no knowledge of concrete observer classes. (What design principle is used?) • Support for broadcast communication. A subject need not specify the receivers; all interested objects receive the notification. • Unexpected updates: Observers need not be concerned about when then updates are to occur. They are not concerned about each other’s presence. In some cases this may lead to unwanted updates. CS 406: Design Patterns

  20. Client Classes Need to communicate with Subsystem classes FacadePattern: Problem CS 406: Design Patterns

  21. Client Classes Subsystem classes FacadePattern: Solution Facade CS 406: Design Patterns

  22. FacadePattern: Why and What? • Need to provide a simple interface to many, often small, classes. But not necessarily to ALL classes of the subsystem. • Subsystems often get complex as they evolve. • Façade provides a simple default view good enough for most clients. • Facade decouples a subsystem from its clients. • A façade can be a single entry point to each subsystem level. This allows layering. CS 406: Design Patterns

  23. FacadePattern: Participants and Communication • Clients communicate with subsystem classes by sending requests to façade. • Participants: Façade and subsystem classes • Façade forwards requests to the appropriate subsystem classes. • Clients do not have direct access to subsystem classes. CS 406: Design Patterns

  24. FacadePattern: Benefits • Promotes weak coupling between subsystem and its clients. • Shields clients from subsystem classes; reduces the number of objects that clients deal with. • Helps in layering the system. Helps eliminate circular dependencies. CS 406: Design Patterns

  25. Compiler Compile() Invocations Stream Scanner Token BytecodeStream Parser Symbol CodeGenerator PnodeBuilder Pnode RISCCodegenerator StackMachineCodegenerator Example: A compiler StatementNode ExpressionNode CS 406: Design Patterns

  26. Façade Pattern: Code [1] class Scanner { // Takes a stream of characters and produces a stream of tokens. public: Scanner (istream&); virtual Scanner(); virtual Token& Scan(); Private: istream& _inputStream; }; CS 406: Design Patterns

  27. Façade Pattern: Code [2] class parser { // Builds a parse tree from tokens using the PNodeBuilder. public: Parser (); virtual ~Parser() virtual void Parse (Scanner&, PNodeBuilder&); }; CS 406: Design Patterns

  28. virtual Pnode* NewVariable ( Char* variableName ) const; virtual Pnode* NewAssignment ( Pnode* variable, Pnode* expression Private: ) const; Pnode* _node; }; Façade Pattern: Code [3] // Builds a parse tree incrementally. Parse tree // consists of Pnode objects. class Pnodebuilder { public: Pnodebuilder (); // Node for a variable. // Node for an assignment. // Similarly...more nodes. CS 406: Design Patterns

  29. // Manipulate program node. virtual void GetSourcePosition (int& line, int& index); // Manipulate child node. virtual void Add (Pnode*); virtual void Remove (Pnode*); // …. virtual void traverse (Codegenerator&); // Traverse tree to generate code. protected: PNode(); }; Façade Pattern: Code [4] // An interface to manipulate the program node and its children. class Pnode { public: CS 406: Design Patterns

  30. // Manipulate program node. virtual void Visit (StatementNode*); virtual void Visit (ExpressionNode*); // …. Protected: CodeGenerator (BytecodeStream&); BytecodeStream& _output; }; Façade Pattern: Code [5] // Generate bytecode. class CodeGenerator { public: CS 406: Design Patterns

  31. }; }; Façade Pattern: Code [6] void ExpressionNode::Traverse (CodeGenerator& cg) { cg.Visit (this); ListIterator<Pnode*> i(_children); For (i.First(); !i.IsDone(); i.Next();{ i.CurrentItem()Traverse(cg); CS 406: Design Patterns

  32. Could also take a CodeGenerator Parameter for increased generality. Compiler(); virtual void Compile (istream&, BytecodeStream&); } void Compiler:: Compile (istream& input, BytecodeStream& output) { Scanner scanner (input); PnodeBuilder builder; Parser parser; parser.Parse (scanner, builder); RISCCodeGenerator generator (output); Pnode* parseTree = builder.GetRootNode(); parseTreeTraverse (generator); Façade Pattern: Code [7] // Façade. Offers a simple interface to compile and // Generate code. class Compiler { public: } CS 406: Design Patterns

  33. FacadePattern: Another Example from POS [1] • Assume that rules are desired to invalidate an action: • Only one item can be purchased using a gift certificate. • Suppose that when a new Sale is created, it will be paid by a gift certificate • Hence, subsequent enterItem operations must be invalidated in some cases. (Which ones?) How does a designer factor out the handling of such rules? CS 406: Design Patterns

  34. FacadePattern: Another Example [2] • Define a “rule engine” subsystem (e.g. POSRuleEngineFacade). • Calls to this façade are placed near the start of the methods that need to be validated. • It evaluates a set of rules against an operation and indicates if the rule has invalidated an operation. • Example: Invoke the façade to check if a new salesLineItem created by makeLineItem is valid or not. (See page 370 of Larman.) CS 406: Design Patterns

  35. Reuse the main body of an Application and write the code it calls Main body of an Application Defines the architecture Of the application Calls a procedure or A method Toolkit Framework Toolkits and Frameworks Toolkits: Collection of related and reusable classes e.g. C++ I/O stream library Framework: A set of cooperating classes that make up a reusable design for a specific class of applications e.g. drawing, compilers, CAD/CAM etc. CS 406: Design Patterns

  36. Toolkits and Frameworks Advantages and disadvantages of using frameworks. 1. When using frameworks, what defines the architecture of the application? 2. What is more difficult to design: Application, toolkit, or frameworks? 3. How do changes in framework effect an application? 4. How do design patterns differ from frameworks? CS 406: Design Patterns

  37. Abstract Factory: The Problem 1. Consider a user interface toolkit to support multiple look-and-feel standards. 2. For portability an application must not hard code its widgets for one look and feel. How to design the application so that incorporating new look and feel requirements will be easy? CS 406: Design Patterns

  38. Abstract FactoryPattern: Solution[1] 1. Define an abstract WidgetFactory class. 2. This class declares an interface to create different kinds of widgets. 3. There is one abstract class for each kind of widget and concrete subclasses implement widgets for different standards. 4. WidgetFactory offers an operation to return a new widget object for each abstract widget class. Clients call these operations to obtain instances of widgets without being aware of the concrete classes they use. CS 406: Design Patterns

  39. Client WidgetFactory Window CreateScrollbar() WWindow CreateWindow() MacWindow ScrollBar WWidgetFactory MacScrollBar WScrollBar MacWidgetFactory One for each standard. Abstract Factory: Solution[2] CS 406: Design Patterns

  40. AbstractFactory ConcreteFactory2 Client ProductA1 ProductA2 AbstractProductA AbstractProductB CreateScrollbar() CreateProductA() CreateWindow() CreateProductB() ConcreteFactory1 ProductB2 ProductB1 Abstract Factory: Solution[2] CS 406: Design Patterns

  41. Abstract FactoryPattern: Participants and Communication • ConcreteFactory: Implements the operations to create concrete product objects. • AbstractFactory: Declares the interface for operations to create abstract product objects • AbstractProduct: Declares an interface for a type of product object. • ConcreteProduct: Defines a product object to be created by the corresponding factory. • Client: Uses only the interface declared by the abstractFactory and AbstractProduct classes. CS 406: Design Patterns

  42. virtual Maze* MakeMaze() const { return new Maze;} virtual Wall* MakeWall() const virtual Wall* MakeRoom(int n) const { return new Wall;} { return new Room;} Abstract Factory Pattern: Code [1] // Creates components of mazes. // Builds rooms, walls, and doors. class MazeFactory { public: MazeFactory(); // This factory is a collection of // factory methods. Also, this class // acts both as Abstract and Concrete // Factory // more methods. } CS 406: Design Patterns

  43. Abstract Factory Pattern: Code [1] Maze* MazeGame:: CreateMaze (MazeFactory& factory) // Builds a maze. Maze* aMaze = factory.MakeMaze(); Room* myroom = factory.MakeRoom(1); Room* herroom = factory.MakeRoom(2); Door* aDoor = factory.MakeDoor(myRoom,herRoom) aMaze AddRoom(myRoom) // One can also create a // BombedMazeFactory with // different types of Rooms // and Walls. aMaze AddRoom(herRoom) // More code to add walls. } CS 406: Design Patterns

  44. Factory Method: The Problem [1] 1. Frameworks use abstract classes to define and maintain relationships between objects 2. Consider a framework for applications that present multiple documents to the user. A drawing application is an example. 3. This framework defines two abstract classes: application and document. These ought to be sub classed by clients for application specific implementation. 4. The application class will create and manage documents when required, e.g. when a New command is selected from the menu. CS 406: Design Patterns

  45. Factory Method Pattern: The Problem [2] 5. Document sub class is application specific. Hence the Application class does not know what kind of document to create! 6. Problem: The framework must instantiate classes but it only knows about the abstract classes, which it cannot initiate! CS 406: Design Patterns

  46. Factory Method Pattern: Solution[1] 1. The Factory Method pattern encapsulates the knowledge of which Document subclass to create and moves this knowledge out of the framework. 2. Application subclasses redefine an abstract CreateDoc() method to return the appropriate Document subclass. 3. When an Application is instantiated, it can instantiate application specific Documents without knowing their class. CS 406: Design Patterns

  47. Factory method docs Application 1 * CreateDoc() NewDoc() OpenDoc() Document Open() Close() Save() MyApplication CreateDoc() MyDocument Document* doc=CreateDoc(); docs.Add(doc); docOpen(); Factory Method: Solution[2] CS 406: Design Patterns

  48. Creator Product FactoryMethod() SomeOperation() product=Factory method ConcreteCreator FactoryMethod() ConcreteProduct Return new ConcreteProduct Factory Method Pattern: Structure CS 406: Design Patterns

  49. Factory Method Pattern: Participants and Communication • ConcreteProduct (MyDocument): Implements the Product interface. • Product (Document): Defines the interface of objects the factory method creates. • Creator (Application): Declares factory method which returns an object of type Product. Also, may define the factory method to create a Product object. • ConcreteCreator (MyApplication): Overrides the factory method to return an instance of a ConcreteProduct. CS 406: Design Patterns

  50. Other Patterns: Singleton • One may use a global variable to access an object but it does not prevent one from creating more than one instance. • Used to ensure that a class has only one instance. For example, one printer spooler object, one file system, one window manager, etc. • Instead the class itself is made responsible for keeping track of its instance. It can thus ensure that no more than one instance is created. This is the singleton pattern. CS 406: Design Patterns

More Related