wzorce projektowe

39
WZORCE PROJEKTOWE Języki i Techniki Programowania 7.XI.2003 Joanna Zięba

Upload: clare

Post on 19-Mar-2016

53 views

Category:

Documents


2 download

DESCRIPTION

WZORCE PROJEKTOWE. Języki i Techniki Programowania 7.XI.2003 Joanna Zięba. CZYM SĄ WZORCE PROJEKTOWE?. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: WZORCE PROJEKTOWE

WZORCE PROJEKTOWE

Języki i Techniki Programowania 7.XI.2003

Joanna Zięba

Page 2: WZORCE PROJEKTOWE

CZYM SĄ WZORCE PROJEKTOWE?

„Wzorzec opisuje problem powtarzający się w środowisku naszego systemu i opisuje jego rozwiązanie w taki sposób, że może ono być wykorzystane wielokrotnie i na różne sposoby” (Huston Design Patterns - home.earthlink.net/~huston2/dp/patterns.html)

Page 3: WZORCE PROJEKTOWE

ANALIZA WZORCÓWNależy wiedzieć, gdzie wzorców szukać (literatura, zasoby internetowe itp.), umieć je rozpoznawać w programach innych i wybierać najlepsze do swoich celów. Przy wyborze warto zwrócić uwagę na następujące aspekty zagadnienia:- kontekst (co, gdzie, kiedy...)- warunki wstępne- konsekwencje użycia danego rozwiązania- możliwe alternatywy (inne wzorce lub rezygnacja z ich stosowania na rzecz własnych rozwiązań)

Page 4: WZORCE PROJEKTOWE

KLASYFIKACJA WZORCÓW (konstrukcyjne, strukturalne,

behawioralne)

Page 5: WZORCE PROJEKTOWE

WZORCE KONSTRUKCYJNE(creational patterns)

Opisują jak obiekt może zostać stworzony. Powinny wyodrębniać szczegóły kreacji obiektów tak aby kod był niezależny od ich typów i nie musiał być zmieniany w miarę pojawiania się nowych rodzajów obiektów.

Przykłady: Singleton, Fabryka, Fabryka Abstrakcyjna, Prototyp, Budowniczy

Page 6: WZORCE PROJEKTOWE

SINGLETON (Singleton)Gwarantuje, że dana klasa ma tylko jeden obiekt (instancję) i zapewnić globalny sposób dostępu do tego obiektu. Obiekt stworzony wg tego wzorca może zastąpić zmienną globalną.

PODEJŚCIE: Klasę typu Singleton należy uczynić odpowiedzialną za tworzenie, inicjalizację, dostęp i ew. zmiany obiektów. Sam obiekt musi być jej składnikiem typu private static, a funkcja inicjalizacji i dostępu – public static

Page 7: WZORCE PROJEKTOWE

Prosty przykład:class Singleton {

  private Singleton s;  private int i;  private Singleton(int x) { i = x; }  public static Singleton getReference() { if (s == null) s = new Singleton(2);    return s;   }  public int getValue() { return i; }  public void setValue(int x) { i = x; }

}

Przykład z życia: „prezydent RP” – istnieje tylko co najwyżej jeden, a nazwa jednoznacznie identyfikuje sprawującą urząd osobę.

Page 8: WZORCE PROJEKTOWE

• Inne wzorce, jak Fabryka Abstrakcyjna, Budowniczy i Prototyp mogą używać Singletona w swojej implementacji

• Singletonami są często obiekty typu Fasada (zwykle potrzeba tyko jednej) oraz Stan (powinien przyjmować jedną wartość)

Page 9: WZORCE PROJEKTOWE

FABRYKA (Simple Factory)Wzorzec ten w zależności od dostarczonych danych, zwraca instancję jednej z możliwych klas. Najczęściej zwracane klasy wywodzą się z tej samej klasy podstawowej i mają takie same metody, ale każda z nich wykonuje swoje zadania w inny sposób i jest zoptymalizowana dla innego rodzaju danych.

Rozwinięciem tego wzorca jest fabryka polimorficzna – struktura gdzie istnieje klasa - fabryka bazowa i jej różne podklasy – specyficzne fabryki.

Page 10: WZORCE PROJEKTOWE

FABRYKA – SCHEMAT

Page 11: WZORCE PROJEKTOWE

abstract class Shape {  public abstract void draw();  public abstract void erase();  public static Shape factory(String

type) {    if(type.equals("Circle")) return

new Circle();    if(type.equals("Square")) return

new Square();    throw new RuntimeException(      "Bad shape creation: " + type);  }} class Circle extends Shape {  Circle() {} // Package-access

constructor  public void draw() {    

System.out.println("Circle.draw");   }  public void erase() {    

System.out.println("Circle.erase");

  }}  

public class ShapeFactory1 extends TestCase  {

  String shlist[] = { "Circle", "Square",

    "Square", "Circle", "Circle", "Square" };

  List shapes = new ArrayList();  public void test() {    Iterator it =

Arrays.asList(shlist).iterator();

    while(it.hasNext())     

shapes.add(Shape.factory((String)it.next()));

    it = shapes.iterator();    while(it.hasNext()) {      Shape s = (Shape)it.next();      s.draw();      s.erase();    }  }

Page 12: WZORCE PROJEKTOWE

FABRYKA ABSTRAKCYJNA (Abstract Factory)

Wzorca projektowego Abstract Factory można używać w celu otrzymania jednej z wielu związanych ze sobą klas obiektów, z których każdy może na żądanie zwrócić wiele innych obiektów. Wzorzec ten jest fabryką, która zwraca jedną z wielu grup klas. Można nawet gdy używa się Simple Factory, decydować, którą klasę z tej grupy zwrócić. Można także wykorzystać w implementacji wzorzec Prototype, jeśli często będą tworzone obiekty o bardzo zbliżonych własnościach.

Page 13: WZORCE PROJEKTOWE

FABRYKA ABSTRAKCYJNA – SCHEMAT

Page 14: WZORCE PROJEKTOWE

PROTOTYP (Prototype)W tym wzorcu tworzenie obiektu polega na modyfikacji uprzednio utworzonej kopii pewnego obiektu - prototypu. Zastosowanie tego wzorca jest w szczególności uzasadnione, gdy tworzone obiekty zawiera dużą ilość czasochłonnie stworzonych danych, których tylko mała część jest modyfikowana względem prototypu.

Przykład z życia: klonowanie, podział komórki

Page 15: WZORCE PROJEKTOWE

interface Xyz { Xyz cloan();

class Tom implements Xyz { public Xyz cloan() { return new Tom(); } public String toString() { return "ttt"; } }

class Dick implements Xyz { public Xyz cloan() { return new Dick(); } public String toString() { return "ddd"; } }

class Factory { private java.util.Map prototypes; public Factory(){ prototypes = new java.util.HashMap(); prototypes.put( "tom", new Tom() );

prototypes.put( "dick", new Dick() ); public Xyz makeObject( String s ) { return ((Xyz)prototypes.get(s)).cloan(); } } public static void main( String[] args ) { for (int i=0; i < args.length; i++) System.out.print( (new Factory()). makeObject( args[i] ) + " " );

Page 16: WZORCE PROJEKTOWE

BUDOWNICZY (Builder)Ten wzorzec jest podobny do wzorca Abstrakcyjnej Fabryki, gdyż służy on tworzeniu zbioru obiektów, ale tutaj tworzone obiekty są z sobą powiązane (w szczególności gdy tworzą Kompozyt). Obiekt złożony jest tworzony na podstawie danych wejściowych. Dane te są przetwarzane tak, że kolejne ich części tworzą komponenty, które z kolei mogą służyć wraz z innymi danymi utworzeniu obiektu złożonego.

Page 17: WZORCE PROJEKTOWE

BUDOWNICZY – SCHEMAT

Page 18: WZORCE PROJEKTOWE

WZORCE STRUKTURALNE (structural patterns)

Pozwalają łączyć obiekty w większe struktury, mając zastosowanie np. w implementacji złożonego interfejsu użytkownika.

Przykłady: Adapter, Most, Kompozyt, Dekorator, Fasada, Waga Piórkowa, Proxy

Page 19: WZORCE PROJEKTOWE

ADAPTER (Adapter)Wzorzec Adapter konwertuje interfejs jednej klasy na interfejs innej klasy. Używamy tego wzorca, jeśli chcemy, żeby dwie niezwiązane ze sobą klasy współpracowały ze sobą w jednym programie. Koncepcja wzorca Adaptera jest bardzo prosta: piszemy klasę, która posiada wymagany interfejs, a następnie zapewniamy jej komunikację z klasą, która ma inny interfejs. Istnieją dwa sposoby realizacji: poprzez dziedziczenie i poprzez kompozycję.

Page 20: WZORCE PROJEKTOWE

ADAPTER – PRZYKŁAD IMPLEMENTACJIpackage adapter;import junit.framework.*; class Target {  public void request() {}} class Adaptee {  public void specificRequest() {    System.out.println("Adaptee:

SpecificRequest");  }} class Adapter extends Target {  private Adaptee adaptee;  public Adapter(Adaptee a) {    adaptee = a; 

}  public void request() {    adaptee.specificRequest();  }} public class SimpleAdapter extends

TestCase  {  Adaptee a = new Adaptee();  Target t = new Adapter(a);  public void test() {    t.request();  }  public static void main(String

args[]) {   

junit.textui.TestRunner.run(SimpleAdapter.class);

  }

Page 21: WZORCE PROJEKTOWE

KOMPOZYT (Composite)Wzorzec kompozytu pozwala na jednolite traktowanie komponentów i obiektów z nich złożonych poprzez specyfikację ich wspólnego interfejsu.

Przykład z życia: zapis działania matematycznego, składa się ono z liczb, symboli operatorów i nawiasów; także przepis kuchenny, jeśli za komponenty uznamy poszczególne składniki.

Page 22: WZORCE PROJEKTOWE

KOMPOZYT – SCHEMAT

Page 23: WZORCE PROJEKTOWE

Przykład:package composite;import java.util.*;import junit.framework.*; interface Component {  void operation();} class Leaf implements Component {  private String name;  public Leaf(String name) { this.name =

name; }  public String toString() { return name; }  public void operation() {    System.out.println(this);  }} class Node extends ArrayList implements

Component {  private String name;  public Node(String name) { this.name =

name; }  public String toString() { return name; } 

public void operation() {    System.out.println(this);    for(Iterator it = iterator();

it.hasNext(); )      ((Component)it.next()).operation();  }} public class CompositeStructure extends

TestCase {  public void test() {    Node root = new Node("root");    root.add(new Leaf("Leaf1"));    Node c2 = new Node("Node1");    c2.add(new Leaf("Leaf2"));    c2.add(new Leaf("Leaf3"));    root.add(c2);    c2 = new Node("Node2");    c2.add(new Leaf("Leaf4"));    c2.add(new Leaf("Leaf5"));    root.add(c2);    root.operation();  }  public static void main(String args[]) {   

junit.textui.TestRunner.run(CompositeStructure.class);

  }

Page 24: WZORCE PROJEKTOWE

DEKORATOR (Decorator)Wzorzec ten pozwala na dekorowanie zachowania klasy, czyli zmianę jej funkcjonalności bez potrzeby dziedziczenia, które mogłoby stworzyć zbyt wiele mało elastycznych klas.

Najprostsza sytuacja:

Page 25: WZORCE PROJEKTOWE

FASADA (Facade)Często program podczas tworzenia ewoluuje i rośnie stopień jego komplikacji. Możemy zauważyć że oprócz korzyści wzorce mają też ujemną cechę: czasami generują one bardzo wiele dodatkowych klas, przez co trudniej jest zrozumieć działanie programu. Poza tym programy często składają się z szeregu podsystemów, z których każdy posiada swój własny skomplikowany interfejs. Dlatego też warto wprowadzić Fasadę – ujednolicony interfejs do szeregu interfejsów poszczególnych podsystemów.

Page 26: WZORCE PROJEKTOWE

FASADA - SCHEMAT

Page 27: WZORCE PROJEKTOWE

WAGA PIÓRKOWA (Flyweight)

Waga Piórkowa ogranicza ilość tworzonych instancji obiektów, przez przeniesienie części danych z stanu obiektu do parametrów metod co umożliwia ich współdzielenie. Takie rozwiązanie wpływa korzystnie na szybkość wykonywania się programu – niekiedy niekontrolowane powstawanie zbyt dużej ilości obiektów spowalnia jego pracę.

Page 28: WZORCE PROJEKTOWE

Przykład: zamknięcie wielu obiektów w jednym (przetwarzanie ich osobno skrajnie nieefektywne z powodu dużej ich ilości)class DataPoint {  private static int count = 0;  private int id = count++;  private int i;  private float f;  public int getI() { return i; }  public void setI(int i) { this.i

= i; }  public float getF() { return

f; }  public void setF(float f)

{ this.f = f; }  public String toString() {    return "id: " + id + ", i = "

+ i + ", f = " + f;  }} 

public class ManyObjects {  static final int size = 1000000;  public static void main(String[]

args) {    DataPoint[] array = new

DataPoint[size];    for(int i = 0; i <

array.length; i++)      array[i] = new DataPoint();    for(int i = 0; i <

array.length; i++) {      DataPoint dp = array[i];      dp.setI(dp.getI() + 1);      dp.setF(47.0f);    }    System.out.println(array[size

-1]);  }

Page 29: WZORCE PROJEKTOWE

Rozwiązanie: zamknięcie wszystkich DataPoint w jednym ExternalizedData

class ExternalizedData {•   static final int size = 5000000;•   static int[] id = new int[size];•   static int[] i = new int[size];•   static float[] f = new float[size];•   static {•     for(int i = 0; i < size; i++)•       id[i] = i;•   }• }•  • class FlyPoint {•   private FlyPoint() {}•   public static int getI(int obnum) {•     return ExternalizedData.i[obnum];•   }•   public static void setI(int obnum, int

i) {•     ExternalizedData.i[obnum] = i;•   }• public static float getF(int obnum) {•     return ExternalizedData.f[obnum];•   }

    public static void setF(int obnum, float f) {•     ExternalizedData.f[obnum] = f;•   }•   public static String str(int obnum) {•     return "id: " +•       ExternalizedData.id[obnum] +•       ", i = " +•       ExternalizedData.i[obnum] +•       ", f = " +•       ExternalizedData.f[obnum];•   }• }•  • public class FlyWeightObjects {•   public static void main(String[] args) {•     for(int i = 0; i < ExternalizedData.size;

i++) {•       FlyPoint.setI(i, FlyPoint.getI(i) + 1);•       FlyPoint.setF(i, 47.0f);•     }•     System.out.println(•       FlyPoint.str(ExternalizedData.size -

1));•   }

Page 30: WZORCE PROJEKTOWE

WZORCE OPERACYJNE (behavioral patterns)

pomagają zdefiniować komunikację pomiędzy obiektami oraz kontrolować przepływ danych w złożonym programie.

Przykłady: Iterator, Łańcuch Odpowiedzialności, Interpreter, Stan, Mediator, Obserwator, Memento, Strategia

Page 31: WZORCE PROJEKTOWE

STAN (State)Wzorzec Stan pozwala obiektowi zmienić zachowanie gdy zmieni się jego stan wewnętrzny.

Page 32: WZORCE PROJEKTOWE

Przykład (bajkowy :-))

//: state:KissingPrincess.javapackage state;import junit.framework.*; class Creature {  private boolean isFrog = true;  public void greet() {    if(isFrog)    System.out.println("Ribbet!");    else   System.out.println("Darling!");  }  public void kiss()

{ isFrog = false; }} 

public class KissingPrincess extends TestCase  {

  Creature creature = new Creature();

  public void test() {    creature.greet();    creature.kiss();    creature.greet();  }  public static void main(String

args[]) {   

junit.textui.TestRunner.run(KissingPrincess.class);

  }

Page 33: WZORCE PROJEKTOWE

OBSERWATOR (Observer)Wzorzec ma na celu zdefiniowanie zależności miedzy obiektami typu jeden-do-wielu tak, aby przy zmianie stanu jednego pozostałe były o tym powiadamiane i też zmieniały swój stan.

Page 34: WZORCE PROJEKTOWE

ITERATOR (Iterator)Wzorzec Iteratora jest jednym z prostszych i najczęściej wykorzystywanych. Pozwala przemieszczać się poprzez listę lub dowolną kolejkę danych, z wykorzystaniem standardowego interfejsu, bez potrzeby znajomości wewnętrznej reprezentacji danych. Można też zdefiniować specjalne iteratory, które dokonują specjalnego przetwarzania i zwracają tylko niektóre elementy kolekcji danych.

Page 35: WZORCE PROJEKTOWE

Przykład użycia:public class TypedIterator implements Iterator {  private Iterator imp;  private Class type;  public TypedIterator(Iterator it, Class type) {    imp = it;    this.type = type;  }  public boolean hasNext() {     return imp.hasNext();   }  public void remove() { imp.remove(); }  public Object next() {    Object obj = imp.next();    if(!type.isInstance(obj))      throw new ClassCastException(        "TypedIterator for type " + type +        " encountered type: " + obj.getClass());    return obj;  }

Page 36: WZORCE PROJEKTOWE

Schemat innego zastosowania (C++)

<listiterator.h>class ListIterator{ public: ListIterator(const List& alist); virtual ~ListIterator() {} int AtEnd() const; void Restart(); int getPosition()const {return position;} protected: virtual ListElement* get(); virtual ListIterator& advance(); ListIterator& operator=(const ListIterator& other); ListIterator& operator=(const List& alist);

private: ListElement* start; ListElement* cursor; int position;};

<ObjectListIterator.h>class ObjectListIterator:public

ListIterator{ public: ObjectListIterator(const ObjectList&

alist); virtual ~ObjectListIterator() {} virtual ObjectListIterator& operator++

(); //advances a cursor virtual ObjectListIterator& operator++

(int); //same Object* Get();

//gets a pointer to an object void Set(Object*newobj=0);

//sets a pointer to an object

ObjectListIterator&operator=(const ObjectList& alist);

};

Page 37: WZORCE PROJEKTOWE

WZORCE - KORZYŚCI+ Sukces jest ważniejszy niż tworzenie

wszędzie czegoś nowego+ Dobrze napisane wzorce ułatwiają

komunikację między autorami kodu+ Pochodzą z praktycznego doświadczenia

i rozwiązują konkretne problemy+ Wzorce wcale nie służą eliminacji

programistów!

Page 38: WZORCE PROJEKTOWE

ŹRÓDŁA I BIBLIOGRAFIA• Gamma i inni (GoF): „Elements of

Reusable Object-Oriented Software”• James William Cooper „Java. Wzorce

projektowe” (wyd. Helion)• Bruce Eckel „Thinking in Patterns”,

dostępne na www.bruceeckel.com• Żródła internetowe – m.in. tutoriale na

www.ibm.com (Java Patterns 101 i 201)

Page 39: WZORCE PROJEKTOWE

MOTTO„Użycie wzorców projektowych

pozwala nam uczyć się na sukcesach innych zamiast na

własnych błędach”