Structural Design Patterns Yaodong Bi 14 December 2021
Structural Design Patterns Yaodong Bi 14 December 2021
Structural design patterns Façade n Decorator n Composite n Proxy n Adapter n Bridge n Flyweight n
Façade n Design Purpose – Provide a single and simple interface to a package of classes n Design Pattern Summary – Define a single and simple interface for clients to use the functionality of the package
Façade - examples n A compiler package – It normally contains many classes/subpackages like Scanner, Parser, etc. – Most clients only want to compile their programs, i. e. , they don’t care about functions of individual components in the package – Use Façade to provide a simple default interface to most clients.
Façade - Structure Client Use op 1(), op 2(), op 3(), and op 4() Class. A Class. C op 3_a() op 4_c() Class. B op 1_b() op 2_b()
Sequence Diagram Client op 1() Facade op 1_b() op 3_a() op 4_c() op 2_b() B: Class. B A: Class. A C: Class. C
Façade - Structure Client Compiler. compile(“test. c”) Program. Node. Builder Scanner Code. Generator Parser
Façade – Sample code Class Scanner { public Scanner(Input. Stream sourcecode) public Token scan() { … } } Class Parser { public parse(Scanner s, Program. Node. Budiler p) { … } } Class Program. Node. Builder { public Program. Node new. Variable(…) { … } public Program. Node new. Assignment(…) {…} public Program. Node new. Return. Stmt(…) { …} } Class Code. Generator { public void visit. Statement. Node(…) { … } public void visit. Expression. Node(…) { … } } Class Compiler { public void compile(Input. Stream sc, Output. Stream bytecode) { Scanner sc = new Scanner(sc); Program. Node. Builder pnb = new Program. Node. Builder(); Parser parser = new Parser(); parser. parse(sc, pnb); Intel. Code. Generator cg = new Intel. Code. Generator(byte code) Program. Node nodetree = pnb. get. Root. Node(); parsetree. traverse(cg); }
Façade - Examples framework Account. Exception Customer Account get. Customer. Name() get. Num. Accounts() get. Personal. Note() get. Account( int ) get. Account. Num() deposit( int ) get. Balance() Bank. Customers Client Bank. Customer 1. . n Bank. Customers do. Deposit( int amt, Customer cust, Account acc ) get. Bank. Account( Customer cust, int acc. Num ) get. Bank. Customer( String cust. Name ) Bank. Account
Façade - comments n Façade can reduce the degree of dependency between packages – Packages are dependent on each other only through their facades, not individual classes n n Use Façade to provide a simple default view of the package that is enough for most clients Façade does not try to encapsulate/hide the components in the package since there may be clients who need to access individual components in the package
Decorator n Design Purpose – Add responsibilities to an object at runtime. n Design Pattern Summary – Provide for a linked list of objects, each encapsulating responsibility.
Decorator - examples n The word processor example – A text view may have a border and a scroll bar and maybe other bells and whistles attached to it – How can those bells and whistles be added to the text view? – Inheritance?
Decorator – structure Component operation() add(Component) remove(Component) get. Child() Client Concrete. Comp operation() Decorator Operation() void operation() { // do actions of the decorator comp. operation(); // do actions of the decorator } comp
Decorator - example
Decorator – structure Visual. Component draw() Client Text. View draw() Decorator draw() comp. draw() Scroll. Decorator draw() scroll. To() scroll. Position Border. Descrotor draw() draw. Border() border. Width super. draw() this. draw. Border()
Decorator – examples Client : Decorator 1 : Decorator 2 : Concrete. Comp
Decorator - Sequence Diagram Component Client operation() : Decorator 1 : Decorator 2 : Concrete. Comp operation() return
Decorator – examples : Reader 1 : Input. Stream. Reader System. in: Input. Stream : Buffered. Stream. Reader
Decorator – examples : Buffered. Stream. Reader : Input. Stream. Reader System. in: Input. Stream
Decorator – key concept n allows addition to and removal from objects at runtime
Decorator – sample code class Visual. Component { virtual void Draw(); virtual void Resize(); }; class Decorator : public Visual. Component { Decorator(Visual. Component*); void Decorator: : Draw () { _component->Draw(); } Visual. Component* _component; }; class Border. Decorator : public Decorator { Border. Decorator(Visual. Component*, int border. Width); void Draw(){ Decorator: : Draw(); Draw. Border(_width); } private void Draw. Border(int); private int _width; }; Class Window { void Set. Contents (Visual. Component* contents) { //. . . } Window* window = new Window(); Text. View* text. View = new Text. View; window->Set. Contents(text. View); window->Set. Contents( new Border. Decorator( new Scroll. Decorator(text. View), 1 ) ); Window. draw();
Composite n Design Purpose – Represent a Tree of Objects n Design Pattern Summary – Use a Recursive Form in which the tree class aggregates and inherits from the base class for the objects.
Composite - structure Objects Classes 1. . n Component non-leaf node “every object involved is a Compone nt object” “non-leaf nodes have one or more components” Non. Leaf. Node
Composite - structure Component Client add( Component ) Remove(component) do. It() 1. . n comp Leaf. Node do. It() Non. Leaf. Node do. It() Type. ANon. Leaf. Node do. It() for all elements e in comp e. do. It() Type. BNon. Leaf. Node do. It()
Composite – A Class Diagram : Client N 0: Non. Leaf. Node N 1: Non. Leaf. Node L 1: Leaf. Node L 2: Leaf. Node N 2: Non. Leaf. Node L 3: Leaf. Node
Composite – sequence diagram : Client do. It() N 0: Non. Leaf. Node N 1: Non. Leaf. Node L 1: Leaf. Node L 2: Leaf. Node L 3: Leaf. Node N 2: Non. Leaf. Node do. It()
Composite – examples Component 1. . n Composite in java. awt Container Window Canvas component …. .
Proxy n Design Purpose – Avoid the unnecessary execution of expensive functionality in a manner transparent to clients. n Design Pattern Summary – Interpose a substitute class which accesses the expensive functionality only when required.
Proxy – examples Client Instantiate with Proxy object Real. Active. Class expensive. Method() another. Method() Base. Active. Class expensive. Method() another. Method() Proxy expensive. Method() another. Method() if ( real. Active. Object == null ) // not loaded yet { real. Active. Object = get. Real. Active. Object(); real. Active. Object. expensive. Method(); } else { real. Active. Object. expensive. Method(); }
Proxy – sequence diagram Client Base. Active. Class Proxy Real. Active. Class expensive. Method() create() if needed expensive. Method()
Proxy – examples Instantiate with Proxy object Tex. Doc Graphics Display() graphics Image image display() bitmap Image. Proxy display() file. Name if ( image == null ) { // not loaded yet image = new Image(file. Name); } Image. display();
Proxy – Sample code Class Text. Doc { graphics g; Text. Doc(Image. Proxy ip) { g = ip; } void display() { g. display(); } } Class Image. Proxy implements Graphics { File. Name file. Name; Image image; Image. Proxy(File. Name fn) { file. Name = fn; } display() { if (image == null) image = new Image(file. Name); image. display(); } Interface Graphics { display(); } Class Image Implements Graphics { Bitmap bitmap; Image(File. Name fn) { bitmap = read. Image(fn); } display() { // draw the bitmap } read. Image(File. Name fn) { // read from the file(fn) // create a bitmap } }
Adapter n Design Purpose – Allow an application to use external functionality in a retargetable manner. n Design Pattern Summary – Write the application against an abstract version of the external class; introduce a subclass that aggregate the external class.
Adapter - examples n Interact with legacy systems – When you design a new system which has to interact with a legacy system, you may not want to the new system tightly coupled with (or dependent upon) the legacy system since the legacy system may be replaced in the future. n Using 3 rd party systems – You may want to be able to easily substitute the current 3 rd party system with another one.
Adapter - Structure Client Target Adaptee +request() Adapter +request() adaptee. requested. Method() +requested. Method(); adaptee
Adapter – sequence diagram Client Target Adapter Adaptee request(Target. In): Target. Outconvert(Target. In): Adaptee. In requested. Method(Adaptee. In): Adaptee. Out Return Target. Out convert(Adaptee. Out): Target. Out
Adapter – sample code Interface Target { public Target. Out request(Target. In); } Class Adaptee { … public Adaptee. Out requested. Method(Adaptee. In) { // produce Adaptee. Out; return Adaptee. Out; } … } Class Adapter implements Target { private Adaptee adaptee; public Adapter(Adaptee ad) { adaptee = ad; } public Target. Out request(Target. In ti) { Adaptee. In ai = convert(ti); Adaptee. Out ao = adaptee. requested. Method(ai); return convert(ao); } private Adaptee. In convert(Target. In ti) { // convert Target. In to Adaptee. In } private Target. Out convert(Adaptee. Out ao) { // convert Adaptee. Out to Target. Out } }
Adapter - Structure Drawing. Tool Shape Text. View +bounding. Box() +create. Manipulator() Text. Shape +get. Extent(); text +bounding. Box() +create. Manipulator() text. get. Extent() return new Text. Manipulator()
Adapter - comments n An adapter may have more than one adaptee – There may not be a one-to-one correspondence between operations of Target and those of Adaptee – So it is possible that an operation of Target is realized with two separate adaptee classes. n The pattern decouples Client from adaptee. – When a different adaptee is needed, we only need to change to another adapter and the client does not need to change at all.
Structural Patterns - Summary n n n Facade provides an interface to collections of objects Decorator adds to objects at runtime Composite represents trees of objects Proxy avoids calling expensive operations unnecessarily Adapter decouples client from an existing system
- Slides: 40