Introduction to Design Pattern

Views:
 
Category: Entertainment
     
 

Presentation Description

No description available.

Comments

By: RaviSankarVN (45 month(s) ago)

Hi, very nice presentation. Can you provide a copy of this?

By: rdwivedi2510 (45 month(s) ago)

hi , being teacher of architecture design , i needs to have a copy of yours wonderful work.

By: tanujsinghal (45 month(s) ago)

i want to download this .i request u to allow to download this

By: tanujsinghal (45 month(s) ago)

presentation is very nice.

By: tanujsinghal (45 month(s) ago)

presentation is vvery good i want to be download this .i requsted u to allow to download

See all

Presentation Transcript

Introduction to Design Pattern: 

Introduction to Design Pattern Sammy Wang CS, UGA

Gang of Four Design Patterns: 

Gang of Four Design Patterns Behavioral patterns Chain of responsibility Command Interpreter Iterator Mediator Memento Observer State Strategy Template method Visitor Creational patterns Abstract factory Builder Factory method Prototype Singleton Structural patterns Adapter Bridge Composite Decorator Facade Flyweight Proxy

General Principles: 

General Principles The Single-Responsibility Principle (SRP) The Interface-Segregation Principle (ISP) The Open-Closed Principle (OCP) The Liskov Substitution Principle (LSP)

The Single-Responsibility Principle (SRP): 

The Single-Responsibility Principle (SRP) “A class should have only one reason to change” Why? Every responsibility is an axis of change. The change will be manifest/cascade

An Example of SRP Violation : 

Modem.java Interface Modem { public void dial(String pno); public void hangup(); public void send(char c); public char recv(); } An Example of SRP Violation Two responsibilities: Connection management: dial and hangup Communication management: send and recv

Refactoring: 

Refactoring <<interface>> Connection +dial(pno:String) +hangup() <<interface>> Data Channel +send(:char) +recv() Modem Implementation

Another Example of SRP Violation: 

Another Example of SRP Violation Persistence Subsystem Employee +calculatePay +Store

The Interface-Segregation Principle (ISP): 

The Interface-Segregation Principle (ISP) It deals with “fat” interface—Interface Contamination. Different client needs different services– Customized Service

The Interface-Segregation Principle (ISP): 

The Interface-Segregation Principle (ISP) Client1 Client2 <<interface>> Service1 +m1() +p2() <<interface>> Service2 +m2() +p1() Service Service includes public function: m1(), m2(), p1(), p2()

An Example of ISP Violation: 

An Example of ISP Violation Client -indexCursor Indexer -searcher Searcher <<interface>> BadExample +first() void +last() void +next() void +previous() void +getExcerpt() String +getFullRecord() String +reIndexAll() void +updateIndex() void +search(keywords String[]) void +getResult() void

Refactoring: 

Refactoring Client -indexCursor Indexer -searcher Searcher <<interface>> Indexer +reIndexAll() void +updateIndex() void <<interface>> Searcher +search(keywords String[]) void +getResult() void FileIndexer +reIndexAll() void +updateIndex() void RdbIndexer +reIndexAll() void +updateIndex() void <<interface>> ResultSet +first() void +last() void +next() void +previous() void +getExcerpt() String +getFullRecord() String Interface can’t be instantiated

The Open-Closed Principle (OCP): 

The Open-Closed Principle (OCP) Software entities (classes, modules, functions, etc) should be open to extension, but closed for modification Principle of Encapsulation of Variation (EVP) "Open For Extension" – extend/change the behavior of the module as the requirements change "Closed For Modification" - Extending the behavior of the module does not result in the changing of the source code or binary code of the module itself.

An Example of OCP Violation: 

An Example of OCP Violation Client is not open and closed: Client Server1 Server2

Refactoring: 

Refactoring STRATEGY pattern: Client is both open and closed (open to extension and closed for modification) Abstraction is the key Client <<interface>> Client Interface Server

The Liskov Substitution Principle (LSP): 

The Liskov Substitution Principle (LSP) “Subtypes must be substitutable for their base types” Whenever a method accepts a base type, it must accept the base type’s derived class. For example: If method1(Base base), Then method1(Derived derived) Base base Derived derived Tester +method1(Base)

Rectangle vs. Square: 

Rectangle vs. Square Rectangle.java public class Rectangle{ private long width; private long height; public void setWidth(long width){ this.width = width; } public long getWidth(){ return this.width; } public void setHeight(long height){ this.height = height; } public long getHeight(){ return this.height; } } Square.java public class Square{ private long side; public void setSide(long side){ this.side = side; } public long getSide(){ return side; } } Rectangle width: long height: long Square side: int

Rectangle vs. Square: 

Rectangle vs. Square Rectangle width: long height: long Square width: long height: long side: int public class Square extends Rectangle{ private long side; private long height; public void setWidth(long width){ setSide(width); } public long getWidth(){ return getSide(); } public void setHeight(long height){ setSide(height); } public long getHeight(){ return getSide(); } public long getSide(){ return side; } public void setSide(long side){ this.side = side; } }

Problem: 

Problem Rectangle width: long height: long Square width: long height: long side: int Tester +resize void Tester.java public class Tester{ public void resize(Rectangle r){ while(r.getHeight() < r.getWidth() ) r.setWidth(r.getWidth() +1 ); }

Refactoring: 

Refactoring <<interface>> Quadrangle width:long height:long Square side:long width:long height:long Ractangle width:long height:long Quardrangle.java public interface Quardrangle{ public long getWidth(); public long getHeight(); } Inheritance from abstraction, not from implementation

Source code: 

Source code Rectangle.java public class Rectangle implements Quadrangle{ private long width; private long height; public void setWidth(long width){ this.width = width; } public long getWidth(){ return this.width; } public void setHeight(long height){ this.height = height; } public long getHeight(){ return this.height; } } Square.java public class Square implements Quadrangle{ private long side; public void setSide(long side){ this.side = side; } public long getSide(){ return side; } public long getWidth(){ return getSide(); } public long getHeight(){ return getSide(); } }

Factories: 

Factories Creates Creates Creates Creates Simple Factory Factory Pattern Abstract Factory

Simple Factory: 

Simple Factory <<interface>> Fruit +grow:void +harvest:void +plant:void Grape +grow:void +harvest:void +plant:void seedless:boolean Apple +grow:void +harvest:void +plant:void treeAge:boolean Strawberry +grow:void +harvest:void +plant:void FruitGardener +factory:Fruit

Source Code: 

Source Code FruitGardener.java Public class FruitGardener{ Public static Fruit factory(String which){ if(which.equalsIgnoreCase(“apple”)) { return new Apple(); } if(which.equalsIgnoreCase(“strawberry”)) { return new Strawberry(); } if(which.equalsIgnoreCase(“grape”)) { return new grape(); } else throw new Exception(“no such fruit”); } }

Factory: 

Factory <<interface>> FruitGardener +factory: Fruit AppleGardener +factory: Fruit Strawberry Gardener +factory: Fruit GrapeGardener +factory: Fruit <<interface>> Fruit +grow:void +harvest:void +plant:void Apple +grow:void +harvest:void +plant:void Strawberry +grow:void +harvest:void +plant:void Grape +grow:void +harvest:void +plant:void Creates

Sequence Diagram: 

Sequence Diagram :Client :AppleGardener :Apple new new Factory() Apple Client.java: Public class Client{ Private static Fruit apple,grape; Private static FruitGardener aG, gG; Public static void main(String[] args){ aG = new AppleGardener(); apple = aG.factory(); gG = new GrapeGardener(); Grape = gG.factory(); } }

Abstract Factory: 

Abstract Factory

Garden Example: 

Garden Example <<interface>> Gardener <<interface>> Fruit TropicalGardener +createFruit:Fruit +createVeggie:Veggie TropicalFruit +TropicalFruit name:String NorthenGardener +createFruit:Fruit +createVeggie:Veggie NorthernFruit +NorthernFruit name:String <<interface>> Veggie TropicalVeggie +TropicalVeggie name:String NorthernVeggie +NorthernVeggie name:String Creates Creates

Source Code1: 

Source Code1 Interface Gardener: public interface Gardener{} NorthernGardener.java: public class NorthernGardener implements Gardener{ public Fruit createFruit(String name){ return new NorthernFruit(name); } public Veggie createVeggie(String name){ return new NorthernVeggie(name); } } TropicalGardener.java: public class TropicalGardener implement Gardener{ public Fruit createFruit(String name){ return new TropicalFruit(name); } public Veggie createVeggie(String name){ return new TropicalVeggie(name); } }

Source Code2: 

Source Code2 interface Veggie: public interface Veggie{} NorthernVeggie.java: public class NorthernVeggie(String name){ private String name; public NorthernVeggie(String name){ this.name = name;} public String getName(){ return name; } public void setName(String name){ this.name = name; } } TropicalVeggie.java: public class TropicalVeggie(String name){ private String name; public TropicalVeggie(String name){ this.name = name;} public String getName(){ return name; } public void setName(String name){ this.name = name; } } interface Fruit: public interface Fruit{} Northern Fruit.java: public class NorthernFruit(String name){ private String name; public NorthernFruit(String name){ this.name = name;} public String getName(){ return name; } public void setName(String name){ this.name = name; } } TropicalFruit.java: public class TropicalFruit(String name){ private String name; public TropicalFruit(String name){ this.name = name;} public String getName(){ return name; } public void setName(String name){ this.name = name; } }

Another Example: 

Another Example WinFactory +createButton: Void +createMenu: Void OSXFactory +createButton: Void +createMenu: Void <<interface>> Button +paint:void Creates <<interface>> GUIFactory + createButton:void WinButton Creates OSXButton <<interface>> Menu WinMenu OSXMenu

Source Code: 

Source Code /* * GUIFactory example */ public abstract class GUIFactory { public static GUIFactory getFactory() { int sys = readFromConfigFile("OS_TYPE"); if (sys == 0) { return(new WinFactory()); } else { return(new OSXFactory()); } } public abstract Button createButton(); } class WinFactory extends GUIFactory { public Button createButton() { return(new WinButton()); } } class OSXFactory extends GUIFactory { public Button createButton() { return(new OSXButton()); } } public abstract class Button { private String caption; public abstract void paint(); public String getCaption(){ return caption; } public void setCaption(String caption){ this.caption = caption; } } class WinButton extends Button { public void paint() { System.out.println("I'm a WinButton: “ +caption); } } class OSXButton extends Button { public void paint() { System.out.println("I'm a OSXButton: “ +caption); } } public class Application { public static void main(String[] args) { GUIFactory aFactory = GUIFactory.getFactory(); Button aButton = aFactory.createButton(); Menu aMenu = aFactory.createMenu(); aButton.setCaption("Play Button"); aButton.paint(); aMenu.setCaption("Play Menu"); aMenu.paint(); } //output is I'm a WinButton: Play Button I'm a WinMenu: Play Menu OR I'm a OSXButton: Play Button I'm a OSXMenu: Play Menu

Composite Design Pattern: 

Composite Design Pattern This pattern allows a client object to treat both single components and collections of components identically: file system recursive AWT & SWING Bi-direction, leaf holds reference to composite Cache leaf to enhance performance Two variation: transparent pattern and safe pattern

Safety Style Class Diagram: 

Safety Style Class Diagram Composite +defaultMethod() +getChild() +addComponent +removeComponent Leaf +defaultMethod() <<interface>> Component +defaultMethod() 0..* Client aComponent: Component

Source Code: 

Source Code import java.util.*; interface Component { public String defaultMethod(); public ArrayList<Component> getChildren(); public boolean addComponent(Component c); public boolean removeComponent(Component c); } class Composite implements Component { private String id; private ArrayList<Component> components = new ArrayList<Component>(); public Composite(String identification) { id = identification; } public String defaultMethod(){ String s = "(" + id + ":"; for (Component child : getChildren()) s = s + " " + child.defaultMethod(); return s + ")"; } public ArrayList<Component> getChildren(){ return components; } public boolean addComponent(Component c) { return components.add(c); } public boolean removeComponent(Component c) { return components.remove(c); } } class Leaf implements Component { private String id; public Leaf(String identification) { id = identification; } public String defaultMethod() { return id; } } class CompositePattern { public static void main(String[] args) { Composite england = new Composite("England"); Leaf york = new Leaf("York"); Leaf london = new Leaf("London"); england.addComponent(york); england.addComponent(london); england.removeComponent(york); Composite france = new Composite("France"); france.addComponent(new Leaf("Paris")); Composite europe = new Composite("Europe"); europe.addComponent(england); europe.addComponent(france); System.out.println( europe.defaultMethod() ); } } //output: (Europe: (England: London) (France: Paris))

Transparent Style Class Diagram: 

Transparent Style Class Diagram Client aComponent: Component <<interface>> Component +defaultMethod() +getChild() +addComponent +removeComponent 0..* Composite +defaultMethod() +getChild() +addComponent +removeComponent class Leaf implements Component { private String id; public Leaf(String identification) { id = identification; } public String defaultMethod() { return id; } public ArrayList<Component> getChildren() { return null; } public boolean addComponent(Component c) { return false; } public boolean removeComponent(Component c) { return false; } }

Another Safety Style Example: 

Another Safety Style Example Graphics +draw:void Line +draw:void Rectangle +draw:void Circle +draw:void Picture -list:Vector +draw:void +add:void +remove:void +getChild:Graphics

Source Code: 

Source Code abstract public class Graphics{ public abstract void draw(); } public class Picture extends Graphics{ private Vector<Graphics> list; list = new Vector(10); public void draw(){ for(int i=0;i<list.size();i++){ Graphics g=list.get(i); g.draw(); } } public void add(Graphics g){ list.add(g); } public void remove(Graphics g){ list.remove(g); } public Graphics getChild(int i){ return list.get(i); } } public class Line extends Graphics{ public void draw(){ //code for drawing line }} public class Rectangle extends Graphics{ public void draw(){ //code for drawing rectangle }} public class Circle extends Graphics{ public void draw(){ //code for drawing circle }}

The Strategy Pattern: 

The Strategy Pattern Define a family of algorithms, encapsulate each one, and make them interchangeable. It lets the algorithm vary independently from clients that use it. – [GOF] It embodies two principles—encapsulate the concept that varies and program to an interface, not an implementation. loosely coupled collection of interchangeable parts vs. monolithic, tightly coupled system extensible, maintainable, and reusable if/else problem Strategy: behavior/dynamic vs. Bridge: static

Class Diagram: 

Class Diagram

Pros and Cons: 

Pros and Cons Moving the common code from detailed strategy class to its base abstract class Hiding complex detail information from client Client decides to use which strategy dynamically

Sort Sample: 

Sort Sample Sorter/Client +sort:void +add(String):void +setSortStrategy: SortStrategy BubbleSort +sort:void HeapSort +sort:void QuickSort +sort:void SortStrategy +sort:void

How to Invoke: 

How to Invoke static void Main( { Sorter studentRecords = new Sorter();studentRecords.add("Samual");studentRecords.add("Jimmy");studentRecords.add("Sandra");    studentRecords.setSortStrategy(new QuickSort());studentRecords.sort();studentRecords.SetSortStrategy(new HeapSort());studentRecords.sort();   }

Discount Sample: 

Discount Sample Client NoDiscount -price:double -copies:int +NoDiscount +caclDiscount:double FlatRate -price:double -copies:int +NoDiscount +caclDiscount:double amount:double Percentage -price:double -copies:int +NoDiscount +caclDiscount:double percent:double DiscountStrategy +caclDiscount:double

Source Code: 

Source Code public abstract class DiscountStrategy{ private single price = 0; private int copies = 0; public abstract single calcDiscount(); public DiscountStrategy(single price, int copies){ this.price = price; this.copies = copies; } } public class NoDiscount extends DiscountStategy{ private single price = 0; private int copies = 0; public NoDiscount (single price, int copies){ this.price = price; this.copies = copies; } public single calcDiscount(){ return 0; } } public class Percentage extends DiscountStategy{ private single percent; private single price = 0; private int copies = 0; public Percentage (single price, int copies){ this.price = price; this.copies = copies; } public single getPercentage(){ return percent; } public void setPercentage(single percent){ this.percent = percent; } public single calcDiscount(){ return copies*price*percent; } } public class Client{ public static void main(String[] args) { DiscountStrategy a=new Percentage( 100,1000); a.setPercentage(0.1); double discount=a.calcDiscount(); }

If/Else Problem: 

If/Else Problem public class Client{ private int copies; private double price; private String discountType; private double amount; private double percent; public double calcDiscount(String discountType, int copies, double price) { if(discountType.equals(“NoDiscount”) return copies*price; else( if(discountType.equals(“FlatDiscount”) return copies*price-amount; else( if(discountType.equals(“PercentageDiscount”) … …} }

Decorator Design Pattern: 

Decorator Design Pattern Wrapping the new "decorator" object around the original object typically by passing the original object as a parameter to the constructor of the decorator, with the decorator implementing the new functionality. the interface of the original object needs to be maintained by the decorator. Transparent vs. semi-transparent style Decorator: adding new behavior at runtime vs. subclassing: adding new behavior at compile time

Class Diagram: 

Class Diagram Concrete Component Decorator

Sequence Diagram: 

Sequence Diagram Original Class

Java I/O Decorator: 

Java I/O Decorator Reader +read() FileReader +read() BufferedReader +read() +readLine() LineNumberReader +read() +readLine() +getLineNumber()

Sequence Diagram: 

Sequence Diagram

Slide 51: 

import java.io.BufferedReader;import java.io.FileReader; import java.io.LineNumberReader; public class Tester { public static void main(String args[]) { read("c:\\result.xml"); } public static void read(String filename) { try { FileReader frdr = new FileReader(filename); BufferedReader brdr = new BufferedReader(frdr); LineNumberReader lrdr = new LineNumberReader(brdr); //Reader rdr = new LineNumberReader(brdr); for(String line; (line = lrdr.readLine()) != null;) { //rdr.read(); //read a single character System.out.print(lrdr.getLineNumber() + ":\t"); printLine(line); } } catch(java.io.FileNotFoundException fnfx) { fnfx.printStackTrace(); } catch(java.io.IOException iox) { iox.printStackTrace(); } } private static void printLine(String s) { for(int c, i=0; i < s.length(); ++i) { c = s.charAt(i); if(c == '\t') System.out.print(" "); else System.out.print((char)c); } System.out.println(); } }

References: 

References Agile Software Development by Robert C. Martin Gang of Four Design Patterns Design Patterns by Yanhong http://www.tml.tkk.fi/~pnr/GoF-models/html/ http://en.wikipedia.org/wiki/Image:Abstract_factory_UML.svg http://en.wikipedia.org/wiki/Composite_pattern http://en.wikipedia.org/wiki/Decorator_pattern http://www.javaworld.com/cgi-bin/mailto/x_java.cgi