Your Federal Quarterly Tax Payments are due April 15th Get Help Now >>

Design Pattern - DOC by ashrafp

VIEWS: 3,856 PAGES: 21

									                                                     Design Pattern
Design patterns = Reusable design solutions to problems in context
                                                                        ่
ที่มาของ Design patterns เปรียบเทียบมาจากหลักการสร้ างบ้ านของสถาปนิก ทีมองว่าจะออกแบบแต่ละส่วนของบ้ าน
มีแพทเทิรน์อะไรให้ เลือกบ้ าง สถาปนิกก็จะเลือกเอาแพทเทิรน์ของแต่ละส่วนมารวมกันเป็ น blueprint ของบ้ านทังหลัง  ้
          ื่
เพื่อใช้ สอสารกับเจ้ าของบ้ าน วิศวกรโยธาและทีมงานต่อไป
ที่ใช้ คาว่า Design เพราะเป็ นการพูดถึงเทคนิคการออกแบบโปรแกรมสาหรับปั ญหาแต่ละด้ าน (problem in context)
ที่ใช้ คาว่า Pattern เพราะเทคนิคการออกแบบมีรูปแบบชัดเจน และสามารถเอาไปใช้ งานได้ หลายกรณี (reusable)
                                                                         ู
design patterns ช่วยให้ การพัฒนาโปรแกรมง่ายขึ ้น โดยการใช้ เทคนิคที่พิสจน์แล้ วว่าใช้ งานได้ จริ ง คือ design pattern
                       ่                                                                                     ั
แต่ละตัวต้ องมาจากสิงที่โปรแกรมอื่นเคยใช้ จริ งมาแล้ ว มา implement เป็ นโปรแกรม โดยถ้ านักพัฒนาในทีมรู้จก design
                                   ่
pattern แต่ละตัว ก็จะสามารถสือสารกันง่ายขึ ้น เช่น ถ้ าต้ องการสร้ างระบบติดตามราคาหุ้น
อาจออกแบบส่วนติดต่อตลาดหุ้นด้ วย Observer pattern ส่วน user interface ใช้ MVC pattern ส่วนรับอินพุทจากผู้ใช้
                                                                     ่
ใช้ Command pattern คนที่ร้ ูรายละเอียดของแต่ละแพทเทิรน์ก็จะรู้ วาต้ องเขียนออกมายังไง
                                                                                                  ้
1. Creational : เป็ น pattern ที่สนับสนุนการสร้ าง object ในระบบ โดย creational pattern นันจะสามารถสร้ าง object
                                                                ่
ในระบบได้ โดยไม่ต้อง specified type ของ class ใน code เลย ซึงใน pattern นี ้ประกอบด้ วย
- Abstract Factory pattern
คราวนี ้มามอง AbstractFactory บ้ าง ในขณะที่ Factory Method เป็ นเมดธอด ตัว AbstractFactory เป็ นคลาส
                                                             ั
คลาสที่เลือกว่าเราจะใช้ โรงงานไหนผลิตออปเจก กลับไปที่ตวอย่างเดิม ถ้ าคุณจะเลือกซื ้อรถยนต์
   ่      ุ                                            ั ุ
สิงแรกที่คณอาจมองคือจะซื ้อของยี่ห้อไหน (ทางปฏิบติคณอาจเลือกที่ขนาดรถ รุ่ นหรื อราคารถก่อน แต่หลักการก็เหมือนกัน)
            ่
ถ้ าสมมติวาอยากเลือกซื ้อยี่ห้อ โตโยเย (ไม่ขอใช้ ชื่อจริงๆนะครับ เดี๋ยวหาว่าโฆษณา)
     ่
ก็คอยไปโรงงานโตโยเยให้ ผลิตรถโมเดลที่ต้องการออกมา
CODE
Factory factory = ToyoyeFactory;
Car car = ToyoyeFactory.createSaloonCar();
ถ้ าอยากสร้ างรถจากยี่ห้ออื่นก็ต้องกาหนดโรงงานใหม่
CODE
Factory factory = AbstractFactory.createFactory("Toyoye");
Car car = factory.createSaloonCar();
                                   ่
แล้ วถ้ าตอนเขียนโปรแกรมเราไม่ร้ ูวาผู้ใช้ จะเลือกรถยี่ห้อไหนล่ะ เราจะรู้ได้ อย่างไรว่าจะใช้ โรงงานไหน นี่แหละครับ คือจุดที่
AbstractFactory มาช่วยได้ คือเราสามารถกาหนดชนิดของโรงงานเป็ นพารามิเตอร์ บอกให้ AbstractFactory
คืนค่าโรงงานทีเ่ ราต้ องการ เช่น
CODE
Factory factory = AbstractFactory.createFactory("Toyoye");
Car car = factory.createSaloonCar();
โดยตัว AbstractFatory มีโค้ ดดังนี ้
CODE
public class AbstractFactory {
 public Factory createFactory(String factoryName) {
  if ("Toyoye".equals(factoryName))
          return ToyoyeFactory;
        else if ("Honde".equals(factoryName))
          return HondeFactory;
        else ...
    }
}
ด้ วยวิธีนี ้เราสามารถเลือก Factory ของรถยี่ห้อใดก็ได้ ในระหว่างรันโปรแกรม
และแต่ละยี่ห้อเราสามารถสร้ างออปเจกรถแต่ละโมเดลได้ โดยที่ไม่ต้อง hardcode ไว้ ในโปรแกรม
                                         ่
สรุปแล้ ว Factory method คือเมดธอดทีใช้ สร้ างออปเจกที่มี standard attributes ส่วน AbstractFactory
                                                                                              ่
เป็ นคลาสที่คืนค่าโรงงานที่มี Factory method โดยชนิดของโรงงานสามารถระบุได้ จากพารามิเตอร์ ที่ผานไปให้
AbstractFactory
Abstract Factory กับ Factory ต่างกันอย่างไร
                   ้                                                        ั
เหมือนกับว่า บางครังเราใช้ แค่ Factory มันยังไม่สามารถแบ่งแยกการทางานได้ ชดเจนเพราะต้ องเลือก Factory
                            ่
สาหรับงานแต่ละงานอีกทีหนึง ... เลยให้ Abstract Factoryเป็ นตัวเลือกว่า จะใช้ Factory ไหนเพื่อทางานต่อไป
CODE
/ Run on Win32
Factory f = AbstractFactory.getFactory(); // return Win32Factory
f.getInstance("abc"); // return Win32Object
// Run on *NIX
Factory f = AbstractFactory.getFactory(); // return UnixFactory
f.getInstance("abc"); // return UnixObject

- Builder pattern
Definition
         Separate the construction of a complex object from its representation so that the same
construction process can create different representations.
Participants
  The classes and/or objects participating in this pattern are:
Builder (VehicleBuilder)specifies an abstract interface for creating parts of a Product object
ConcreteBuilder (MotorCycleBuilder, CarBuilder, ScooterBuilder)
     constructs and assembles parts of the product by implementing the Builder interface
     defines and keeps track of the representation it creates
     provides an interface for retrieving the product
Director (Shop)
     constructs an object using the Builder interface
Product (Vehicle)
     represents the complex object under construction. ConcreteBuilder builds the product's internal
         representation and defines the process by which it's assembled
     includes classes that define the constituent parts, including interfaces for assembling the parts
         into the final result
                                               ้        ่ ั
จะรวม object ต่างๆ ไว้ โดยจะ return object มานันขึ ้นอยูกบ data โดย builder pattern
  ้
นันสรางขึ ้นมาเพื่อแยกส่วนของข้ อมูลออกจากการแสดงผล Builder pattern จะแตกต่างกับ Factory pattern คือ factory
                                        ่ ั       ่                   ่
pattern จะทาการ return object ขึ ้นอยูกบ data ที่สงไปให้ แต่ไม่ต้องมีสวนของ algorithm ในการคานวณใดๆ Builder
          ้                                                         ้      ่
pattern นันจะทาการสร้ าง object ที่มีความซับซ้ อนคือมีการทางานหลายขันตอน ซึงต่างจาก pattern
อื่นที่มีการทางานเพียง step เดียว

Example
Builder Interface CODE
public interface BuilderIF {
  public void buildCustomer();
  public CustomerIF getCustomer();
}
public interface BuilderIF {
  public void buildCustomer();
  public CustomerIF getCustomer();
}
Class Director สาหรับสร้ าง builder
CODE
public class Director {
  BuilderIF builder;
  public Director(BuilderIF param) {
      this.builder = param;
  }
  public void construct() {
      builder.buildCustomer();
  }
}
Implement BuilderIF
CODE
public class ConcreateBuilder implemets BuilderIF {
  CustomerIF customer;
  public void buildCustomer() {
     customer = new ConcreateCustomer();
     //All processing .....
  }
  public CustomerIF getCustomer() {
    return customer;
  }
}
Implement CustomerIF
CODE
public class ConcreateCustomer implements CustomerIF {
  public ConcreateCustomer() {
  }
  public void action() {
  }
}
//Main : How to use builder
//Create builder
  BuilderIF builder = new ConcreateBuilder();
  //Create director
  Director director = new Director(builder);
  //Construct customer via director
  director.construct();
  //Get customer via builder
  CustomerIF customer = builder.getCustomer();
  //Call action on customer
  customer.action();

- Factory method pattern
      ่                  ั      ่
สมมติวาเราจะประกอบรถยนต์สกคันหนึง เราอาจสร้ างรถด้ วยวิธีนี ้
CODE
Car car = new Car();
car.setEngine(new V8Engine());
car.setBrake(new ABSBrake());
car.setHeadLight(new XenonHeadLight());
จะเห็นว่าเราต้ องมาคอยเซตชิ ้นส่วนต่างๆ (Attribute) ของรถ (object) คันนี ้
                                                   ่
คุณอาจมองว่าถ้ าไม่อยากเซตชิ ้นส่วนต่างๆต่างหาก ก็นาจะกาหนดชิ ้นส่วนต่างๆไว้ ตอนสร้ างรถใน constructor เลย เช่น
CODE
Car car = new Car(new V8Engine, new ABSBrake(), new XenonHeadLight());
                                        ่
แต่วิธีนี ้มีข้อจากัดคือถ้ ารถคันนี ้มีสวนประกอบอื่นๆเพิ่มขึ ้น เราก็ต้องมากาหนดพารามิเตอร์ ใน Car constructor เพิ่มขึ ้น
ทาให้ ออปเจกนี ้มี constructor มากมาย
                                                                  ั
ในทานองตรงกันข้ าม ถ้ ากลับไปมองตัวอย่างรถที่ขายปั จจุบนมักจะมี standard options ให้ เลือกเป็ นโมเดลๆ เช่น LX, EX,
SE โดยแต่ละโมเดลมี standard options ที่มากับรถแตกต่างกัน ดังนัน            ้
ถ้ าเรามีโรงงานที่ผลิตรถยนต์แต่ละโมเดลมาให้ ใช้ ได้ เลย คนใช้ ก็จะได้ ไม่ต้องมาเลือก option ต่างๆเอง เช่น
CODE
Car car = CarFactory.createCarLX();
Car anotherCar = CarFactory.createCarEX();
เป็ นต้ น การสร้ างรถ (ออปเจก) ผ่านโรงงาน (แฟกตอรี่ ) ทาให้ เราไม่ต้องมาเซต Standard options (default attributes)
                              ั
ของรถเอง โดยมอบภาระให้ กบโรงงาน (Factory class) ไป ทาให้ การสร้ างออปเจกง่ายขึ ้น ตัว createCarXX();
จึงเรียกว่าเป็ น Factory Method
แฟกทอรี เมธอดแพตเทิร์น (Factory method pattern)
                                                                         ่
เป็ นดีไซน์แพตเทิร์นที่นิยามเมธอดสาหรับสร้ างอ็อบเจกต์ของคลาสชนิดหนึงๆ แต่ไม่ได้ เจาะจงชนิดที่แน่นอน
ซับคลาสเป็ นผู้กาหนดเจาะจงว่าจะสร้ างอ็อบเจกต์ของคลาสใด
                                    ่
แฟกทอรี เมธอดในความหมายโดยทัวไปคือเมธอดที่ทาหน้ าที่สร้ างอ็อบเจกต์นนเอง   ั่
แฟกทอรี เมธอดแพตเทิร์นจะถูกใช้ ร่วมกับเทมเพลทเมธอดแพตเทิร์น (Template method pattern)
โดยถูกเรียกใช้ งานจากในเทมเพลทเมธอด
องค์ประกอบของแฟกทอรีเมธอดแพตเทิร์นมีดงนี ้   ั
ผลิตภัณฑ์ (Product) นิยามอินเตอร์ เฟสของของอ็อบเจกต์ที่แฟกทอรี เมธอดจะเป็ นผู้สร้ าง
                                                         ่
ผลิตภัณฑ์รูปธรรม (Concrete product) ตัวคลาสที่แท้ จริ งทีจะถูกสร้ างโดยแฟกทอรี เมธอด
คลาสนามธรรม (Abstract class) เป็ นผู้กาหนดแฟกทอรีเมธอด โดยสร้ างเป็ นเมธอดนามธรรม (Abstract method)
                                                                                           ู
คลาสรูปธรรม (Concrete class) ซับคลาสของคลาสนามธรรม กาหนดรายละเอียดของแฟกทอรี เมธอดที่ถกนิยามในคลาสแม่
ภาษาจาวา

                                                  ่ ู
ตัวอย่างโปรแกรมคานวณหาปริมาตรของรูปทรงกระบอกซึงมีสตรดังนี ้
ปริ มาตร = พื ้นที่ฐาน * ความสูง
โดยที่
แฟกทอรี เมธอดทาหน้ าที่สร้ างรูปวงกลม
                                                                 ่ ู
ปริ มาตรของทรงกระบอกคือผลคูณของความสูงและพื ้นที่ฐานจากรูปวงกลมทีถกสร้ างโดยแฟกทอรีเมธอด
คลาสนามธรรม Container นิยามแฟกทอรีเมธอด createBase() getHeight() และ getVolume()
  ่
ซึงเป็ นเทมเพลทเมธอดมีรายละเอียดการคานวณหาปริมาตร
- Prototype pattern
                          ่                                                             ู
Prototype pattern เป็ นหนึงใน design pattern ที่ใช้ ในการพัฒนาซอฟแวร์ เมื่อชนิดของวัตถุถกพิจารณาโดย Instance
    ่ ่                              ่                                     ้
ทัวไปซึงถูกคัดลอกไปเป็ นวัตถุใหม่ ซึงรูปแบบนี ้ถูกนาไปเป็ นตัวอย่างความสินเปลืองในการสร้ างวัตถุใหม่โดยวิธีอื่นๆ(เช่น
                                 ่        ้
การใช้ คาว่า new) ที่เกิดขึ ้นอยูประจานันกับโปรแกรมประยุกต์
          การนารูปแบบนี ้ไปใช้ ให้ ประกาศคลาสที่เป็ น abstract ที่ระบุถึงเมดธอด clone()ก่อน
  ่           ่
ซึงคลาสใดๆทีต้องการความสามารถ polymorphic constructor จะต้ องสืบทอดตัวเองมาจากคลาสที่เป็ น abstract
และดาเนินการ clone()
                                                     ั
          แทนที่ฝั่ง Client จะเขียนโค้ ดที่เรียกใช้ ตวดาเนินการ new บนชื่อคลาสที่แก้ ไขลาบาก จะเรียกใช้ เม็ดธอด clone()
      ่
ที่อยูใน prototype ,แล้ วเรี ยกใช้ factory method
                        ่ ั                            ื
กับพารามิเตอร์ ที่แต่งตังให้ กบคลาสที่เป็ นรูปธรรมที่สบทอดมากตามต้ องการ หรื อเรี ยกใช้ เม็ดธอด clone()
                           ่
ผ่านกลไกบางอย่างที่มีอยูใน design pattern อื่นๆ
          Prototype Design Pattern ช่วยในการลดจานวนของ Class


Class Diagram
Java Example Code

/** Prototype Class **/
public class Cookie implements Cloneable {

    public Object clone()
    {
      try{
          //In an actual implementation of this pattern you would now attach references to
          //the expensive to produce parts from the copies that are held inside the prototype.
          return this.getClass().newInstance();
      }
      catch(InstantiationException e)
      {
         e.printStackTrace();
      }
    }
}

/** Concrete Prototypes to clone **/
public class CoconutCookie extends Cookie { }

/** Client Class**/
public class CookieMachine
{

    private Cookie cookie;//could have been a private Cloneable cookie;

     public CookieMachine(Cookie cookie) {
         this.cookie = cookie;
     }
     public Cookie makeCookie() {
       return (Cookie)cookie.clone();
     }
     public Object clone() { }

     public static void main(String args[]){
       Cookie tempCookie = null;
       Cookie prot = new CoconutCookie();
        CookieMachine cm = new CookieMachine(prot);
        for(int i=0; i<100; i++)
           tempCookie = cm.makeCookie();
    }
}

Rules of thumb
                  ้                                        ่          ่           ่
            บางครังรูปแบบของ creational pattern จะเหลือมกัน – ซึงจะมีเคสที่วา Prototype หรื อ Abstract Factory
                                 ้                 ั
อันใหนเหมาะสม ในบางครังมันจะเติมเต็มให้ กนและกัน: เช่น Abstract Factory จะเก็บชุดของ Prototype
           ่ ู
จากอันทีถกคัดลอกและคืนค่าวัตถุที่เป็ นผลผลิต
            Abstract Factory, Builder, และ Prototype สามารถใช้ Singleton ในการสร้ างพวกมันได้
                                               ้                                    ั
            คลาส Abstract Factory บ่อยครังถูกสร้ างด้ วย Factory Method แต่มนก็สามารถสร้ างด้ วย Prototype
ได้ ด้วยเช่นกัน
Prototype: ถูกสร้ างผ่านตัวแทน
Factory Method: ถูกสร้ างผ่านการสืบทอด
                    ้
            บ่อยครังที่เริ่มต้ นด้ วย Factory Method (ความซับซ้ อนน้ อยกว่า, ปรับแต่งได้ มากกว่า, เพิ่มจานวน Subclass
อย่างรวดเร็ ว) และกลายพันธ์เป็ น Abstract Factory , Prototype, Builder (ซับซ้ อนกว่า ยืดหยุนกว่า)  ่
         ั
ตามที่นกออกแบบเห็นว่าต้ องการความยืดหยุน         ่
                                                     ั            ั                   ่
การทา Prototype ไม่ต้องการ subclassing แต่มนต้ องการปฏิบติการ Initialize ซึงตรงข้ ามกับ Factory method
                ่
การออกแบบทีใช้ รูปแบบ Composite และ Decorator บ่อยๆจะได้ ผลประโยชน์จาก Prototype ไปด้ วย
          The rule of thumb
   ่                                                                       ่                    ี่
นันคุณควรที่จะคัดลอกวัตถุเมื่อต้ องการวัตถุอื่นในเวลาโปรแกรมทางานซึงจะเป็ นการคัดลอกวัตถุทแท้ จริ ง
                                                                                            ่ ั
ชื่อวัตถุควรจะเหมือนกับวัตถุต้นแบบ การคัดลอกที่แท้ จริ ง attribute จะต้ องเหมือนกับต้ นแบบทีคดลอก
                            ุ
ถ้ าคุณต้ องสร้ างวัตถุใหม่คณควรได้ รับวัตถุที่ attribute เหมือนกับค่าเริ่มต้ นของมัน เช่น
                                                              ่
           ถ้ าคุณออกแบบระบบธุรกรรมของบัญชีธนาคาร ซึงคุณควรที่จะสร้ างสาเนาของวัตถุที่เก็บข้ อมูลบัญชีของคุณ
                                ่ั                          ู       ่
และทาธุรกรรมกับมันและแทนทีวตถุต้นแบบมันด้ วยอันที่ถกแก้ ไข ซึงในเหตุการณ์นี ้ต้ องใช้ เม็ดธอด clone() แทนตัวกระทา
new

- Singleton pattern
                          ้                                          ้
เป็ น Pattern ที่ class นันๆ จะมี instance เพียง instance เดียวเท่านัน และ pattern นี ้จะต้ องสร้ างทางสาหรับ access
                                                                       ่
(public method) โดยทุกๆ object จะใช้ instance ของ class เดียวกันเสมอ ซึงประโยชน์ของ pattern นี ้คือ
1. ควบคุนการเข้ าถึง
2. ลดการใช้ namespace
Definition
Ensure a class has only one instance and provide a global point of access to it.
Participants The classes and/or objects participating in this pattern are:
Singleton (LoadBalancer) defines an Instance operation that lets clients access its unique instance.
Instance is a class operation. responsible for creating and maintaining its own unique instance.
                                                                         ่
2. Structural pattern นี ้จะควบคุมความสัมพันธ์ ระหว่างส่วนต่างๆ ในระบบ ซึงประกอบด้ วย
- Adapter pattern
อะแด็ปเตอร์ แพตเทิร์น (Adapter pattern) เป็ นดีไซน์แพตเทิร์น
                                                       ู                    ู
ที่ใช้ เชื่อมการทางานระหว่างคลาสผู้เรี ยกและคลาสที่ถกเรี ยกในกรณีที่คลาสที่ถกเรียกมีเมธอดที่แตกต่างจากที่ผ้ เู รี ยกคาดหวัง
ตัวอย่างทีเ่ ห็นได้ ในชีวิตประจาวันเช่น หม้ อแปลงไฟฟ้ า
            ๊                                  ั
หรื อปลักไฟที่มีขาต่างรูปทรงต่างกันจะต้ องมีตวแปลงเพื่อต่อเชื่อมเป็ นต้ น
การนาไปใช้ งาน
                                                                      ั
การสร้ างคลาสสาหรับทาหน้ าที่เป็ นอะแด็ปเตอร์ สามารถทาได้ สองวิธีดงนี ้
วิธีการแบบ inheritance
                          ั
ให้ คลาสอะแด็ปเตอร์ ซบคลาสจากคลาสที่จะถูกใช้ งานจริงและให้ อิมพลิเมนท์อินเตอร์ เฟสตามที่คลาสผู้เรี ยกคาดหวัง
                                      ู
ความสัมพันธ์ระหว่างผู้แปลงและผู้ถกแปลงจะเป็ นในแบบ is-a ดังภาพประกอบ




                                                                      ่
วิธีการแบบ delegation ให้ คลาสอะแด็ปเตอร์ อิมพลิเมนท์อินเตอร์ เฟสตามทีคลาสผู้เรี ยกคาดหวังแต่ไม่ต้องซับคลาส
                                                                               ู
คลาสอะแด็ปเตอร์ เรี ยกเมธอดของคลาสที่จะถูกใช้ งานผ่านทางอ็อบเจกต์ของคลาสที่ถกใช้ งานนัน้
                                 ู
ความสัมพันธ์ระหว่างผู้แปลงและผู้ถกแปลงจะเป็ นในแบบ has-a ดังภาพ
ตัวอย่างโปรแกรมภาษาจาวา
ซอร์ สโค้ ดอะแด็ปเตอร์ แบบ inheritance
public class Adapter extends Adaptee implements ExpectedInterface {
  public void doWork() {
      actualDoWork();
  }
}
ซอร์ สโค้ ดอะแด็ปเตอร์ แบบ delegation
public class Adapter implements ExpectedInterface {
  private Adaptee adaptee;
   public void doWork() {
    adaptee.actualDoWork();
  }
}
อินเตอร์ เฟสที่โค้ ดผู้เรียกคาดหวัง
public interface ExpectedInterface {
  public void doWork();
}
        ู
คลาสที่ถกแปลง
public class Adaptee {
  public void actualDoWork() {
    // do work
  }
}
การเรี ยกใช้ งาน
expectedInterface.doWork();

- Bridge pattern
Intent
Decouple an abstraction from its implementation so that the two can vary independently.
จะพูดถึงการออกแบบระบบที่ขึ ้นกับ operation แต่ไม่ขึ ้นกับ implementation
การมองแบบ operation คือการทา abstraction ถ้ าระบบเรายังขึ ้นกับการ implement สามารถ refactoring เพื่อดึงเอา
                                                                                                           ้
operation จริ งของระบบออกมา ทาเป็ น interface เช่น JDBC เป็ นการสร้ าง interface ของ การติดต่อ database ทังระบบ
โดยไม่ขึ ้น กับ การ implement ทาให้ สามารถ implement ได้ หลายๆ แบบ (ODBC, MySQL, ..) instance ของ database
                                                         ่
driver ที่ load มาก็คือ instance ของ Adapter Pattern นันเอง เพราะ database server มี interface ไม่ตรงกับ JDBC
                 ้                     ่
interface ดังนันต้ องการ Adapter มาคันกลาง เมื่อไหร่ ก็ตามที่ระบบของเราสามารถทางานได้ โดยอาศัยเพียงแค่ interface
      ้
เท่านันแสดง ว่าเราได้ ใช้ Bridge Pattern แล้ ว
- Compositor pattern
คอมโพสิตแพตเทิร์น (Composite pattern) เป็ นดีไซน์แพตเทิร์น
    ั                          ี ั
ที่จดโครงสร้ างของอ็อบเจกต์ที่มลกษณะการทางานคล้ ายกันและเป็ นส่วนประกอบย่อยๆ
                     ่                                           ั ่
ของระบบใหญ่ให้ อยูในรูปแบบโครงสร้ างต้ นไม้ คลาสผู้ใช้ สามารถปฏิบติตอส่วนต่างๆ
ของคอมโพสิตในแบบเดียวกันโดยไม่ต้องคานึงว่าเป็ นส่วนปลายหรื อส่วนกลางของแผนผังต้ นไม้
                                   ่
ตัวอย่างเช่นโครงสร้ างของบทความหนึงๆ แบ่งเป็ นหลายๆ ย่อหน้ า แต่ละย่อหน้ ายังแบ่งย่อยต่อไปได้ เป็ นประโยค คา
และตัวอักษรในที่สดุ
การนาไปใช้ งาน
องค์ประกอบของคอมโพสิตแพตเทิร์นมีสามส่วนคือ
                                                            ิ
       อินเตอร์ เฟสหรื อคลาสแบบแอ็บสแตรคเป็ นแม่แบบที่นยามพฤติกรรมที่แต่ละอ็อบเจกต์ของคอมโพสิตต้ องมี
                                     ่
       คลาสที่สามารถมีองค์ประกอบอืนของคอมโพสิตได้
       คลาสที่เป็ นส่วนปลาย ไม่สามารถมีองค์ประกอบอื่นได้




ตัวอย่ างโปรแกรม
ภาษาจาวา
                                                                                  ่
ตัวอย่างโปรแกรมเพื่อแสดงโครงสร้ างของ File System โดยแบ่งเป็ นแฟ้ มและเอกสารที่อยูภายในแฟ้ ม
และการแสดงรายชื่อของแฟ้ มและเอกสารภายใน
อินเตอร์ เฟส File เป็ นแม่แบบของส่วนประกอบต่างๆ ของคอมโพสิต นิยามเมธอด list()
                                                                 ่
เพื่อให้ แต่ละองค์ประกอบพิมพ์ชื่อของตัวเองและองค์ประกอบย่อยที่อยูภายใต้
public interface File {
  public void list();
  public void addFile(File file);
  public void removeFile(File file);
}
                                                ่
คลาส Folder สามารถมีอ็อบเจกต์ชนิด File อื่นๆ อยูภายใต้ ได้ คือมีได้ ทง้ั Folder ย่อยและ Document เมธอด list()
                                                                      ่
จะพิมพ์ชื่อของตนเองและตามด้ วยการเรี ยกเมธอด list() ของทุก File ที่อยูภายใต้ Folder
                                            ั
เมธอด addFile() และ removeFile() ทาหน้ าที่จดการกับ File ย่อยๆ ภายใต้ Folder
public class Folder implements File {
  private String name;
  private ArrayList<File> files = new ArrayList<File>();
   public Folder(String name) {
    this.name = name;
  }
   public void addFile(File file) {
    files.add(file);
  }
   public void removeFile(File file) {
    files.remove(file);
  }
   public void list() {
    System.out.println("Folder: " + name);
    for (File file : files) {
       file.list();
    }
  }
}

                                                  ุ                           ่             ้
คลาส Document เป็ นส่วนปลายสุดหรื อส่วนย่อยที่สดของคอมโพสิต ไม่สามารถมีสวนอื่นๆ ภายใต้ ดังนันเมธอด list()
จึงมีหน้ าที่เพียงพิมพ์ชื่อของตนเองและเมธอด addFile() และ removeFile() ไม่ต้องทาอะไร
public class Document implements File {
  private String name;

  public Document(String name) {
    this.name = name;
  }

  public void list() {
    System.out.println("Document: " + name);
  }
    public void addFile(File file) {
      // do nothing
    }

    public void removeFile(File file) {
      // do nothing
    }
}

การเรี ยกใช้ งาน
File root = new Folder("root");
root.addFile(new Document("one.doc"));

File sub = new Folder("sub");
sub.addFile(new Document("two.doc"));
sub.addFile(new Document("three.doc"));
root.addFile(sub);

root.list();

- Decorator
                            ่
Pattern นี ้เป็ นทางเลือกหนึงสาหรับการขยายความสามารถของ function เดิมด้ วยการสร้ าง subclass โดย pattern
                        ่
นี่จะทาให้ ง่ายต่อการเพิมเติม function ใหม่ๆ เข้ าไป ในการ implement pattern จะใช้ การ composition แทนการใช้
inheritance
Interface สาหรับ function เดิม CODE
public interface ComponentIF {
  public void action();
}
Class implemets ComponentIterface
CODE
public class ConcreateComponent implements ComponentIF {
  public void action() {}
}
                                               ่
Decorator class สาหรับเป็ น base class ในการเพิม function ใหม่
CODE
public class Decorator implements ComponentIF {
  ComponentIF component = new ConcreateComponent();
  public void action() {
    component.action();
  }
}

CODE
public class ConcreateDecorator1 extends Decorator {
  String var;
   public void action() {
     super.action();
     System.out.println("Test : " + var);
   }
}
Add new method
CODE
public class ConcreateDecorator2 extends Decorator {
   public void action() {
        super.action();
       //Call new method
       addNewMethod();
   }
   private void addNewMethod() {
   }
}
- Facade pattern
ฟะซาดแพตเทิร์น (ภาษาอังกฤษ Façade pattern หรื อ Facade pattern)
                                                                          ั
เป็ นดีไซน์แพตเทิร์นเพื่อช่วยให้ การเรี ยกใช้ งานคลาสต่างๆ ในระบบที่ซบซ้ อนทาได้ ง่ายขึ ้น
ฟะซาดแพตเทิร์นได้ ชื่อมาจากส่วนตกแต่งด้ านหน้ าของอาคาร ที่ทาเพื่อความสวยงามและซ่อนโครงสร้ างของตัวตึก
                                                                 ิ ู                                                  ่
ตัวอย่างทีเ่ ห็นได้ ในชีวิตประจาวันเช่น เกียร์ รถยนต์แบบอัตโนมัตที่ผ้ ใช้ ไม่จาเป็ นต้ องกังวลกับรายละเอียดวิธีการเปลียนเกียร์
เป็ นต้ น
การนาไปใช้ งาน
                    ่ ่                               ิ
ถ้ าเรามีคลาสกลุมหนึง (หรื อแม้ แต่คลาสเดียว) ที่มีวธีการเรี ยกใช้ งานที่สลับซับซ้ อน
เราสามารถซ่อนรายละเอียดวิธีการเรี ยกใช้ งานนี ้โดยสร้ างคลาสขึ ้นมาเพื่อทาหน้ าทีเ่ ป็ นฟะซาด
                     ่ ั                                  ่
และรวบรวมโค้ ดทีซบซ้ อนไว้ ในเมธอดของคลาสฟะซาดทีง่ายต่อการเรี ยกใช้ งาน
คลาสผู้ใช้ บริ การเพียงเรียกเมธอดของคลาสฟะซาด




ตัวอย่ างโปรแกรมภาษาจาวา
ซอร์ สโค้ ดของฟะซาดเพื่อช่วยเขียนไฟล์ (เรี ยกใช้ File และ FileWriter) และอ่านไฟล์ (เรี ยกใช้ File, FileReader และ
BufferedReader)
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
 public class FileFacade {
   public void write(String filePath, String content) {
    File file = new File(filePath);
    FileWriter fileWriter = null;
    try {
       fileWriter = new FileWriter(file);
       fileWriter.write(content);
       fileWriter.flush();
    }
    catch (IOException e) {
       e.printStackTrace();
    }
    finally {
       if (fileWriter != null) {
          try {
              fileWriter.close();
          }
          catch (IOException e) {
              e.printStackTrace();
          }
       }
    }
  }
   public String read(String filePath) {
    StringBuilder sb = new StringBuilder();
    File file = new File(filePath);
    BufferedReader bufferedReader = null;
    try {
       FileReader fileReader = new FileReader(file);
       bufferedReader = new BufferedReader(fileReader);
        String s;
       while ((s = bufferedReader.readLine()) != null) {
          sb.append(s);
       }
    }
    catch (FileNotFoundException e) {
       e.printStackTrace();
    }
    catch (IOException e) {
       e.printStackTrace();
    }
    finally {
       if (bufferedReader != null) {
          try {
              bufferedReader.close();
          }
                catch (IOException e) {
                  e.printStackTrace();
                }
            }
        }

        return sb.toString();
    }
}
การเรียกใช้ งาน
String filePath = "filefacade.txt";
FileFacade ff = new FileFacade();
 // write to file
ff.write(filePath, "Hello World!");
// read from file
String content = ff.read(filePath);

- Flyweight pattern
- Proxy pattern

                                                                                ่
3. Behavioral pattern. Pattern นี ้จะเกี่ยวกับ state และ flow การทางานของระบบ ซึงประกอบด้ วย
- Chain of responsibility
- Command
- Interpreter
อินเทอร์ พรี เตอร์ แพตเทิร์น (Interpreter pattern) เป็ นดีไซน์แพตเทิร์น
ที่ใช้ ในกรณีที่ขอบเขตของปั ญหาสามารถถูกอธิบายในลักษณะทีเ่ ป็ นภาษาและกฏที่แน่นอนตายตัว
                                                                                                 ่
เราสามารถสร้ างคลาสทีเ่ ป็ นตัวแทนขององค์ประกอบของภาษา จัดเรี ยงเข้ าด้ วยกันเพื่ออธิบายปั ญหาหนึงๆ
                                                ั        ั้                            ่
และแปลหรื อประเมินผลโดยใช้ โครงสร้ างที่ได้ จดเรี ยงไว้ นน ตัวอย่างเช่นสูตรคณิตศาสตร์ ตางๆ
หรื อยกตัวอย่างให้ เฉพาะเจาะจงเช่น สูตรเรขาคณิตสาหรับหาพื ้นที่รูปสามเหลียม ่
                  ่
พื ้นที่รูปสามเหลียม = 1/2 * ความยาวฐาน * ความสูง
การนาไปใช้ งาน
                                                                       ั
จากการที่ปัญหาส่วนใหญ่เมื่อถูกอธิบายในแบบที่เป็ นนิยามภาษาจะมีลกษณะที่เป็ น recursive คือปั ญหาใหญ่ๆ
จะถูกแก้ ได้ โดยการแบ่งแยกเป็ นปั ญหาย่อยๆ และแก้ ปัญหาย่อยๆ ลงไปตามลาดับๆ
            ุ
จนในที่สดถึงปั ญหาที่ไม่จาเป็ นต้ องแบ่งย่อยอีก
                                                   ั
ทาให้ องค์ประกอบของอินเทอร์ พรี เตอร์ แพตเทิร์นมีลกษณะเดียวกับคอมโพสิตแพตเทิร์น
                                              ั
องค์ประกอบของอินเทอร์ พรี เตอร์ แพตเทิร์นมีดงนี ้

                                                ิ
อินเตอร์ เฟสหรื อคลาสแบบแอ็บสแตรคเป็ นแม่แบบที่นยามพฤติกรรมที่แต่ละอ็อบเจกต์ของอินเทอร์ พรี เตอร์ ต้องมี
                                     ่
      คลาสที่สามารถมีองค์ประกอบอืนของอินเทอร์ พรี เตอร์ ได้
      คลาสที่เป็ นส่วนปลาย ไม่สามารถมีองค์ประกอบอื่นได้
       คลาสสาหรับเป็ นบริ บท (context) หรื อองค์ประกอบที่ใช้ ในการประเมินผล




ตัวอย่ างโปรแกรม
ภาษาจาวา
                                             ่                           ่
ตัวอย่างโปรแกรมเพื่อคานวณหาพื ้นที่รูปสามเหลียมโดยสูตร พื ้นที่รูปสามเหลียม = 1/2 * ความยาวฐาน * ความสูง
อินเตอร์ เฟส Expression เป็ นแม่แบบของส่วนประกอบต่างๆ ของคอมโพสิต นิยามเมธอด evaluate()
                                                                            ่
เพื่อให้ แต่ละองค์ประกอบประเมินผลในส่วนของตัวเองและองค์ประกอบย่อยที่อยูภายใต้ ในที่นี ้เราใช้ HashMap เป็ น
context เพื่อส่งผ่านค่าคัวแปรไปให้ คลาสชนิด Variable ใช้ ในการประเมินผล

- Iterator
- Mediator
- Memento

- Observer
อ็อบเซิร์ฟเวอร์ แพตเทิร์น (observer pattern หรื อเรี ยกอีกชื่อว่า พับลิช/ซับสไครบ์ publish/subscribe)
เป็ นดีไซน์แพตเทิร์นที่ใช้ แจ้ งเหตุการณ์หรื อข้ อมูลข่าวสารจากคลาสต้ นกาเนิดไปยังคลาสที่สมัครเป็ นผู้รับข่าวสาร
ตัวอย่างทีเ่ ด่นชัดได้ แก่การสมัครเป็ นสมาชิกรับหนังสือพิมพ์หรื อนิตยสาร
การนาไปใช้ งาน
                                              ่                  ่
โครงสร้ างของอ็อบเซิร์ฟเวอร์ แพตเทิร์นมีสวนหลักสองส่วนคือผู้สงสารและผู้รับสาร
    ่
ผู้สงสารมีเมธอดหลักคือเมธอดสาหรับเพิ่มและลดผู้รับสาร และเมธอดสาหรับส่งสารไปยังผู้บอกรับข่าวสารทังหมด          ้
จากตัวอย่างคลาสไดอะแกรมอินเตอร์ เฟส Publisher และคลาส NewspaperPublisher มีเมธอด subscribe(), remove()
และ publish() ตามลาดับ
                                         ู ่
ส่วนผู้รับสารจะต้ องมีเมธอดสาหรับที่ผ้ สงสารใช้ เรียกเมื่อต้ องการส่งข่าวสาร จากคลาสไดอะแกรมอินเตอร์ เฟส Subscriber
และคลาส Reader มีเมธอด receive() ที่ Publisher เรี ยกใช้ เมื่อต้ องการส่งข่าวสาร
ตัวอย่างโปรแกรม
ภาษาจาวา
ตัวอย่างโปรแกรมจาลองการทางานของผู้พิมพ์หนังสือพิมพ์และผู้รับหนังสือพิมพ์ที่มีการทางานในแบบอ็อบเซิร์ฟเวอร์ แพตเทิร์
นอินเตอร์ เฟส Publisher
public interface Publisher {
  public void subscribe(Subscriber subscriber);
  public void remove(Subscriber subscriber);
  public void publish();
}
คลาส NewspaperPublisher
public class NewspaperPublisher implements Publisher {
  private ArrayList<Subscriber> subscribers = new ArrayList<Subscriber>();
   public void subscribe(Subscriber subscriber) {
    subscribers.add(subscriber);
  }
   public void remove(Subscriber subscriber) {
    subscribers.remove(subscriber);
  }
   public void publish() {
    Publication pub = new Newspaper();
    for (Subscriber subscriber : subscribers) {
       subscriber.receive(pub);
    }
  }
}
อินเตอร์ เฟส Subscriber
public interface Subscriber {
  public void receive(Publication publication);
}
คลาส Reader
public class Reader implements Subscriber {
  private String name;

    public Reader(String name) {
      this.name = name;
    }
     public void receive(Publication publication) {
      System.out.println(name + " received " + publication);
    }
}
การเรียกใช้ งาน
public class PublishSubscribeTest {
  public static void main(String[] args) {
    Reader reader1 = new Reader("reader 1");
        Reader reader2 = new Reader("reader 2");
        Publisher publisher = new NewspaperPublisher();
        publisher.subscribe(reader1);
        publisher.subscribe(reader2);
        publisher.publish();
    }
}
ผลการรัน
reader 1 received Newspaper@6b97fd
reader 2 received Newspaper@6b97fd
- State
- Strategy
- Template method
เทมเพลทเมธอดแพตเทิร์น (Template method pattern)
                                                               ึ                               ้
เป็ นดีไซน์แพตเทิร์นที่ใช้ กาหนดแม่แบบหรื อโครงหลักของอัลกอริ ทม โดยไม่ได้ กาหนดรายละเอียดของขันตอนต่างๆ
                                               ้
ซับคลาสสามารถนิยามรายละเอียดของแต่ละขันตอนย่อยได้ ตามความต้ องการ
เทมเพลทเมธอดถูกใช้ เป็ นส่วนหลักของซอฟต์แวร์ เฟรมเวิร์ก ตัวอย่างที่นอกเหนือจากการเขียนโปรแกรมเช่น
แบบแปลนบ้ านที่เจ้ าของบ้ านสามารถเลือกสีและตบแต่งได้ ภายหลัง
องค์ประกอบของเทมเพลทเมธอดแพตเทิร์นมีดงนี ้  ั
คลาสนามธรรม (Abstract class) เป็ นผู้กาหนดโครงหลักในการทางาน
           ้
กาหนดขันตอนย่อยของการทางานโดยไม่กาหนดรายละเอียด โดยสร้ างเป็ นเมธอดนามธรรม (Abstract method)
หรื ออาจจะกาหนดการทางานพื ้นฐานไว้ ก็ได้
                                       ึ              ั้
สร้ างเทมเพลทเมธอดที่มีโครงของอัลกอริ ทมและเรี ยกใช้ ขนตอนย่อยที่ได้ นิยามไว้ แล้ วเป็ นเมธอดนามธรรม
คลาสรูปธรรม (Concrete class) ซับคลาส
ตัวอย่ างโค้ ด
ภาษาจาวา
                                                                      ่ ่ ู
ตัวอย่างโปรแกรมคานวณหาปริมาตรของรูปทรงกระบอกและรูปทรงสีเ่ หลียมซึงมีสตรร่วมกันดังนี ้
ปริ มาตร = พื ้นที่ฐาน * ความสูง
โดยที่
คานวณหาปริ มาตรในเทมเพลทเมธอดของคลาสนามธรรม
                                     ่                             ่
พื ้นที่ฐานของทรงกระบอกและทรงสีเ่ หลียมมีวิธีการหาที่แตกต่างกัน อยูในเมธอดของซับคลาสรูปธรรม
คลาสนามธรรม ThreeDShape นิยามเมธอด getBaseArea() getHeight() และ getVolume()
  ่
ซึงเป็ นเทมเพลทเมธอดมีรายละเอียดการคานวณหาปริมาตร
public abstract class ThreeDShape {
  public abstract double getBaseArea();
  public abstract double getHeight();
  /**
  * The Template Method
  */
  public double getVolume() {
    return getBaseArea() * getHeight();
  }
}
                                                ่
คลาสรูปธรรม Cylinder กาหนดวิธีการหาพื ้นที่ฐานซึงเป็ นรูปวงกลมในเมธอด getBaseArea()
public class Cylinder extends ThreeDShape {
  private final double radius;
  private final double height;
   public Cylinder(double radius, double height) {
    this.radius = radius;
    this.height = height;
  }
   @Override
  public double getBaseArea() {
    return Math.PI * radius * radius;
  }
   @Override
  public double getHeight() {
    return height;
  }
}
                                           ่                ่
คลาสรูปธรรม Box กาหนดวิธีการหาพื ้นที่ฐานซึงเป็ นรูปสีเ่ หลียมในเมธอด getBaseArea()
public class Box extends ThreeDShape {
  private final double width;
  private final double length;
  private final double height;
   public Box(double width, double length, double height) {
    this.width = width;
    this.length = length;
    this.height = height;
  }
   @Override
  public double getBaseArea() {
    return width * length;
  }
   @Override
  public double getHeight() {
    return height;
  }
}

- Visitor pattern
Definition
         Represent an operation to be performed on the elements of an object structure. Visitor lets you
define a new operation without changing the classes of the elements on which it operates.
Participants
   The classes and/or objects participating in this pattern are:
Visitor (Visitor)
      declares a Visit operation for each class of ConcreteElement in the object structure. The
         operation's name and signature identifies the class that sends the Visit request to the visitor.
       That lets the visitor determine the concrete class of the element being visited. Then the visitor
       can access the elements directly through its particular interface
ConcreteVisitor (IncomeVisitor, VacationVisitor)
    implements each operation declared by Visitor. Each operation implements a fragment of the
       algorithm defined for the corresponding class or object in the structure. ConcreteVisitor
       provides the context for the algorithm and stores its local state. This state often accumulates
       results during the traversal of the structure.
Element (Element)
    defines an Accept operation that takes a visitor as an argument.
ConcreteElement (Employee)
    implements an Accept operation that takes a visitor as an argument
ObjectStructure (Employees)
    can enumerate its elements
    may provide a high-level interface to allow the visitor to visit its elements
    may either be a Composite (pattern) or a collection such as a list or a s



Summary of Creational Patterns
The Factory Pattern is used to choose and return an instance of a class from a number of similar classes
based on data you provide to the factory.
The Abstract Factory Pattern is used to return one of several groups of classes. In some cases it actually
returns a Factory for that group of classes.
The Builder Pattern assembles a number of objects to make a new object, based on the data with which
it is presented. Frequently, the choice of which way the objects are assembled is achieved using a
Factory.
The Prototype Pattern copies or clones an existing class rather than creating a new instance when
creating new instances is more expensive.
The Singleton Pattern is a pattern that insures there is one and only one instance of an object, and that
it is possible to obtain global access to that one instance.

Summary of structural patterns
In this chapter we have seen the
The Adapter pattern, used to change the interface of one class to that of another one.
The Bridge pattern intended to keep the interface to your client program constant while allowing you to
change the actual kind of class you display or use. You can then change the interface and the underlying
class separately.
The Composite pattern, a collection of objects, any one of which may be either itself a Composite, or
just a primitive object.
The Decorator pattern, a class that surrounds a given class, adds new capabilities to it, and passes all
the unchanged methods to the underlying class.
The Façade pattern, which groups a complex object hierarchy and provides a new, simpler interface to
access those data.
The Flyweight pattern, which provides a way to limit the proliferation of small, similar class instances by
moving some of the class data outside the class and passing it in during various execution methods.
The Proxy pattern, which provides a simple place-holder class for a more complex class which is
expensive to instantiate.

								
To top