1 / 41

Lecture 8 : Structural Patterns

Lecture 8 : Structural Patterns. Object-Oriented Design OODP Eli Katsiri. Design Principles. Modularity GRASP patterns Flexibility Separation of concerns (Impact of change) Reusability Inheritance Composition Parameterization Correctness Robustness Formal verification.

Download Presentation

Lecture 8 : Structural Patterns

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. Lecture 8 : Structural Patterns Object-Oriented Design OODP Eli Katsiri

  2. Design Principles • Modularity • GRASP patterns • Flexibility • Separation of concerns (Impact of change) • Reusability • Inheritance • Composition • Parameterization • Correctness • Robustness • Formal verification

  3. Class Composition • How classes and objects can be composed to form larger structures in order to realise new functionality! • Structural class patterns, use inheritance to compose interfaces or implementations • Multiple inheritance mixes two or more classes into one. The result is a class that combines the properties of its parent classes.

  4. Object composition • Structural object composition can be changed at run-time, which is impossible with static class composition. • This means that our objects are assembled at runtime from a number of helper classes working together to deliver the desired behaviour, rather than being statically defined at compile time using class inheritance. • Objects that are created in this favoured way offer a great deal of runtime flexibility, and are better set up for future modification. Note that the advice is to only to "favour" object composition over class inheritance, not to stop using inheritance altogether. The two techniques work well together.

  5. Structural Patterns • Adapter • Composite • Proxy • Flyweight • Façade • Bridge • Decorator

  6. Core Patterns • Adapter makes one interface conform to another, therefore providing a useful abstraction of different interfaces. Adapter inherits from Adaptee and expresses its interface in terms of the target. • Composite: How to build a class hierarch made of classes for two kinds of objects: primitive and composite. • Decorator: Acts as a decorator for another object.

  7. Adapter • Convert the interface of a class into another interface clients expect. Adapter lets classes work together that wouldn’t otherwise because of incompatible interfaces. • aka Wrapper

  8. Applicability • Use the Adapter Pattern when • You want to use an existing class, and its interface does not match the one you need • You want to create a re-usable class that cooperates with unrelated or unforseen classes, that is classes that don’t necessary have compatible interfaces.

  9. Structure

  10. Adapter: example <<interface>> IAccountingAdapter postReceivable(CreditPayment) postSale(Sale) SAPAccountingAdapter postReceivable(CreditPayment) postSale(Sale) GreatNorthernAccountingAdapter postReceivable(CreditPayment) postSale(Sale) The NextGen POS system needs to support several kinds of external third-party services, Including tax calculators, inventory systems, and accounting systems. Each has a different API Which cannot be changed. A solution is to add a level of indirection with objects that adapt the varying external interfaces to a consistent interface, used within the application.

  11. Using a (Resource) Adapter A particular Adapter instance will be instantiated for the chosen external service, such as SAP accounting, and will adapt the postSale() request to the external interface, such as SOAP XML interface over HTTPS for an internet Web Service offered by SAP

  12. Example:Window Adapter • One of the most commonly used Java adapters is the WindowAdapter class. • One of the inconveniences of Java is that windows do not close automatically when you click on the Close button or window Exit menu item. • The general solution to this problem is to have your main Frame window implement the WindowListener interface, leaving all of the Window events empty except for windowClosing.

  13. Window Listener Interface • A class which implements WindowListener must provide an implementation for each method, even it only needs to implement one e.g. windowClosing public interface WindowListener extends EventListener { public void windowOpened(WindowEvent e); public void windowClosing(WindowEvent e); public void windowClosed(WindowEvent e); public void windowIconified(WindowEvent e); public void windowDeiconified(WindowEvent e); public void windowActivated(WindowEvent e); public void windowDeactivated(WindowEvent e); }

  14. Solution 1 public void mainFrame extends Frame implements WindowListener { public void mainFrame() { addWindowListener(this); //frame listens //for window events } public void windowClosing(WindowEvent wEvt) { System.exit(0); //exit on System exit box clicked } public void windowClosed(WindowEvent wEvt){} public void windowOpened(WindowEvent wEvt){} public void windowIconified(WindowEvent wEvt){} public void windowDeiconified(WindowEvent wEvt){} public void windowActivated(WindowEvent wEvt){} public void windowDeactivated(WindowEvent wEvt){} }

  15. But.. • As you can see, this is awkward and hard to read. • The WindowAdapter class is provided to simplify this procedure. This class contains empty implementations of all seven of the above WindowEvents. • You need then only override the windowClosing event and insert the appropriate exit code. • One such simple program is shown next:

  16. Window Adapter public abstract class WindowAdapter implements WindowListener { public void windowOpened(WindowEvent e) {} public void windowClosing(WindowEvent e) {} public void windowClosed(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowActivated(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} }

  17. Extended Window Adapter //make an extended window adapter which //closes the frame when the closing event is received class WindAp extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } }

  18. Closer // illustrates using the WindowAdapter class public class Closer extends Frame { public Closer() { WindAp windap = new WindAp(); addWindowListener(windap); setSize(new Dimension(100,100)); setVisible(true); } static public void main(String argv[]) { new Closer(); } }

  19. Anonymous class • You can, however, make a much more compact, but less readable version of the same code by using an anonymous inner class: //create window listener for window close click addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e){ System.exit(0); } });

  20. Java Adapters • Adapters like these are common in Java when a simple class can be used to encapsulate a number of events. • They include • ComponentAdapter, • ContainerAdapter, • FocusAdapter, • KeyAdapter, • MouseAdapter, • MouseMotionAdapter.

  21. Composite Pattern • Compose objects into tree-structures to represent part-whole hierarchies. • Composite lets clients treat individual objects and compositions of objects uniformly. • Before we dive into the Composite pattern, I must first define composite objects: objects that contain other objects; for example, a drawing may be composed of graphic primitives, such as lines, circles, rectangles, text, and so on.

  22. Motivation • Java developers need the Composite pattern because we often must manipulate composites exactly the same way we manipulate primitive objects. • For example, graphic primitives such as lines or text must be drawn, moved, and resized. But we also want to perform the same operation on composites, such as drawings, that are composed of those primitives. • Ideally, we'd like to perform operations on both primitive objects and composites in exactly the same manner, without distinguishing between the two. If we must distinguish between primitive objects and composites to perform the same operations on those two types of objects, our code would become more complex and more difficult to implement, maintain, and extend.

  23. Example: Composite object Typically, one or more methods should be callable in the same way for either leaf or composite nodes within the hierarchy. In such a case, composite nodes typically invoke the same named method for each of their children nodes.

  24. Discussion • For example, the Composite class might represent a Drawing class. Figure’s Leaf class represents a concrete primitive object; for example, a Line class or a Text class. The Operation() methods represent domain-specific methods implemented by both the Composite and Leaf classes. • The Composite class maintains a collection of components. Typically, Composite methods are implemented by iterating over that collection and invoking the appropriate method for each Component in the collection. • For example, for the draw() operation:

  25. draw() // This method is a Composite method public void draw() { // Iterate over the components for(int i=0; i < getComponentCount(); ++i) { // Obtain a reference to the component and invoke its draw method Component component = getComponent(i); component.draw(); } }

  26. Structure The key to the Composite pattern is an abstract class that represents both primitives and their containers.

  27. Example: graphics For the graphical system, this class is Graphic. Graphic declares operations like Draw() that are specific to graphical objects. It also declares operations that all composite objects share such as operations for accessing and managing its children. Drawing Draw()

  28. Decorator Attach additional responsibilities to an object dynamically. Provide a flexible alternative to subclassing for extending functionality. aka Wrapper

  29. Decorator • Adding responsibilities through inheritance is inflexible: • Adds behaviour to all instances • Choice of how decoration occurs is made statically • Alternative: enclose the component to be decorated in another component which conforms to the interface of the component it decorates. • The change is transparent to the client. • The decorator forwards requests to the component it decorates and may perform additional actions. • Decorators can be “nested”

  30. Analogy • The ornaments that are added to pine or fir trees are examples of Decorators. Lights, garland, candy canes, glass ornaments, etc., can be added to a tree to give it a festive look. The ornaments do not change the tree itself which is recognizable as a Christmas tree regardless of particular ornaments used. As an example of additional functionality, the addition of lights allows one to "light up" a Christmas tree. • Although paintings can be hung on a wall with or without frames, frames are often added, and it is the frame which is actually hung on the wall. Prior to hanging, the paintings may be matted and framed, with the painting, matting, and frame forming a single visual component.

  31. Scroll and Border Decorators

  32. Example: Windows Suppose you are working on a user interface toolkit and you wish to support adding borders and scroll bars to windows. You could define an inheritance hierarchy like ...

  33. Dynamic construction But the Decorator pattern suggests giving the client the ability to specify whatever combination of "features" is desired. Widget  aWidget = new BorderDecorator(           new HorizontalScrollBarDecorator(                  new VerticalScrollBarDecorator(                           new Window( 80, 24 )))) aWidget.draw();

  34. Window Example:Structure The solution to this class of problems involves encapsulating the original object inside an abstract wrapper interface. Both the decorator objects and the core object inherit from this abstract interface. The interface uses recursive composition to allow an unlimited number of decorator "layers" to be added to each core object.

  35. More structure

  36. Window // the Window interface interface Window { public void draw(); // draws the Window public String getDescription(); // returns a description of the Window } // implementation of a simple Window without any scrollbars class SimpleWindow implements Window { public void draw() { // draw window } public String getDescription() { return "simple window"; } }

  37. Abstract Decorator // abstract decorator class - note that it implements Window abstract class WindowDecorator implements Window { protected Window decoratedWindow; // the Window being decorated public WindowDecorator (Window decoratedWindow){ this.decoratedWindow = decoratedWindow; } }

  38. VSBDecorator // the first concrete decorator which adds vertical scrollbar functionality class VerticalScrollBarDecorator extends WindowDecorator { public VerticalScrollBarDecorator (Window decoratedWindow) { super(decoratedWindow); } public void draw() { drawVerticalScrollBar(); decoratedWindow.draw(); } private void drawVerticalScrollBar() { // draw the vertical scrollbar } public String getDescription() { return decoratedWindow.getDescription() + ", including vertical scrollbars"; } }

  39. Test program public class DecoratedWindowTest { public static void main(String[] args) { // create a decorated Window with horizontal and vertical scrollbars Window decoratedWindow = new HorizontalScrollBarDecorator ( new VerticalScrollBarDecorator (new SimpleWindow())); // print the Window's description System.out.println(decoratedWindow.getDescription()); } }

  40. Structure In the Decorator pattern the ScrollDecorator and BorderDecorator classes are subclasses of Decorator, an abstract class for visual components that decorate other visual components. VisualComponent is the abstract class for visual objects. It defines their drawing and event handling interface. Decorating is simply done by having the Decorator class forwarding draw requests to its component, and let the Decorator subclasses extend this operation.

  41. Summary • Structural Patterns • Adapter • Composite • Decorator

More Related