国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

探索設計模式的魅力:一次設計,多次利用,深入理解原型模式的設計藝術

這篇具有很好參考價值的文章主要介紹了探索設計模式的魅力:一次設計,多次利用,深入理解原型模式的設計藝術。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

?探索設計模式的魅力:一次設計,多次利用,深入理解原型模式的設計藝術,設計模式,設計模式,原型模式,java,面試,職場發(fā)展,程序人生,學習筆記

? ? 原型模式是一種設計模式,屬于創(chuàng)建型模式的一種,它用于創(chuàng)建重復的對象,同時又能保持性能。在原型模式中,通過復制現(xiàn)有對象的原型來創(chuàng)建新對象,而不是通過實例化類來創(chuàng)建對象。這樣做可以避免耗費過多的資源開銷,特別是在對象的創(chuàng)建過程比較復雜或耗時的情況下。

? ? 在原型模式中,原型對象實現(xiàn)一個克隆方法(Clone)用于復制自身,當需要創(chuàng)建新對象時,就可以通過克隆原型對象來得到一個新的對象副本。原型模式通常包括淺拷貝和深拷貝兩種形式,淺拷貝只復制對象本身,而深拷貝則會連同對象引用的其他對象一起復制,因此能夠得到完全獨立的新對象。

? ? 原型模式可以在需要大量創(chuàng)建相似對象的場景中發(fā)揮作用,它能夠提高對象的創(chuàng)建效率,同時也能夠減少對類的直接依賴,使系統(tǒng)結構更靈活。

??關鍵角色有兩個:

  1. 原型(Prototype):定義用于復制現(xiàn)有對象的接口,通常包含一個克隆方法,用于返回一個克隆對象。
  2. 具體原型(Concrete Prototype):實現(xiàn)原型接口,實現(xiàn)克隆方法來復制自身。

??優(yōu)點:

  1. 減少對象創(chuàng)建時間:原型模式通過復制現(xiàn)有對象來創(chuàng)建新對象,避免了昂貴的對象創(chuàng)建過程,特別是在需要頻繁創(chuàng)建相似對象時,可以大大減少對象創(chuàng)建的時間和開銷。
  2. 簡化對象創(chuàng)建過程:原型模式封裝了對象的創(chuàng)建過程,客戶端無需關心具體的創(chuàng)建細節(jié),使得對象創(chuàng)建變得更加簡單,提高了系統(tǒng)的可維護性和擴展性。
  3. 動態(tài)增加或減少原型:原型模式允許動態(tài)地添加或刪除原型,使得系統(tǒng)更加靈活,能夠根據(jù)需求動態(tài)創(chuàng)建新的原型對象。

??缺點:

  1. 需要理解原型對象:在使用原型模式時,需要確保原型對象的克隆方法能夠正確地復制對象的狀態(tài),有時需要深度復制而不是淺復制,這需要額外的處理和理解。
  2. 難以保持一致性:原型模式可能會造成系統(tǒng)中的一些對象克隆出來之后狀態(tài)難以保持一致,特別是涉及到對象之間的引用關系時,需要特別小心處理。

? 本質體現(xiàn)了兩個關鍵點:

  1. 原型:具備復制能力的對象,它是創(chuàng)建新對象的模板。原型可以是一個接口、抽象類或具體類,關鍵是它需要提供克隆自身的方法。
  2. 克?。焊鶕?jù)原型對象復制出來的新對象??寺∵^程可以是淺復制(只復制對象本身)或者深復制(復制對象和其引用的對象)。

? ??原型模式的本質是通過復制現(xiàn)有對象來創(chuàng)建新對象,從而封裝了對象的創(chuàng)建過程,提供了一種靈活、高效的對象創(chuàng)建方式。

目錄

一、案例

1.1?不用模式來實現(xiàn)

1.2 有何問題

1.3 原型模式重構代碼

1.4?完美實現(xiàn)?

三、模式講解

3.1?功能

3.2?原型模式的結構和說明

?3.3?幾種工廠模式總結


一、案例

場景:前段時間有一個考試,發(fā)現(xiàn)在一個教室里考試的試卷有ABCDEFG卷,座位上前后左右人的卷子跟我的都不一樣??纪旰舐犂蠋熣f,ABCDEFG卷的題目是一樣的,意思就是題目是一樣的,題目的順序是打亂的甚至同一個題的選項的順序也是打亂的。

? ? 下面我們從無到有來感受原型模式的設計藝術。

1.1?不用模式來實現(xiàn)

? 選擇題類:

@Data
public class ChoiceQuestion {

    /**
     * 選擇題題目
     */
    private String title;
    /**
     * 選項
     */
    private Map<String, String> options;
    /**
     * 答案
     */
    private String key;

    public ChoiceQuestion(){}
    public ChoiceQuestion(String title, Map<String, String> options, String key) {
        this.title = title;
        this.options = options;
        this.key = key;
    }
}

? 填空題類:

@Data
public class Completion {

    /**
     * 填空題題目
     */
    private String title;
    /**
     * 答案
     */
    private List<String> key;
    public Completion() {}

    public Completion(String title, List<String> key) {
        this.title = title;
        this.key = key;
    }
}

? 試卷類:

public class TestPaper {

    /**
     * 創(chuàng)建試卷
     * @param name 考生姓名
     * @param code 考生編號
     * @return
     */
    public String createPaper(String name, String code) {
        // 這里舉例有兩道選擇題和兩道填空題
        List<ChoiceQuestion> choiceQuestionList = new ArrayList<>(2);
        List<Completion> completionList = new ArrayList<>(2);

        // 初始化選擇題
        Map<String, String> choiceMap1 = new HashMap<>();
        choiceMap1.put("A", "1");
        choiceMap1.put("B", "2");
        choiceMap1.put("C", "3");
        choiceMap1.put("D", "4");
        Map<String, String> choiceMap2 = new HashMap<>();
        choiceMap2.put("A", "1");
        choiceMap2.put("B", "2");
        choiceMap2.put("C", "3");
        choiceMap2.put("D", "4");
        choiceQuestionList.add(new ChoiceQuestion("1 + 1 = ", choiceMap1, "B"));
        choiceQuestionList.add(new ChoiceQuestion("3 + 1 = ", choiceMap2, "D"));

        // 初始化填空題
        List<String> comList1 = new ArrayList<>();
        comList1.add("富強");
        comList1.add("民主");
        List<String> comList2 = new ArrayList<>();
        comList2.add("51");
        comList2.add("21");

        completionList.add(new Completion("任意列舉出兩個社會主義核心價值觀", comList1));
        completionList.add(new Completion("2008年中國獲得金牌數(shù)___枚,銀牌___枚", comList2));

        String newLine = "\n";
        // 組裝試卷
        StringBuffer strBuff = new StringBuffer();
        strBuff.append("考生:").append(name).append(newLine)
                .append("考號:").append(code).append(newLine)
                .append("一、選擇題").append(newLine);

        for (ChoiceQuestion choiceQuestion : choiceQuestionList) {
            strBuff.append(choiceQuestion.getTitle()).append(newLine);
            for (Map.Entry<String, String> entry : choiceQuestion.getOptions().entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                strBuff.append(key).append(":").append(value).append(newLine);
            }
            strBuff.append("答案:").append(choiceQuestion.getKey()).append(newLine);
        }
        for (Completion completion : completionList) {
            strBuff.append(completion.getTitle()).append(newLine);
            strBuff.append("答案:");
            for (String anster : completion.getKey()) {
                strBuff.append("  ").append(anster);
            }
        }

        return strBuff.toString();
    }
}

? 測試客戶端:

public class Client {

    public static void main(String[] args) {
        TestPaper testPaper = new TestPaper();
        System.out.println(testPaper.createPaper("張三", "ACCDF0001"));
        System.out.println(testPaper.createPaper("李四", "ACCDF0002"));
        System.out.println(testPaper.createPaper("王五", "ACCDF0003"));

    }
}

? 運行結果如下:

考生:張三
考號:ACCDF0001
一、選擇題
1 + 1 = 
A:1
B:2
C:3
D:4
答案:B
3 + 1 = 
A:1
B:2
C:3
D:4
答案:D
任意列舉出兩個社會主義核心價值觀
答案:  富強  民主
2008年中國獲得金牌數(shù)___枚,銀牌___枚
答案:  51  21

考生:李四
考號:ACCDF0002
一、選擇題
1 + 1 = 
A:1
B:2
C:3
D:4
答案:B
3 + 1 = 
A:1
B:2
C:3
D:4
答案:D
任意列舉出兩個社會主義核心價值觀
答案:  富強  民主
2008年中國獲得金牌數(shù)___枚,銀牌___枚
答案:  51  21

考生:王五
考號:ACCDF0003
一、選擇題
1 + 1 = 
A:1
B:2
C:3
D:4
答案:B
3 + 1 = 
A:1
B:2
C:3
D:4
答案:D
任意列舉出兩個社會主義核心價值觀
答案:  富強  民主
2008年中國獲得金牌數(shù)___枚,銀牌___枚
答案:  51  21

? 一坨坨代碼很快就實現(xiàn)了,看上去很簡單。?

????????

1.2 有何問題

  • 以上呢就是三位考試的試卷; 線三 、李四和王五 ,每個?人的試卷內(nèi)容是?一樣的這沒問題,但是三個人的題?以及選項順序和答案都是一樣的,但是沒有達到我們的場景中“ABCDEFG卷題目順序和選項順序都不一樣”的目的。
  • 以上代碼?非常難擴展,隨著題?目的不不斷的增加以及亂序功能的補充,都會讓這段代碼變 得越來越混亂。?

?????????

1.3 原型模式重構代碼

原型模式解決的痛點:創(chuàng)建?量重復的類,?我們的場景就需要給不不同的用戶都創(chuàng)建相同的試卷,但這些試卷的題目不便于每次都從庫中獲取,甚至有時候需要從遠程的RPC中獲取。這樣都是?常耗時的,?且隨著創(chuàng)建對象的增多將嚴重影響效率。

????????

?用原型模式注意要點:

  • 原型對象的接口:在原型模式中,原型對象需要實現(xiàn)一個克隆方法(Clone),該方法用于復制自身并返回一個新的對象副本。這需要確保原型對象具有適當?shù)慕涌诤涂寺∧芰Α?/p>

  • 淺拷貝和深拷貝:在實現(xiàn)克隆方法時,需要考慮對象中是否存在引用類型的成員變量。淺拷貝只會復制對象本身,而不會復制對象包含的引用類型成員變量,這意味著原型對象和克隆對象會引用同一個引用類型的成員變量。深拷貝則會復制對象本身以及其引用類型的成員變量,使得原型對象和克隆對象完全獨立。選擇淺拷貝還是深拷貝取決于實際需求和設計考慮。

  • 創(chuàng)建新對象的方式:在使用原型模式創(chuàng)建新對象時,可以通過調用原型對象的克隆方法,或者使用原型管理器(Prototype Manager)來獲取新對象。原型管理器可以維護一組原型對象,并根據(jù)需要返回相應的克隆對象。

  • 修改克隆對象:當獲得克隆對象后,可以根據(jù)需要對克隆對象做進一步的修改。這使得每個克隆對象都可以根據(jù)需求進行個性化的定制。

?????????

? 代碼改造

? 添加選項答案類:

@Data
public class Option {

    /**
     * 選項
     */
    private Map<String, String> options;
    /**
     * 答案
     */
    private String key;

    public Option(Map<String, String> options, String key) {
        this.options = options;
        this.key = key;
    }
}

? 添加選項亂序工具類:

public class RandomUtil {

    /**
     * 亂序Map元素,記錄對應答案key
     * @param option 題?選項 
     * @param key 答案
     * @return Option 亂序后 {A=c., B=d., C=a., D=b.} */
    static public Option random(Map<String, String> option, String key) {
        Set<String> keySet = option.keySet();
        ArrayList<String> keyList = new ArrayList<>(keySet);
        Collections.shuffle(keyList);
        HashMap<String, String> optionNew = new HashMap<>();
        int idx = 0;
        String keyNew = "";
        for (String next : keySet) {
            String randomKey = keyList.get(idx++);
            if (key.equals(next)) {
                keyNew = randomKey;
            }
            optionNew.put(randomKey, option.get(next));
        }
        return new Option(optionNew, keyNew);
    }
}

? 添加題庫類

@Data
public class QuestionBank implements Cloneable {

    /**
     * 試卷序號
     */
    private String seq;
    /**
     * 考生姓名
     */
    private String name;
    /**
     * 考生考號
     */
    private String code;

    private ArrayList<ChoiceQuestion> choiceQuestionList = new ArrayList<>(2);
    private ArrayList<Completion> completionList = new ArrayList<>(2);

    /**
     * 實現(xiàn)中題目可能來自數(shù)據(jù)庫中,這里示例便直接寫死
     */
    public QuestionBank() {

        // 初始化選擇題
        Map<String, String> choiceMap1 = new HashMap<>();
        choiceMap1.put("A", "1");
        choiceMap1.put("B", "2");
        choiceMap1.put("C", "3");
        choiceMap1.put("D", "4");
        Map<String, String> choiceMap2 = new HashMap<>();
        choiceMap2.put("A", "1");
        choiceMap2.put("B", "2");
        choiceMap2.put("C", "3");
        choiceMap2.put("D", "4");
        this.choiceQuestionList.add(new ChoiceQuestion("1 + 1 = ", choiceMap1, "B"));
        this.choiceQuestionList.add(new ChoiceQuestion("3 + 1 = ", choiceMap2, "D"));

        // 初始化填空題
        List<String> comList1 = new ArrayList<>();
        comList1.add("富強");
        comList1.add("民主");
        List<String> comList2 = new ArrayList<>();
        comList2.add("51");
        comList2.add("21");

        this.completionList.add(new Completion("任意列舉出兩個社會主義核心價值觀", comList1));
        this.completionList.add(new Completion("2008年中國獲得金牌數(shù)___枚,銀牌___枚", comList2));
    }

    @Override
    public QuestionBank clone() {
        try {
            QuestionBank questionBank = (QuestionBank) super.clone();
            questionBank.setChoiceQuestionList((ArrayList<ChoiceQuestion>) this.getChoiceQuestionList().clone());
            questionBank.setCompletionList((ArrayList<Completion>) this.getCompletionList().clone());

            // 打亂選擇題
            Collections.shuffle(questionBank.getChoiceQuestionList());
            // 選擇題的選項打亂
            for (ChoiceQuestion choiceQuestion : questionBank.getChoiceQuestionList()) {
                Option option = RandomUtil.random(choiceQuestion.getOptions(), choiceQuestion.getKey());
                choiceQuestion.setOptions(option.getOptions());
                choiceQuestion.setKey(option.getKey());
            }
            // 打亂填空題
            Collections.shuffle(questionBank.getCompletionList());

            return questionBank;
        } catch (Exception e) {
            throw new AssertionError();
        }
    }

    @Override
    public String toString() {
        String newLine = "\r\n";
        StringBuffer strBuff = new StringBuffer();
        strBuff.append("考卷:").append(getSeq()).append(newLine)
                .append("考生:").append(getName()).append(newLine)
                .append("考號:").append(getCode()).append(newLine);
        strBuff.append("一、選擇題").append(newLine);

        for (ChoiceQuestion choiceQuestion : getChoiceQuestionList()) {
            strBuff.append(choiceQuestion.getTitle()).append(newLine);
            for (Map.Entry<String, String> entry : choiceQuestion.getOptions().entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                strBuff.append(key).append(":").append(value).append(newLine);
            }
            strBuff.append("答案:").append(choiceQuestion.getKey()).append(newLine);
        }

        strBuff.append("一、填空題").append(newLine);
        for (Completion completion : getCompletionList()) {
            strBuff.append(completion.getTitle()).append(newLine);
            strBuff.append("答案:");
            for (String anster : completion.getKey()) {
                strBuff.append("  ").append(anster);
            }
        }

        return strBuff.toString();
    }
}

? 試卷類改造:

@Data
public class TestPaper {

    /**
     * 題庫
     */
    QuestionBank questionBank = new QuestionBank();

    /**
     * 創(chuàng)建試卷
     * @param req 試卷序號
     * @param name 考生姓名
     * @param code 考生編號
     * @return
     */
    public String createPaper(String req, String name, String code) {
        QuestionBank questionBankClone = this.getQuestionBank().clone();
        questionBankClone.setSeq(req);
        questionBankClone.setName(name);
        questionBankClone.setCode(code);

        return questionBankClone.toString();
    }
}

? 改造測試客戶端:

public class Client {

    public static void main(String[] args) {
        // 創(chuàng)建試卷工具類并初始化題庫
        TestPaper testPaper = new TestPaper();
        // 創(chuàng)建張三
        System.out.println(testPaper.createPaper("A", "張三", "A0001"));
        System.out.println(testPaper.createPaper("B", "李四", "A0002"));
        System.out.println(testPaper.createPaper("C", "王五", "A0003"));
    }
}

? 運行結果如下:

? (考卷A)

考卷:A
考生:張三
考號:A0001
一、選擇題
1 + 1 = 
A:3
B:1
C:2
D:4
答案:C
3 + 1 = 
A:3
B:1
C:4
D:2
答案:C
一、填空題
2008年中國獲得金牌數(shù)___枚,銀牌___枚
答案:  51  21
任意列舉出兩個社會主義核心價值觀
答案:  富強  民主

? (考卷B)

考卷:B
考生:李四
考號:A0002
一、選擇題
3 + 1 = 
A:4
B:1
C:2
D:3
答案:A
1 + 1 = 
A:2
B:4
C:3
D:1
答案:A
一、填空題
2008年中國獲得金牌數(shù)___枚,銀牌___枚
答案:  51  21
任意列舉出兩個社會主義核心價值觀
答案:  富強  民主

? (考卷C)

考卷:C
考生:王五
考號:A0003
一、選擇題
1 + 1 = 
A:1
B:4
C:3
D:2
答案:D
3 + 1 = 
A:4
B:3
C:1
D:2
答案:A
一、填空題
任意列舉出兩個社會主義核心價值觀
答案:  富強  民主
2008年中國獲得金牌數(shù)___枚,銀牌___枚
答案:  51  21

?????????

1.4?完美實現(xiàn)?

? ? 從上面結果看出,A卷、B卷和C卷的題目和選項都被打亂了。再添加DEF等卷,就完美實現(xiàn)了案例場景下我座位中前后左右人的卷子與我不同的情況。

????????

三、模式講解

本質:通過復制現(xiàn)有對象來創(chuàng)建新對象,從而封裝了對象的創(chuàng)建過程,提供了一種靈活、高效的對象創(chuàng)建方式。

3.1?功能

? ? 原型模式?的功能?實際上包含兩個方面:

  • 一個是通過克隆來創(chuàng)建新的對象實例;
  • 另一個是為克隆出來的對象實例復制原型實例屬性的值。

3.2?原型模式的結構和說明

探索設計模式的魅力:一次設計,多次利用,深入理解原型模式的設計藝術,設計模式,設計模式,原型模式,java,面試,職場發(fā)展,程序人生,學習筆記

  • Prototype:聲明一個克隆自身的接口,用來約束想要克隆自己的類,要求它們都要實現(xiàn)這里定義的克隆方法。
  • ConcretePrototype:實現(xiàn)Prototype接口的類,這些類真正實現(xiàn)了克隆自身的功能。
  • Client:使用原型的客戶端,首先獲取到原型對象,然后通過原型實例克隆自身來創(chuàng)建新的對象實例。

????????

?3.3?幾種工廠模式總結

? ??工廠方法、抽象工廠、建造者模式和原型模式是常見的軟件設計模式,它們各自解決了不同類型的設計問題。

  1. 工廠方法模式:
    工廠方法模式是一種創(chuàng)建型設計模式,它提供了一種將對象的創(chuàng)建和使用分離的方式。核心在于定義一個創(chuàng)建對象的接口,但將具體的創(chuàng)建過程延遲到子類中進行實現(xiàn)。

  2. 抽象工廠模式:
    抽象工廠模式也是一種創(chuàng)建型設計模式,它提供了一種創(chuàng)建一系列相關或相互依賴對象的接口,而無需指定具體的類。核心在于提供一個能夠創(chuàng)建一系列產(chǎn)品的工廠接口,而具體的工廠類負責實現(xiàn)這個接口并創(chuàng)建具體的產(chǎn)品。

  3. 建造者模式:
    建造者模式是一種創(chuàng)建型設計模式,它將一個復雜對象的構建過程與其表示相分離,并允許使用相同的構建過程來創(chuàng)建不同的表示。核心在于將對象的構建過程分解成多個步驟,并提供一個統(tǒng)一的接口來組合這些步驟,從而創(chuàng)建復雜對象。

  4. 原型模式:
    原型模式是一種創(chuàng)建型設計模式,它允許通過復制現(xiàn)有對象來創(chuàng)建新對象,而不是通過實現(xiàn)一個特定的工廠方法來創(chuàng)建對象。核心在于通過克隆已有的對象來創(chuàng)建新的對象,從而避免了通過構造函數(shù)創(chuàng)建對象時的復雜性。

??區(qū)別:文章來源地址http://www.zghlxwxcb.cn/news/detail-817355.html

  • 工廠方法模式和抽象工廠模式都是用于對象創(chuàng)建,但工廠方法模式關注于單個對象的創(chuàng)建,而抽象工廠模式關注于一系列相關對象的創(chuàng)建。
  • 建造者模式主要用于創(chuàng)建復雜對象,并且可以根據(jù)需要定制對象的不同表示,而工廠方法和抽象工廠模式更多地關注于對象的創(chuàng)建過程和對象的組合。
  • 原型模式主要用于通過復制來創(chuàng)建新對象,避免了直接通過構造函數(shù)創(chuàng)建對象時的復雜性,與工廠方法、抽象工廠和建造者模式的區(qū)別在于其實現(xiàn)方式和目的不同。

到了這里,關于探索設計模式的魅力:一次設計,多次利用,深入理解原型模式的設計藝術的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包