GoF Design Patterns - อันไหนที่คุณใช้จริง? [ปิด]


16

ฉันพยายามให้ความรู้แก่เพื่อนร่วมงานในด้านรูปแบบการออกแบบ รูปแบบดั้งเดิมของ Gang of Four บางอันมีความลับเล็กน้อยดังนั้นฉันจึงสงสัยว่ามีรูปแบบ "จำเป็น" ของกลุ่มย่อยที่โปรแกรมเมอร์ทุกคนควรรู้หรือไม่ เมื่อฉันดูรายการฉันคิดว่าฉันอาจใช้

  • โรงงานบทคัดย่อ
  • วิธีการโรงงาน
  • ซิงเกิล
  • สะพาน
  • หน้าตึก
  • คำสั่ง

อันไหนที่คุณใช้จริงในการปฏิบัติและสิ่งที่คุณใช้พวกเขาสำหรับ?

ลิงก์สำหรับผู้ที่ต้องการรายการรูปแบบ


7
IMHO คำถามนั้นคลุมเครือเกินไปที่จะให้การอภิปรายที่มีประโยชน์ คุณต้องการหนึ่งคำตอบต่อรูปแบบหรือหนึ่งคำตอบต่อรูปแบบผสมกันหรือไม่?
Macke

เหตุผลบางประการที่ทำให้คุณใช้รูปแบบเหล่านี้จะมีประโยชน์ไม่เช่นนั้นคุณก็แค่แสดงแนวคิด ... ลองจินตนาการถึงการถามคำถาม: "คุณใช้คำหลักใด" และการรวบรวมรายชื่อ " for, if, while...ฯลฯ " - เป็นการยากที่จะวัดว่าไร้ประโยชน์อย่างไร
ocodo

1
ฉันไม่เห็นด้วยกับ Slomojo - ฉันคิดว่ามันค่อนข้างมีประโยชน์หากรู้ว่าคำหลักใดที่ใช้กันทั่วไปและไม่ได้ใช้ภาษาใด กันไปสำหรับคลาสฐานเช่น
Craig Schwarze

1
ดัดแปลงมันให้ดีขึ้นกว่าเดิมหวังว่ามันจะทำให้การสนทนาดีขึ้น
Craig Schwarze

1
ผลไม้ชนิดใดที่คุณกินจริง? ฉันอยากรู้ว่าคุณคาดหวังอะไรจากคำถามนี้ หากคุณเห็นรูปแบบที่มีผู้ใช้ 3 หรือ 4 คน แต่คุณไม่ได้ใช้นั่นจะทำให้คุณใช้งานได้หรือไม่
Marcie

คำตอบ:


4

นี่คือรายการที่ฉันเคยใช้หรือเคยเห็นในทางปฏิบัติ:

Singleton - แอ็พพลิเคชันอ็อบเจ็กต์ใน ASP.Net เป็นตัวอย่างที่สำคัญของสิ่งนี้

อะแดปเตอร์ - การเชื่อมต่อกับฐานข้อมูลมักจะเกี่ยวข้องกับคลาสอะแดปเตอร์อย่างน้อยในพื้นที่ของฉัน.

โรงงาน - ทั่วไปสำหรับการสร้างวัตถุแม้ว่าฉันจะเห็นสิ่งนี้มากขึ้นใน ASP แบบเก่าที่เก่ากว่าในสมัยนั้น

กลยุทธ์ - ฉันมีแอปพลิเคชั่นสำหรับอุปกรณ์แต่ละประเภทที่ฉันมีโครงสร้างคล้ายกันสำหรับชั้นเรียนที่ฉันพิจารณาการใช้รูปแบบนี้

Facade - ในบางวิธีสิ่งนี้จะคล้ายกับรูปแบบของอะแดปเตอร์ในแง่ของการเป็นสิ่งที่เชื่อมโยงเข้าด้วยกันเป็นสองระบบ


1
การใช้งานที่ถูกต้องทั้งหมด สำหรับทุกคนที่อ่านข้อความนี้ - โปรดจำไว้ว่ารูปแบบเหล่านี้ไม่ได้ จำกัด อยู่เพียงแค่นี้
Boris Yankov

5

ผู้เขียนรวบรวมรูปแบบจากการสังเกตที่พบในการใช้งานจริง ไม่มีใครมีแนวโน้มที่จะใช้พวกเขาทั้งหมด แต่พวกเขาทั้งหมดจะถูกใช้


คุณใช้ smithco ตัวไหนและอะไรกัน
Craig Schwarze

@CraigS ฉันใช้หลายคน ผู้เขียนของรูปแบบการออกแบบมีตัวอย่างที่ดีซึ่งแต่ละรูปแบบจะอธิบาย ข้อแนะนำที่ดีที่สุดที่ฉันให้ได้คือใช้เวลาอ่านหนังสือให้ละเอียด
smithco

3

มัณฑนากร

แก้ไข : ในเกือบทุกโครงการที่อยู่นอกเหนือระยะ 'เล็กน้อย' โครงการหนึ่งจบลงด้วยส่วนต่อประสาน IAction (รายละเอียดอาจแตกต่างกัน):

// Programming Language does not matter
interface IAction {
     bool operateOn(Foo* target);
     string getDisplayName(); // useful for debugging and logging
};

ชั่วโมงถัดไปฉันใช้เวลากับการเขียนชั้นเรียนขนาดเล็กจำนวนเล็กน้อยที่ใช้ IAction เมื่อรวมเข้าด้วยกันมันจะทรงพลังและยืดหยุ่นมาก

เช่นLogAction(เขียนเพื่อบันทึกและดำเนินการ IAction), NullAction(ไม่ทำอะไรเลยและคืนค่าจริง), ActionList(ทำรายการของ IActions และส่งคืน ANDing ของคนโง่) ในบางกรณีAndAction(กลับและไอเอ็นจีของทั้งสองกระทำอาจจะลัดวงจรหรือไม่) OrAction, NotActionให้ความรู้สึกได้เป็นอย่างดี

แม้ว่าในทางเทคนิคจากตัวอย่างด้านบนมีเพียง LogAction เท่านั้นที่เป็น Decorator (อีกคนไม่ทำงานใน 1 IAction อย่างแน่นอน) แต่ฉันก็ยังถือว่ารูปแบบของ Decorator ทั่วไปเมื่อฉันสร้าง ActionList ของ LogActions ของ IActions


คุณใช้มันทำอะไร?
Craig Schwarze

1
@CraigS ตัวอย่างเพิ่มตามคำขอ
Sjoerd

ดูเหมือนว่าการผสมผสานของมัณฑนากรและคอมโพสิตจริงซึ่งเป็นเรื่องที่ดีและการสาธิตที่สมบูรณ์แบบที่ความยากลำบากในรูปแบบไม่ได้มาจากการใช้อย่างอิสระ แต่จากการผสมเข้าด้วยกัน :)
Matthieu M.

ใช่นี่เป็นแบบคลาสสิก คอมโพสิตเทียบกับคำสั่ง จริงๆแล้วมีชื่อสำหรับเสื้อนี้: เรียกว่า "ข้อมูลจำเพาะ" ( en.wikipedia.org/wiki/Specification_pattern )
Martin Wickman

2

ฉันถือว่าคุณหมายถึง จำกัด คำถามสำหรับการใช้รูปแบบในรหัส / โครงการของตัวเอง (ไม่มีไลบรารีคลาสและเฟรมเวิร์กของบุคคลที่สาม)

เช่นเดียวกับคนอื่น ๆ ฉันได้ใช้รูปแบบของโรงงานบ่อยที่สุด แล้วก็

  • ซิงเกิลตัน : ไม่มากในปัจจุบัน แต่บางครั้งก็จำเป็นโดยทั่วไปแล้วสำหรับข้อมูลการกำหนดค่าทั่วโลก
  • กลยุทธ์และวิธีการเทมเพลต : ค่อนข้างบ่อยเช่นสำหรับการคำนวณประเภทต่าง ๆ ในแอปของเรา
  • ตัวสร้าง : สำหรับการเรียงลำดับผลลัพธ์ของการทำธุรกรรมด้วยระบบเมนเฟรมลงในวัตถุเอาท์พุท (ในบางกรณีจะมีการแยกวิเคราะห์ข้อความจำนวนมากและการสร้างลำดับชั้นวัตถุขนาดใหญ่)
  • คำสั่ง : ฉันใช้มันเมื่อหลายปีที่แล้ว แต่ทุกวันนี้ในโปรเจ็กต์ Java ของฉันฉันใช้ Callables ทุกตอนซึ่งฉันเชื่อว่าเป็นคำสั่งพื้นฐาน

2

ฉันใช้คนอื่นมากมายที่พูดถึงไปแล้ว (Singleton, Factory, Builder, Command, Strategy, ฯลฯ ... )

หนึ่งที่ฉันยังไม่เห็นพูดถึงคือ Flyweight ซึ่งฉันมักจะใช้บ่อย ฉันได้แสดงตัวอย่างการนำไปใช้ด้านล่าง:

/**
 * Flyweight class representing OCR digits.
 * 
 * @author matt
 *
 */
public class Digit {
    /** Static flyweight map containing Digits which have been encountered. **/
    private static Map digits = new HashMap();

    /** The block of text representing Digit. **/
    private String blockRep = null;

    /** A map representing acceptable blocks of characters and the string representation of their
     * numerical equivalents.
     */
    public static final Map VALID_DIGITS;

    /** Enum of valid digits. **/
    public static enum DigitRep {
        ZERO    (   " _ \n" +
                    "| |\n" +
                    "|_|"       ),

        ONE (       "   \n" +
                    "  |\n" +
                    "  |"       ),

        TWO (       " _ \n" +
                    " _|\n" +
                    "|_ "       ),

        THREE   (   " _ \n" +
                    " _|\n" +
                    " _|"       ),

        FOUR    (   "   \n" +
                    "|_|\n" +
                    "  |"       ),

        FIVE    (   " _ \n" +
                    "|_ \n" +
                    " _|"       ),

        SIX     (   " _ \n" +
                    "|_ \n" +
                    "|_|"       ),

        SEVEN   (   " _ \n" +
                    "  |\n" +
                    "  |"       ),

        EIGHT   (   " _ \n" +
                    "|_|\n" +
                    "|_|"       ),

        NINE    (   " _ \n" +
                    "|_|\n" +
                    " _|"       );

        private String blockRep;

        DigitRep(String blockRep) {
            this.blockRep = blockRep;
        }

        @Override
        public String toString() {
            return blockRep;
        }
    }

    static {
        /* Initialize the map of acceptable character blocks. */
        Map tmpMap = new HashMap();
        tmpMap.put( DigitRep.ZERO.toString(),   "0");
        tmpMap.put( DigitRep.ONE.toString(),    "1");
        tmpMap.put( DigitRep.TWO.toString(),    "2");
        tmpMap.put( DigitRep.THREE.toString(),  "3");
        tmpMap.put( DigitRep.FOUR.toString(),   "4");
        tmpMap.put( DigitRep.FIVE.toString(),   "5");
        tmpMap.put( DigitRep.SIX.toString(),    "6");
        tmpMap.put( DigitRep.SEVEN.toString(),  "7");
        tmpMap.put( DigitRep.EIGHT.toString(),  "8");
        tmpMap.put( DigitRep.NINE.toString(),   "9");       
        VALID_DIGITS = Collections.unmodifiableMap(tmpMap);
    }

    /**
     * Private constructor to enforce flyweight/factory pattern.
     * 
     * @param blockRep
     */
    private Digit(String blockRep) {
        this.blockRep = blockRep;
    }

    /**
     * Flyweight factory method to create a Digit object from the "block"
     * representation of the digit.
     * @param blockRep The "block" representation of a digit.  Should look
     * something like:
     * " _ \n"
     * "|_|\n"
     * "|_|"
     * @return A flyweight Digit object representing the digit.
     */
    public static synchronized Digit getDigit(String blockRep) {
        Digit digit = digits.get(blockRep);
        if(digit == null) {
            digit = new Digit(blockRep);
            digits.put(blockRep, digit);
        }

        return digit;
    }

    /**
     * Determines whether or not the digit is valid.
     * @return true if the digit is valid, else false.
     */
    public boolean isValid() {
        return VALID_DIGITS.containsKey(blockRep);
    }

    /**
     * Accessor method to get the block representation of this digit.
     * 
     * @return
     */
    public String getBlockRep() {
        return blockRep;
    }

    @Override
    public String toString() {
        return VALID_DIGITS.containsKey(blockRep) ? VALID_DIGITS.get(blockRep) : "?";
    }
}

1
+1 หนึ่งในรูปแบบที่รู้จักน้อยกว่า แต่ยังมีประโยชน์อย่างไม่น่าเชื่อ
MattDavey

2

รูปแบบดั้งเดิมของ Gang of Four ส่วนใหญ่ยังคงใช้มาจนถึงปัจจุบัน แต่ยังมีอีกรูปแบบหนึ่งที่ได้รับความนิยมซึ่งไม่ได้อยู่ในหนังสือ

ค้นหาการอ้างอิงสำหรับ Design Patters ในภาษาที่คุณใช้ พวกเขามีแนวโน้มที่จะเป็นรูปธรรมมากขึ้นและใช้คุณลักษณะภาษาเฉพาะเพื่อใช้รูปแบบในลักษณะที่กระชับและสง่างามยิ่งขึ้น

สามแหล่งข้อมูลที่ยอดเยี่ยมสำหรับรูปแบบการออกแบบ:

หนังสือ "Head First Design Patterns" - ภาษาที่เลือกคือ Java แต่เกี่ยวข้องกับทุกภาษา รูปแบบการออกแบบ dofactory - คำอธิบายรูปแบบการออกแบบสุทธิที่ยอดเยี่ยมและฟรีพร้อมรหัส PluralSight - Design Patterns Library - อันนี้จ่าย แต่ไม่ดีที่จะไม่รวมไว้ในรายการ


1

ถ้าคุณใช้ไลบรารีทั่วไปเช่น ACE คุณจะใช้มากกว่าที่คุณคิด ฉันใช้ผู้สังเกตการณ์ / สังเกตอย่างกว้างขวาง :-)


1

ฉันใช้ตัวสร้างอย่างน้อยหนึ่งครั้ง (กระบวนการแปลงเดียวกันสามารถสร้างผลลัพธ์ HTML หรือ Excel)

ฉันมักจะใช้วิธีการเทมเพลต (สำหรับงานที่เกี่ยวข้องกับ JDBC หรือตัวควบคุมสวิงที่เป็นนามธรรม)

เมื่อฉันต้องพัฒนาฟีเจอร์ใหม่ ๆ ให้กลายเป็นแอพพลิเคชั่นที่ใช้แบบฟอร์มซึ่งเป็นระเบียบ ฉันสามารถดำเนินการต่อได้หลังจากที่ฉันได้รับการปรับสภาพสิ่งที่มีอยู่ให้เป็นโซลูชั่นที่ใช้รูปแบบของรัฐ (ส่วนใหญ่ของมัน)

ฉันยังใช้คำสั่งบ่อยครั้ง (Swing Actions) และผู้สังเกตการณ์ด้วย

เมื่อฉันใช้โซลูชันที่คล้าย Mem Memto เพื่อตรวจจับการเปลี่ยนแปลงในรูปแบบสวิง แบบฟอร์มจะเรียงลำดับสถานะของสิ่งที่ฉันเปรียบเทียบ (เท่ากับ ()) กับสถานะก่อนหน้า


1

ฉันเชื่อว่าฉันมีพวกเขาส่วนใหญ่ผ่านอาชีพของฉัน สิ่งเดียวที่ฉันแน่ใจว่าฉันไม่ได้ใช้ก็คือรูปแบบของอะแดปเตอร์ที่นำมาใช้กับการสืบทอดหลายครั้งในหนังสือเนื่องจากฉันไม่ใช่แฟนตัวยงของการสืบทอดหลายรายการ


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.