480 likes | 646 Views
Design Patterns. CS320 – Fundamentals of Software Engineering. Patterns. Principles and idioms codified in a structured format describing the problem, solution, and given a name are called patterns. Definition of Pattern.
E N D
Design Patterns CS320 – Fundamentals of Software Engineering
Patterns • Principles and idioms codified in a structured format describing the problem, solution, and given a name are called patterns.
Definition of Pattern • Pattern is a named problem/solution pair that can be applied in new contexts,with advice on how to apply it in novel situations and discussion of its trade-offs. • Gang of Four “Design Patterns” Book
Naming Patterns • All Patterns have suggestive names. Naming a pattern, technique, or a principle has the following advantages : • It supports chunking and incorporating that concept into our understanding and memory • It facilitates communication .
Introduction • The following Gang of Four (4 authors) design patterns are explored in the subsequent sections : • Adapter • Factory • Singleton • Strategy • Composite • Publish-Subscribe
Adapter Pattern (GOF) • Context/problem • How to resolve incompatible interfaces or provide a stable interface to similar components with different interfaces? • Solution • Convert the original interface of a component into another interface through an intermediate adapter object.
The Adapter Pattern • Adapters use interfaces and polymorphism to add a level of indirections to varying APIs in other components.
Structure of the Adapter Pattern • Class Adapter
Implementation • myStack Adapter Pattern is an Object Pattern abstract class Stack{ abstract Object top(); abstract Object pop(); abstract void push(Object v); } public class myStack { Adapter class private Vector stack = new Vector(); Adaptee object public boolean empty() {return stack.size() == 0;} pubic Object top() {return stack.lastElement();} public Object pop() { Object rslt = stack.lastElement(); stack.removeElementAt(stack.size()-1); return rslt;} void push(Object v) {stack.addElement(v);} } Target class
Factory Pattern (GoF) • Context/Problem • Who should be responsible for creating objects when there are special considerations, such as complex logic, a desire to separate the creation responsibilities for better cohesion, and so forth • Solution • Create a Pure Fabrication object called a Factory that handles the creation
Pattern: Factory(a variation of Factory Method, Abstract Factory) a class used to create other objects
Problem: Bulky GUI code • GUI code to construct many components quickly becomes redundant (here, with menus): homestarItem = new JMenuItem("Homestar Runner"); homestarItem.addActionListener(this); viewMenu.add(homestarItem); crapItem = new JMenuItem("Crappy"); crapItem.addActionListener(this); viewMenu.add(crapItem); • another example (with buttons): button1 = new JButton(); button1.addActionListener(this); button1.setBorderPainted(false); button2 = new JButton(); button2.addActionListener(this); button2.setBorderPainted(false);
Factory pattern • Factory: a class whose sole job is to easily create and return instances of other classes • a creational pattern; makes it easier to construct complex objects • instead of calling a constructor, use a static method in a "factory" class to set up the object • saves lines and complexity to quickly construct / initialize objects • examples in Java: borders (BorderFactory), key strokes (KeyStroke), network connections (SocketFactory)
Using existing factories in Java • setting borders on buttons and panels • use built-in BorderFactory class myButton.setBorder( BorderFactory.createRaisedBevelBorder()); • setting hot-key "accelerators" on menus • use built-in KeyStroke class menuItem.setAccelerator(KeyStroke.getKeyStroke('T', KeyEvent.ALT_MASK));
Factory implementation details when implementing a factory of your own: • the factory itself should not be instantiated • make constructor private • factory only uses static methods to construct components • factory should offer as simple an interface to client code as possible • don't demand lots of arguments; possibly overload factory methods to handle special cases that need more arguments • factories are often designed for reuse on a later project or for general use throughout your system
Factory example public class ButtonFactory { private ButtonFactory() {} public static JButton createButton( String text, ActionListener listener, Container panel) { JButton button = new JButton(text); button.setMnemonic(text.charAt(0)); button.addActionListener(listener); panel.add(button); return button; } }
Abstract Factory pattern: when the topmost factory class and its creational method are abstract
Advantages of Factory Objects • Separate the responsibility of complex creation into cohesive helper objects. • Hide potentially complex creation logic • Allow introduction of performance-enhancing memory management strategies,such as object caching or recycling.
Singleton Pattern (GOF) • The Factory raises a new problem in the design: • Who creates the factory itself? • How is it accessed? • One solution is pass the Factory instance around as a parameter to wherever a visibility need is discovered for it, or to initialize the objects that need visibility to it,with a permanent reference. • Alternative is Singleton pattern.
Solution • Define a static method of the class that returns the singleton. • With this approach, a developer has global visibility to this single instance,via the static getInstance method of the class.
Visibility to Single Instance public class Register { public void initialize() {… do some work… //accessing the singleton Factory via the getInstance call AccountingAdapter = ServiceFactory.getInstance(); …do some work… } //other methods…}
Lazy Initialization public static synchronized ServiceFactory getInstance() { if(instance==null) { //critical section if multithreaded application instance = new ServicesFactory(); } return instance }
Eager Initialization public class ServiceFactory { //eager initialization private static ServicesFactory instnace = new ServicesFactory(); public static servicesFactory getInstance() { Return instance; } //other methods… }
Reasons to prefer lazy Initialization • Creation work is avoided, if the instance is never actually accessed. • The getInstance lazy initialization sometimes contains complex and conditional creation logic.
Strategy Design Pattern (GoF) • Context/Problem • How to design for varying, but related,algorithms or policies? • How to design for the ability to change these algorithms or policies • Solution • Define each algorithm/policy/strategy in a separate class, with a common interface
Strategy Pattern • Many different algorithms exists for the same task • Examples: • Breaking a stream of text into lines • Parsing a set of tokens into an abstract syntax tree • Sorting a list of customers • The different algorithms will be appropriate at different times • Rapid prototyping vs delivery of final product • We don’t want to support all the algorithms if we don’t need them • If we need a new algorithm, we want to add it easily without disturbing the application using the algorithm
Strategy AlgorithmInterface Strategy Pattern Policy Context ContextInterface() * ConcreteStrategyA AlgorithmInterface() ConcreteStrategyB AlgorithmInterface() ConcreteStrategyC AlgorithmInterface() Policy decides which Strategy is best given the current Context
Strategy Sort() MergeSort Sort() QuickSort Sort() BubbleSort Sort() Applying a Strategy Pattern in a Database Application Database Search() Sort() * Strategy
Applicability of Strategy Pattern • Many related classes differ only in their behavior. Strategy allows to configure a single class with one of many behaviors • Different variants of an algorithm are needed that trade-off space against time. All these variants can be implemented as a class hierarchy of algorithms
Strategy In Collaboration • A strategy object is attached to a context object- the object to which it applies the algorithm. • In this example the context object is a sale.
Pattern: Composite objects that can serve as containers
Composite pattern • composite: an object that is either an individual item or a collection of many items • composite objects can be composed of individual items or of other composites • recursive definition: objects that can hold themselves • often leads to a tree structure of leaves and nodes: • <node> ::= <leafnode> | <compositenode> • <compositenode> ::= <node>* • examples in Java: • collections (a List of Lists) • GUI layout (panels containing panels containing buttons, etc.)
Composite example: layout Container north = new JPanel(new FlowLayout()); north.add(new JButton("Button 1")); north.add(new JButton("Button 2")); Container south = new JPanel(new BorderLayout()); south.add(new JLabel("Southwest"), BorderLayout.WEST); south.add(new JLabel("Southeast"), BorderLayout.EAST); Container cp = getContentPane(); cp.add(north, BorderLayout.NORTH); cp.add(new JButton("Center Button"), BorderLayout.CENTER); cp.add(south, BorderLayout.SOUTH);
Facade(GOF) • Context/Problem • A common, unified interface to a disparate set of implementations or interfaces- such as within a subsystem-is required.There may be undesirable coupling to many things in the subsystem, or the implementation of the subsystem may change.What to do?
Facade Pattern (GOF) (2) • Solution • Define a single point of contact to the subsystem- a facade object that wraps the subsystem. This facade object presents a single unified interface and is responsible for collaboration with the subsystem components.
Facade • A Facade is a front-end object that is the single point of entry for the services of a subsystem; the implementation and other components of the subsystem are private and can't be seen by external components. • Facade provides Protected Variations from changes in the implementation of a subsystem.
Example for a facade • Define a rule engine subsystem, whose specific implementation is not yet known.It will be responsible for evaluating a set of rules against an operation, and then indicating if any of the rules invalidated the operation. • The facade object to this subsystem will be called POSRuleEngineFacade. • The designer decides to place calls to this facade near the start of the methods that have been defined as the points for pluggable rules.
Object code for the Example public class Sale{ public void makeLineItem(Productspecification spec,int quantity){ SaleLineItem sli = new SalesLineItem(spec, quantity); //call to the Facade if(POSRuleEngineFacade.getInstance().isInvalid(sli,this) return; lineItems.add(sli);} //....}//end of class
Explanation • With this design, the complexity and implementation of how rules will be presented and evaluated are hidden in the rules engine subsystem.accessed through the POSRuleEngineFacade facade. • The subsystem hidden by the facade object could contain dozens or hundreds of classes of objects, or even a non-object-oriented solution, yet as a client to the subsystem one can see only its one public access point.
Summary of Facade Objects • The intent of Facade is to produce a simpler interface, and the intent of Adapter is to design to an existing interface. • While Facade routinely wraps multiple objects and Adapter wraps a single object
Observer/Publish-Subscribe/ Delegation Event Model • Context/Problem • Different kinds of subscriber objects are interested in the state changes or events of a publisher object, and want to react in their own unique way when the publisher generates an event. • Moreover, the publisher wants to maintain low coupling to the subscribers.
Solution • Define a subscriber or Listener interface. Subscribers implement this interface. • The publisher can dynamically register subscribers who are interested in an event, and notify when an event occurs.
The classes and/or objects participating: Subject (Stock) knows its observers. Any number of Observer objects may observe a subjec provides an interface for attaching and detaching Observer objects. ConcreteSubject (IBM) stores state of interest to ConcreteObserver sends a notification to its observers when its state changes Observer (IInvestor) defines an updating interface for objects that should be notified of changes in a subject. ConcreteObserver (Investor) maintains a reference to a ConcreteSubject object stores state that should stay consistent with the subject’s implements the Observer updating interface to keep its state consistent with the subject's
The Observer Pattern • Observer Is not only for connecting UIs and Model Objects but also used for GUI widget event handling in both Java technology and Microsoft's .Net. • One publisher can have many subscribers for an event.
Observer • Observer provides a way to loosely coupled objects in terms of communication. • Publishers know about subscribers only through an interface, and subscribers can register dynamically with the publisher.
Conclusion • Objects can be designed and responsibilities assigned with the support of patterns. • They provide an explainable set of idioms by which well designed object-oriented systems can be built.