成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

深入理解原型模式 ——通過(guò)復(fù)制生成實(shí)例

Pocher / 725人閱讀

摘要:定義給出的原型模式定義如下使用原型實(shí)例指定將要?jiǎng)?chuàng)建的對(duì)象類型,通過(guò)復(fù)制這個(gè)實(shí)例創(chuàng)建新的對(duì)象。具體原型類角色負(fù)責(zé)實(shí)現(xiàn)復(fù)制現(xiàn)有實(shí)例并生成新實(shí)例的方法。

Java面試通關(guān)手冊(cè)(Java學(xué)習(xí)指南,歡迎Star,會(huì)一直完善下去,歡迎建議和指導(dǎo)):https://github.com/Snailclimb/Java_Guide

系列文章回顧:

設(shè)計(jì)模式專欄
深入理解單例模式
深入理解工廠模式

深入理解建造者模式 ——組裝復(fù)雜的實(shí)例

歷史文章推薦:

一只準(zhǔn)程序猿的嘮叨

可能是最漂亮的Spring事務(wù)管理詳解

Java多線程學(xué)習(xí)(八)線程池與Executor 框架

面試中關(guān)于Redis的問題看這篇就夠了

目錄:

[TOC]

一 原型模式介紹

在面向?qū)ο笙到y(tǒng)中,使用原型模式來(lái)復(fù)制一個(gè)對(duì)象自身,從而克隆出多個(gè)與原型對(duì)象一模一樣的對(duì)象。

另外在軟件系統(tǒng)中,有些對(duì)象的創(chuàng)建過(guò)程較為復(fù)雜,而且有時(shí)候需要頻繁創(chuàng)建,原型模式通過(guò)給出一個(gè)原型對(duì)象來(lái)指明所要?jiǎng)?chuàng)建的對(duì)象的類型,然后用復(fù)制這個(gè)原型對(duì)象的辦法創(chuàng)建出更多同類型的對(duì)象,這就是原型模式的意圖所在。

1.1 定義

GOF給出的原型模式定義如下:

Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype.  (使用原型實(shí)例指定將要?jiǎng)?chuàng)建的對(duì)象類型,通過(guò)復(fù)制這個(gè)實(shí)例創(chuàng)建新的對(duì)象。)
1.2 原型模式適用場(chǎng)景

我們現(xiàn)在一般會(huì)使用new關(guān)鍵字指定類名生成類的實(shí)例(PS:我們以前使用java.lang.Cloneable的一個(gè)很大原因是使用new創(chuàng)建對(duì)象的速度相對(duì)來(lái)說(shuō)會(huì)慢一些,隨著JVM性能的提升,new的速度和Object的clone()方法的速度差不多了。)。

使用new關(guān)鍵字創(chuàng)建類的時(shí)候必須指定類名,但是在開發(fā)過(guò)程中也會(huì)有“在不指定類名的前提下生成實(shí)例”的需求。例如,在下面這些情況下,就需要根據(jù)現(xiàn)有的實(shí)例來(lái)生成新的實(shí)例。

1) 對(duì)象種類繁多,無(wú)法將他們整合到一個(gè)類的時(shí)候;

2) 難以根據(jù)類生成實(shí)例時(shí);

3) 想解耦框架與生成的實(shí)例時(shí)。

如果想要讓生成實(shí)例的框架不再依賴于具體的類,這時(shí),不能指定類名來(lái)生成實(shí)例,而要事先“注冊(cè)”一個(gè)“原型”實(shí)例,然后通過(guò)復(fù)制該實(shí)例來(lái)生成新的實(shí)例。

1.3 模式分析

在原型模式結(jié)構(gòu)中定義了一個(gè)抽象原型類,所有的Java類都繼承自 java.lang.Object,而Object類提供一個(gè)clone()方法,可以將一個(gè)Java對(duì)象復(fù)制一份。因此在Java中可以直接使用Object提供的clone()方法來(lái)實(shí)現(xiàn)對(duì)象的克隆,Java語(yǔ)言中的原型模式實(shí)現(xiàn)很簡(jiǎn)單。

能夠?qū)崿F(xiàn)克隆的Java類必須實(shí)現(xiàn)一個(gè)標(biāo)識(shí)接口Cloneable,表示這個(gè)Java類支持復(fù)制。如果一個(gè)類沒有實(shí)現(xiàn)這個(gè)接口但是調(diào)用了clone()方法,Java編譯器將拋出一個(gè)CloneNotSupportedException異常。

注意: `java.lang.Cloneable 只是起到告訴程序可以調(diào)用clone方法的作用,它本身并沒有定義任何方法。

在使用原型模式克隆對(duì)象時(shí),根據(jù)其成員對(duì)象是否也克隆,原型模式可以分為兩種形式:深克隆淺克隆 。

關(guān)于深克隆淺克隆 的詳細(xì)內(nèi)容可以參考:詳解Java中的clone方法

1.4 模式優(yōu)缺點(diǎn)分析

原型模式的優(yōu)點(diǎn):

當(dāng)創(chuàng)建新的對(duì)象實(shí)例較為復(fù)雜時(shí),使用原型模式可以簡(jiǎn)化對(duì)象的創(chuàng)建過(guò)程,通過(guò)一個(gè)已有實(shí)例可以提高新實(shí)例的創(chuàng)建效率。

可以動(dòng)態(tài)增加或減少產(chǎn)品類。

原型模式提供了簡(jiǎn)化的創(chuàng)建結(jié)構(gòu)。

可以使用深克隆的方式保存對(duì)象的狀態(tài)。

原型模式的缺點(diǎn):

需要為每一個(gè)類配備一個(gè)克隆方法,而且這個(gè)克隆方法需要對(duì)類的功能進(jìn)行通盤考慮,這對(duì)全新的類來(lái)說(shuō)不是很難,但對(duì)已有的類進(jìn)行改造時(shí),不一定是件容易的事,必須修改其源代碼,違背了“開閉原則”。

在實(shí)現(xiàn)深克隆時(shí)需要編寫較為復(fù)雜的代碼。

二 示例程序

下面示例程序的作用是將字符串放入方框中顯示出來(lái)或者是加了下劃線顯示出來(lái)。

類和接口一覽表:

示例程序類圖:

2.1 Product接口 (Prototype)

Product接口是復(fù)制功能接口,該接口繼承了java.lang.Cloneable(只有實(shí)現(xiàn)了該接口的類的實(shí)例才可以調(diào)用clone()方法復(fù)制實(shí)例,否則會(huì)拋出異常).
另外需要注意:`java.lang.Cloneable 只是起到告訴程序可以調(diào)用clone方法的作用,它本身并沒有定義任何方法。

package prototype_pattern;

public interface Product extends Cloneable{
   //use方法是用于“使用”的方法,具體怎么“使用”,則被交給子類去實(shí)現(xiàn)。
    public abstract void use(String s);
    //creatClone方法是用于復(fù)制實(shí)例的方法
    public abstract Product creatClone();

}
2.2 Manager類(Client)

Manager類使用Product接口來(lái)復(fù)制實(shí)例。

Product接口以及Manager類的代碼完全沒有出現(xiàn)在MessageBox類UnderlinePen類的名字,因此這意味著我們可以獨(dú)立地修改Product接口以及Manager類,不受MessageBox類UnderlinePen類的影響。這是非常重要的,因?yàn)?一旦在類中使用到了別的類名,就意味著該類與其他類緊密的地耦合在了一起 。在Manager類中,并沒有寫明具體的類名, 僅僅使用了Product這個(gè)接口名。也就是說(shuō),Product接口成為了連接Manager類與其他具體類之間的橋梁。

package prototype_pattern;

import java.util.HashMap;

public class Manager {
    //保存實(shí)例的“名字”和“實(shí)例”之間的對(duì)應(yīng)關(guān)系
    private HashMap showcase=new HashMap();
    //register方法將接收到的一組“名字”和“Product接口”注冊(cè)到showcase中。這里Product是實(shí)現(xiàn)Product接口的實(shí)例,具體還未確定
    public void register(String name ,Product product){
        showcase.put(name, product);
    }
    public Product create(String productname){
        Product p=showcase.get(productname);
        return p.creatClone();
    }

}
2.3 MessageBox類(ConcreteProtorype)

裝飾方框樣式的具體原型,實(shí)現(xiàn)了 Product接口,實(shí)現(xiàn)復(fù)制現(xiàn)有實(shí)例并生成新實(shí)例的方法。

package prototype_pattern;

public class MessageBox implements Product {
    //保存的是裝飾方框使用的字符樣式
    private char decochar;

    public MessageBox(char decochar) {
        this.decochar = decochar;
    }

    @Override
    public void use(String s) {
     int length=s.getBytes().length;
     for (int i = 0; i < length+4; i++) {
            System.out.print(decochar);    
    }
     System.out.println("");
     System.out.println(decochar+" "+s+" "+decochar);
     for (int i = 0; i < length+4; i++) {
        System.out.print(decochar);
    }
     System.out.println("");
    }
    
    //該方法用于復(fù)制自己
    @Override
    public Product creatClone() {
        Product p=null;
        try {
            p=(Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }

}

只有類自己(或是它的子類)能夠調(diào)用Java語(yǔ)言中定義的clone方法。當(dāng)其他類要求復(fù)制實(shí)例時(shí),必須先調(diào)用createClone這樣的方法,然后在該方法內(nèi)部在調(diào)用clone方法。

2.4 UnderlinePen類(ConcreteProtorype)

下劃線樣式的具體原型,實(shí)現(xiàn)了Product接口,用于實(shí)現(xiàn)復(fù)制現(xiàn)有實(shí)例并生成新實(shí)例的方法。UnderlinePen類的實(shí)現(xiàn)幾乎和 MessageBox類一樣,不同的可能只是use方法的實(shí)現(xiàn)。

package prototype_pattern;

public class UnderlinePen implements Product {

    private char ulchar;

    public UnderlinePen(char ulchar) {
        this.ulchar = ulchar;
    }

    @Override
    public void use(String s) {
        int length = s.getBytes().length;
        System.out.println("""+s+""");
        for (int i = 0; i 
2.5 Main類

Main類首先生成Manager實(shí)例。接著,在Manager實(shí)例中通過(guò)`register方法注冊(cè)了UnderlinePen類的實(shí)例(帶名字)和MessageBox類的實(shí)例(帶名字)。

package prototype_pattern;

public class Main {

    public static void main(String[] args) {
        Manager manager = new Manager();
        UnderlinePen underlinePen=new UnderlinePen("~");
        MessageBox mbox=new MessageBox("*");
        MessageBox sbox=new MessageBox("/");
        manager.register("Strong message", underlinePen);
        manager.register("Waring Box", mbox);
        manager.register("Slash Box", sbox);
        Product p1=manager.create("Strong message");
        p1.use("hello world");
        Product p2=manager.create("Waring Box");
        p2.use("hello world");
        Product p3=manager.create("Slash Box");
        p3.use("hello world");
    }

}

運(yùn)行結(jié)果:

三 原型模式的角色分析

通過(guò)上面的例子,相信大家對(duì)于原型模式有了更進(jìn)一步的認(rèn)識(shí),下面我們看看原型模式的幾個(gè)登場(chǎng)角色。

3.1 Prototype(抽象原型類)

Product角色負(fù)責(zé)定義用于復(fù)制現(xiàn)有實(shí)例來(lái)生成新實(shí)例的方法。在示例程序中的Product接口就是該角色。

3.2 ConcretePrototype(具體原型類)

ConcretePrototype角色負(fù)責(zé)實(shí)現(xiàn)復(fù)制現(xiàn)有實(shí)例并生成新實(shí)例的方法。在示例程序中,MessageBox和UnderlinePen都是該角色。

3.3 Client(客戶類/使用者)

Client角色負(fù)責(zé)使用復(fù)制實(shí)例的方法生成新的實(shí)例。在示例程序中,Manager類扮演的就是該角色。

Prototype模式的類圖:

四 原型模式的實(shí)際應(yīng)用案例

(1) 原型模式應(yīng)用于很多軟件中,如果每次創(chuàng)建一個(gè)對(duì)象要花大量時(shí)間,原型模式是最好的解決方案。很多軟件提供的復(fù)制(Ctrl + C)粘貼(Ctrl + V)操作就是原型模式的應(yīng)用,復(fù)制得到的對(duì)象與原型對(duì)象是兩個(gè)類型相同但內(nèi)存地址不同的對(duì)象,通過(guò)原型模式可以大大提高對(duì)象的創(chuàng)建效率。

(2) 在Struts2中為了保證線程的安全性,Action對(duì)象的創(chuàng)建使用了原型模式,訪問一個(gè)已經(jīng)存在的`Action對(duì)象時(shí)將通過(guò)克隆的方式創(chuàng)建出一個(gè)新的對(duì)象,從而保證其中定義的變量無(wú)須進(jìn)行加鎖實(shí)現(xiàn)同步,每一個(gè)Action中都有自己的成員變量,避免Struts1因使用單例模式而導(dǎo)致的并發(fā)和同步問題。

(3) 在Spring中,用戶也可以采用原型模式來(lái)創(chuàng)建新的bean實(shí)例,從而實(shí)現(xiàn)每次獲取的是通過(guò)克隆生成的新實(shí)例,對(duì)其進(jìn)行修改時(shí)對(duì)原有實(shí)例對(duì)象不造成任何影響。

五 總結(jié)

本文主要介紹了:什么是原型模式、原型模式的優(yōu)缺點(diǎn)以及使用場(chǎng)景。另外,簡(jiǎn)單介紹了深拷貝和淺拷貝以及原型模式的實(shí)際應(yīng)用案例。

參考:

《圖解設(shè)計(jì)模式》

歡迎關(guān)注我的微信公眾號(hào):"Java面試通關(guān)手冊(cè)"(一個(gè)有溫度的微信公眾號(hào),無(wú)廣告,單純技術(shù)分享,期待與你共同進(jìn)步~~~堅(jiān)持原創(chuàng),分享美文,分享各種Java學(xué)習(xí)資源。)

最后,就是使用阿里云服務(wù)器一段時(shí)間后,感覺阿里云真的很不錯(cuò),就申請(qǐng)做了阿里云大使,然后這是我的優(yōu)惠券地址.

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71210.html

相關(guān)文章

  • 理解JavaScript的核心知識(shí)點(diǎn):原型

    摘要:首先,需要來(lái)理清一些基礎(chǔ)的計(jì)算機(jī)編程概念編程哲學(xué)與設(shè)計(jì)模式計(jì)算機(jī)編程理念源自于對(duì)現(xiàn)實(shí)抽象的哲學(xué)思考,面向?qū)ο缶幊淌瞧湟环N思維方式,與它并駕齊驅(qū)的是另外兩種思路過(guò)程式和函數(shù)式編程。 JavaScript 中的原型機(jī)制一直以來(lái)都被眾多開發(fā)者(包括本人)低估甚至忽視了,這是因?yàn)榻^大多數(shù)人沒有想要深刻理解這個(gè)機(jī)制的內(nèi)涵,以及越來(lái)越多的開發(fā)者缺乏計(jì)算機(jī)編程相關(guān)的基礎(chǔ)知識(shí)。對(duì)于這樣的開發(fā)者來(lái)說(shuō) J...

    iKcamp 評(píng)論0 收藏0
  • 深入學(xué)習(xí)js之——原型原型

    摘要:我們用一張圖表示構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系好了構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系我們已經(jīng)梳理清楚了,那我們?cè)趺幢硎緦?shí)例與實(shí)例原型,也就是或者和之間的關(guān)系呢。 開篇: 在Brendan Eich大神為JavaScript設(shè)計(jì)面向?qū)ο笙到y(tǒng)的時(shí)候,借鑒了Self 和Smalltalk這兩門基于原型的語(yǔ)言,之所以選擇基于原型的面向?qū)ο笙到y(tǒng),并不是因?yàn)闀r(shí)間匆忙,它設(shè)計(jì)起來(lái)相對(duì)簡(jiǎn)單,而是因?yàn)閺囊婚_始B...

    FingerLiu 評(píng)論0 收藏0
  • 深入學(xué)習(xí)js之——原型原型

    摘要:我們用一張圖表示構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系好了構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系我們已經(jīng)梳理清楚了,那我們?cè)趺幢硎緦?shí)例與實(shí)例原型,也就是或者和之間的關(guān)系呢。 開篇: 在Brendan Eich大神為JavaScript設(shè)計(jì)面向?qū)ο笙到y(tǒng)的時(shí)候,借鑒了Self 和Smalltalk這兩門基于原型的語(yǔ)言,之所以選擇基于原型的面向?qū)ο笙到y(tǒng),并不是因?yàn)闀r(shí)間匆忙,它設(shè)計(jì)起來(lái)相對(duì)簡(jiǎn)單,而是因?yàn)閺囊婚_始B...

    xialong 評(píng)論0 收藏0
  • 通過(guò)類型繼承深入理解原型繼承

    摘要:上圖中的在原型繼承稱作構(gòu)造器。構(gòu)造器就是一個(gè)普通的函數(shù),但是將操作符用到構(gòu)造器上時(shí),它會(huì)執(zhí)行一個(gè)叫的過(guò)程。從第條可以看到,構(gòu)造器生成的對(duì)象的屬性會(huì)指向構(gòu)造器的值,這就是我們構(gòu)造原型鏈的關(guān)鍵。 基于類的繼承是大多數(shù)人所熟悉的,也是比較容易理解的。當(dāng)我們形成類型繼承的思維定勢(shì)后,再次接觸原型繼承可能會(huì)覺得有些奇怪并難以理解。你更可能會(huì)吐槽,原型繼承根本就不能叫做繼承,一點(diǎn)都不面向?qū)ο蟆1救?..

    Alliot 評(píng)論0 收藏0
  • 通過(guò)類型繼承深入理解原型繼承

    摘要:上圖中的在原型繼承稱作構(gòu)造器。構(gòu)造器就是一個(gè)普通的函數(shù),但是將操作符用到構(gòu)造器上時(shí),它會(huì)執(zhí)行一個(gè)叫的過(guò)程。從第條可以看到,構(gòu)造器生成的對(duì)象的屬性會(huì)指向構(gòu)造器的值,這就是我們構(gòu)造原型鏈的關(guān)鍵。 基于類的繼承是大多數(shù)人所熟悉的,也是比較容易理解的。當(dāng)我們形成類型繼承的思維定勢(shì)后,再次接觸原型繼承可能會(huì)覺得有些奇怪并難以理解。你更可能會(huì)吐槽,原型繼承根本就不能叫做繼承,一點(diǎn)都不面向?qū)ο?。本?..

    Hegel_Gu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<