Prototype模式

簡介

用于創(chuàng)建重復(fù)的對象,同時又能保證性能霜定。這種類型的設(shè)計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式廊鸥。這種模式是實現(xiàn)了一個原型接口望浩,該接口用于創(chuàng)建當(dāng)前對象的克隆。當(dāng)直接創(chuàng)建對象的代價比較大時惰说,則采用這種模式磨德。

什么情況下使用原型設(shè)計模式呢?

一個對象需要在一個高代價的數(shù)據(jù)庫操作之后被創(chuàng)建助被。我們可以緩存該對象剖张,在下一個請求時返回它的克隆切诀,在需要的時候更新數(shù)據(jù)庫揩环,以此來減少數(shù)據(jù)庫調(diào)用。

實現(xiàn)方式

  • c++
    c++中可以通過實現(xiàn)拷貝構(gòu)造函數(shù)的方法實現(xiàn)幅虑,要注意深拷貝和淺拷貝的問題丰滑。
  • java
    • 實現(xiàn)Cloneable接口,并覆寫clone方法;
    • 使用對象流。使用對象流褒墨,所有的自定義類型需要實現(xiàn)Serializable接口炫刷。
prototype.png

抽象原型

class Prototype {
public:
    virtual Prototype * clone() = 0;
};

具體原型

class ContretePrototype :public Prototype {
private:
    char *name;
    int id;
public:
    ContretePrototype(const char *name, int id) {
        this->name = NULL;
        if (name != NULL) {
            //this->name = (char *)malloc(sizeof(char)*(strlen(name) + 1));
            this->name = new char[sizeof(char)*(strlen(name) + 1)];
            strcpy(this->name, name);
        }
        this->id = id;
    }
    ContretePrototype(const ContretePrototype& prototype) {
        this->name = NULL;
        if (prototype.getName() != NULL) {
            this->name = (char *)malloc(sizeof(char)*(strlen(prototype.getName()) + 1));
            strcpy(this->name, prototype.getName());
        }
        this->id = prototype.getId();
    }

    Prototype * clone() {
        ContretePrototype *prototype = new ContretePrototype(*this);
        return prototype;
    }
    ~ContretePrototype() {
        if (this->name != NULL) {
            //free (this->name);
            delete[]this->name;
        }
    }

    int getId()const {
        return this->id;
    }

    char * getName()const {
        return this->name;
    }
};

測試

int main()
{
    ContretePrototype p("abc", 1);
    cout << p.getName() << "  " << p.getId() << endl;
    ContretePrototype *p1 =dynamic_cast<ContretePrototype *>( p.clone());
    cout << p1->getName() << "  " << p1->getId() << endl;
    delete p1;
    return 0;
}
prototype_res.png

Java版

public class A  implements Cloneable,Serializable {
    private int x;
    private int y;

    public A(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    protected Object clone()   {
        Object o=null;
        try {
            o=(A)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    @Override
    public String toString() {
        return "A{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
}
public class Prototype implements Cloneable, Serializable {
    private List<A> list;
    private A a;
    private int id;
    private String name;

    @Override
    protected Object clone() {
        Prototype o = null;
        try {
            o = (Prototype) super.clone();
            o.setA((A) o.getA().clone());
            List<A> temp = new ArrayList<A>(o.getList().size());
            for (A a : o.getList()) {
                temp.add((A) a.clone());
            }
            o.setList(temp);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }

    public Object deepClone() throws IOException, ClassNotFoundException {
        //將對象寫到流里
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        ObjectOutputStream oo = new ObjectOutputStream(bo);
        oo.writeObject(this);
        //從流里讀出來
        ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
        ObjectInputStream oi = new ObjectInputStream(bi);
        return (oi.readObject());
    }

    public List<A> getList() {
        return list;
    }

    public void setList(List<A> list) {
        this.list = list;
    }

    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Prototype{" +
                "list=" + list +
                ", a=" + a +
                ", id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //構(gòu)造對象
        Prototype prototype = new Prototype();
        List<A> list = new ArrayList<A>();
        A a1 = new A(1, 2);
        A a2 = new A(10, 20);
        list.add(a1);
        list.add(a2);
        prototype.setList(list);
        A a3 = new A(100, 200);
        prototype.setA(a3);
        prototype.setId(1000);
        prototype.setName("prototype name");
        //打印對象內(nèi)容
        log(prototype.toString());
        //使用clone克隆
        Prototype p1 = (Prototype) prototype.clone();
        //查看克隆后的結(jié)果
        log(p1.toString());
        //使用對象流序列化
        Prototype p2 = (Prototype) p1.deepClone();
        p1.getA().setX(300);
        p1.getList().get(0).setX(3000);
        log(prototype.toString());
        log(p2.toString());
    }


    public static void log(String content) {
        System.out.println(content);
    }
}

結(jié)果

Prototype{list=[A{x=1, y=2}, A{x=10, y=20}], a=A{x=100, y=200}, id=1000, name='prototype name'}
Prototype{list=[A{x=1, y=2}, A{x=10, y=20}], a=A{x=100, y=200}, id=1000, name='prototype name'}
Prototype{list=[A{x=1, y=2}, A{x=10, y=20}], a=A{x=100, y=200}, id=1000, name='prototype name'}
Prototype{list=[A{x=1, y=2}, A{x=10, y=20}], a=A{x=100, y=200}, id=1000, name='prototype name'}

Process finished with exit code 0
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市郁妈,隨后出現(xiàn)的幾起案子浑玛,更是在濱河造成了極大的恐慌,老刑警劉巖噩咪,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件顾彰,死亡現(xiàn)場離奇詭異,居然都是意外死亡胃碾,警方通過查閱死者的電腦和手機涨享,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仆百,“玉大人厕隧,你說我怎么就攤上這事《碇埽” “怎么了吁讨?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長峦朗。 經(jīng)常有香客問我挡爵,道長,這世上最難降的妖魔是什么甚垦? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任茶鹃,我火速辦了婚禮,結(jié)果婚禮上艰亮,老公的妹妹穿的比我還像新娘闭翩。我一直安慰自己,他們只是感情好迄埃,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布疗韵。 她就那樣靜靜地躺著,像睡著了一般侄非。 火紅的嫁衣襯著肌膚如雪蕉汪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天逞怨,我揣著相機與錄音者疤,去河邊找鬼。 笑死叠赦,一個胖子當(dāng)著我的面吹牛驹马,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼糯累,長吁一口氣:“原來是場噩夢啊……” “哼算利!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起泳姐,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤效拭,失蹤者是張志新(化名)和其女友劉穎穆趴,沒想到半個月后锈麸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體邮绿,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡拄氯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年卖鲤,在試婚紗的時候發(fā)現(xiàn)自己被綠了甜熔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片器腋。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡伏钠,死狀恐怖盗痒,靈堂內(nèi)的尸體忽然破棺而出蚂蕴,到底是詐尸還是另有隱情,我是刑警寧澤俯邓,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布骡楼,位于F島的核電站,受9級特大地震影響稽鞭,放射性物質(zhì)發(fā)生泄漏鸟整。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一朦蕴、第九天 我趴在偏房一處隱蔽的房頂上張望篮条。 院中可真熱鬧,春花似錦吩抓、人聲如沸涉茧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伴栓。三九已至,卻和暖如春雨饺,著一層夾襖步出監(jiān)牢的瞬間钳垮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工额港, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留饺窿,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓锹安,卻偏偏與公主長得像短荐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子叹哭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容