欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
博客園 - 探索設計模式(六):原型模式(Prototype Pattern)

原型模式(Prototype Pattern

——探索設計模式系列之六

Terrylee,20061

概述

在軟件系統中,有時(shí)候面臨的產(chǎn)品類(lèi)是動(dòng)態(tài)變化的,而且這個(gè)產(chǎn)品類(lèi)具有一定的等級結構。這時(shí)如果用工廠(chǎng)模式,則與產(chǎn)品類(lèi)等級結構平行的工廠(chǎng)方法類(lèi)也要隨著(zhù)這種變化而變化,顯然不大合適。那么如何封裝這種動(dòng)態(tài)的變化?從而使依賴(lài)于這些易變對象的客戶(hù)程序不隨著(zhù)產(chǎn)品類(lèi)變化?

意圖

用原型實(shí)例指定創(chuàng )建對象的種類(lèi),并且通過(guò)拷貝這些原型創(chuàng )建新的對象。

結構圖

Prototype模式結構圖

生活中的例子

Prototype模式使用原型實(shí)例指定創(chuàng )建對象的種類(lèi)。新產(chǎn)品的原型通常是先于全部產(chǎn)品建立的,這樣的原型是被動(dòng)的,并不參與復制它自己。一個(gè)細胞的有絲分裂,產(chǎn)生兩個(gè)同樣的細胞,是一個(gè)扮演主動(dòng)角色復制自己原型的例子,這演示了原型模式。一個(gè)細胞分裂,產(chǎn)生兩個(gè)同樣基因型的細胞。換句話(huà)說(shuō),細胞克隆了自己。

使用細胞分裂例子的Prototype模式對象圖

原型模式解說(shuō)

我們考慮這樣一個(gè)場(chǎng)景,假定我們要開(kāi)發(fā)一個(gè)調色板,用戶(hù)單擊調色板上任一個(gè)方塊,將會(huì )返回一個(gè)對應的顏色的實(shí)例,下面我們看看如何通過(guò)原型模式來(lái)達到系統動(dòng)態(tài)加載具體產(chǎn)品的目的。

很自然,我們利用OO的思想,把每一種顏色作為一個(gè)對象,并為他們抽象出一個(gè)公用的父類(lèi),如下圖:

實(shí)現代碼:

public abstract class Color

{

        public abstract void Display();

}

public class RedColor:Color

{

    public override void Display()

    {

        Console.WriteLine("Red‘s RGB Values are:255,0,0");

    }

}

public class GreenColor:Color

{

    public override void Display()

    {

        Console.WriteLine("Green‘s RGB Values are:0,255,0");

    }

}

客戶(hù)程序需要某一種顏色的時(shí)候,只需要創(chuàng )建對應的具體類(lèi)的實(shí)例就可以了。但是這樣我們并沒(méi)有達到封裝變化點(diǎn)的目的,也許你會(huì )說(shuō),可以使用工廠(chǎng)方法模式,為每一個(gè)具體子類(lèi)定義一個(gè)與其等級平行的工廠(chǎng)類(lèi),那么好,看一下實(shí)現:

實(shí)現代碼:

public abstract class ColorFactory

{

    public abstract Color Create();

}

public class RedFactory:ColorFactory

{

    public override Color Create()

    {

        return new RedColor();

    }

}

public class GreenFactory:ColorFactory

{

    public override Color Create()

    {

        return new GreenColor();

    }

}

實(shí)現了這一步之后,可以看到,客戶(hù)程序只要調用工廠(chǎng)方法就可以了。似乎我們用工廠(chǎng)方法模式來(lái)解決是沒(méi)有問(wèn)題的。但是,我們考慮的僅僅是封裝了new變化,而沒(méi)有考慮顏色的數量是不斷變化的,甚至可能是在程序運行的過(guò)程中動(dòng)態(tài)增加和減少的,那么用這種方法實(shí)現,隨著(zhù)顏色數量的不斷增加,子類(lèi)的數量會(huì )迅速膨大,導致子類(lèi)過(guò)多,顯然用工廠(chǎng)方法模式有些不大合適。

進(jìn)一步思考,這些Color子類(lèi)僅僅在初始化的顏色對象類(lèi)別上有所不同。添加一個(gè)ColorTool這樣的類(lèi),來(lái)參數化的它的實(shí)例,而這些實(shí)例是由Color支持和創(chuàng )建的。我們讓ColorTool通過(guò)克隆或者拷貝一個(gè)Color子類(lèi)的實(shí)例來(lái)創(chuàng )建新的Color,這個(gè)實(shí)例就是一個(gè)原型。如下圖所示:

實(shí)現代碼:

abstract class ColorPrototype

{

    public abstract ColorPrototype Clone();

}

class ConcteteColorPrototype : ColorPrototype

{

    private int _red, _green, _blue;

    public ConcteteColorPrototype(int red, int green, int blue)

    {

        this._red = red;

        this._green = green;

        this._blue = blue;

    }

     public override ColorPrototype Clone()

    {

        //實(shí)現淺拷貝

        return (ColorPrototype) this.MemberwiseClone();

    }

    public void Display(string _colorname)

    {

        Console.WriteLine("{0}‘s RGB Values are: {1},{2},{3}",

            _colorname,_red, _green, _blue );

    }

}

class ColorManager

{ 

    Hashtable colors = new Hashtable();

    public ColorPrototype this[string name]

    {

        get

        {

            return (ColorPrototype)colors[name];

        }

        set

        {

            colors.Add(name,value);

        }

    }

}

現在我們分析一下,這樣帶來(lái)了什么好處?首先從子類(lèi)的數目上大大減少了,不需要再為每一種具體的顏色產(chǎn)品而定一個(gè)類(lèi)和與它等級平行的工廠(chǎng)方法類(lèi),而ColorTool則扮演了原型管理器的角色。再看一下為客戶(hù)程序的實(shí)現:

class App

{

    public static void Main(string[] args)

    {

        ColorManager colormanager = new ColorManager();

        //初始化顏色

        colormanager["red"] = new ConcteteColorPrototype(255, 0, 0);

        colormanager["green"] = new ConcteteColorPrototype(0, 255, 0);

        colormanager["blue"] = new ConcteteColorPrototype(0, 0, 255);

        colormanager["angry"] = new ConcteteColorPrototype(255, 54, 0);

        colormanager["peace"] = new ConcteteColorPrototype(128, 211, 128);

        colormanager["flame"] = new ConcteteColorPrototype(211, 34, 20);

        //使用顏色

        string colorName = "red";

        ConcteteColorPrototype c1 = (ConcteteColorPrototype)colormanager[colorName].Clone();

        c1.Display(colorName);

        colorName = "peace";

        ConcteteColorPrototype c2 = (ConcteteColorPrototype)colormanager[colorName].Clone();

        c2.Display(colorName);

        colorName = "flame";

        ConcteteColorPrototype c3 = (ConcteteColorPrototype)colormanager[colorName].Clone();

        c3.Display(colorName);

        Console.ReadLine();

    }

}

可以看到,客戶(hù)程序通過(guò)注冊原型實(shí)例就可以將一個(gè)具體產(chǎn)品類(lèi)并入到系統中,在運行時(shí)刻,可以動(dòng)態(tài)的建立和刪除原型。最后還要注意一點(diǎn),在上面的例子中,用的是淺表復制。如果想做深復制,需要通過(guò)序列化的方式來(lái)實(shí)現。經(jīng)過(guò)了上面的分析之后,我們再來(lái)思考下面的問(wèn)題:

1.為什么需要Prototype模式?

引入原型模式的本質(zhì)在于利用已有的一個(gè)原型對象,快速的生成和原型對象一樣的實(shí)例。你有一個(gè)A的實(shí)例a:A a = new A();現在你想生成和car1一樣的一個(gè)實(shí)例b,按照原型模式,應該是這樣:A b = a.Clone();而不是重新再new一個(gè)A對象。通過(guò)上面這句話(huà)就可以得到一個(gè)和a一樣的實(shí)例,確切的說(shuō),應該是它們的數據成員是一樣的。Prototype模式同樣是返回了一個(gè)A對象而沒(méi)有使用new操作。

2.引入Prototype模式帶來(lái)了什么好處?

可以看到,引入Prototype模式后我們不再需要一個(gè)與具體產(chǎn)品等級結構平行的工廠(chǎng)方法類(lèi),減少了類(lèi)的構造,同時(shí)客戶(hù)程序可以在運行時(shí)刻建立和刪除原型。

3Prototype模式滿(mǎn)足了哪些面向對象的設計原則?

依賴(lài)倒置原則:上面的例子,原型管理器(ColorManager)僅僅依賴(lài)于抽象部分(ColorPrototype),而具體實(shí)現細節(ConcteteColorPrototype)則依賴(lài)與抽象部分(ColorPrototype),所以Prototype很好的滿(mǎn)足了依賴(lài)倒置原則。

通過(guò)序列化實(shí)現深拷貝

要實(shí)現深拷貝,可以通過(guò)序列化的方式。抽象類(lèi)及具體類(lèi)都必須標注為可序列化的[Serializable],上面的例子加上深拷貝之后的完整程序如下:

using System;

using System.Collections;

using System.IO;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

[Serializable]

abstract class ColorPrototype

{

    public abstract ColorPrototype Clone(bool Deep);

}

[Serializable]

class ConcteteColorPrototype : ColorPrototype

{

    private int _red, _green, _blue;

    public ConcteteColorPrototype(int red, int green, int blue)

    {

        this._red = red;

        this._green = green;

        this._blue = blue;

    }

     public override ColorPrototype Clone(bool Deep)

    {

        if(Deep)

            return CreateDeepCopy();

        else

            return (ColorPrototype) this.MemberwiseClone();

    }

    //實(shí)現深拷貝

    public ColorPrototype CreateDeepCopy()

    {

        ColorPrototype colorPrototype;

        MemoryStream memoryStream = new MemoryStream();

        BinaryFormatter formatter = new BinaryFormatter();

        formatter.Serialize(memoryStream, this);

        memoryStream.Position = 0;

        colorPrototype = (ColorPrototype)formatter.Deserialize(memoryStream);

        return colorPrototype;

    }

    public ConcteteColorPrototype Create(int red,int green,int blue)

    {

        return new ConcteteColorPrototype(red,green,blue); 

    }

    public void Display(string _colorname)

    {

        Console.WriteLine("{0}‘s RGB Values are: {1},{2},{3}",

            _colorname,_red, _green, _blue );

    }

}

class ColorManager

{ 

    Hashtable colors = new Hashtable();

     public ColorPrototype this[string name]

    {

        get

        {

            return (ColorPrototype)colors[name];

        }

        set

        {

            colors.Add(name,value);

        }

    }

}

class App

{

    public static void Main(string[] args)

    {

        ColorManager colormanager = new ColorManager();

        //初始化顏色

        colormanager["red"] = new ConcteteColorPrototype(255, 0, 0);

        colormanager["green"] = new ConcteteColorPrototype(0, 255, 0);

        colormanager["blue"] = new ConcteteColorPrototype(0, 0, 255);

        colormanager["angry"] = new ConcteteColorPrototype(255, 54, 0);

        colormanager["peace"] = new ConcteteColorPrototype(128, 211, 128);

        colormanager["flame"] = new ConcteteColorPrototype(211, 34, 20);

        //使用顏色

        string colorName = "red";

        ConcteteColorPrototype c1 = (ConcteteColorPrototype)colormanager[colorName].Clone(false);

        c1.Display(colorName);

        colorName = "peace";

        ConcteteColorPrototype c2 = (ConcteteColorPrototype)colormanager[colorName].Clone(true);

        c2.Display(colorName);

        colorName = "flame";

        ConcteteColorPrototype c3 = (ConcteteColorPrototype)colormanager[colorName].Clone(true);

        c3.Display(colorName);

        Console.ReadLine();

    }

}

實(shí)現要點(diǎn)

1.使用原型管理器,體現在一個(gè)系統中原型數目不固定時(shí),可以動(dòng)態(tài)的創(chuàng )建和銷(xiāo)毀,如上面的舉的調色板的例子。

2.實(shí)現克隆操作,在.NET中可以使用Object類(lèi)的MemberwiseClone()方法來(lái)實(shí)現對象的淺表拷貝或通過(guò)序列化的方式來(lái)實(shí)現深拷貝。

3Prototype模式同樣用于隔離類(lèi)對象的使用者和具體類(lèi)型(易變類(lèi))之間的耦合關(guān)系,它同樣要求這些“易變類(lèi)”擁有穩定的接口。

效果

1.它對客戶(hù)隱藏了具體的產(chǎn)品類(lèi),因此減少了客戶(hù)知道的名字的數目。

2Prototype模式允許客戶(hù)只通過(guò)注冊原型實(shí)例就可以將一個(gè)具體產(chǎn)品類(lèi)并入到系統中,客戶(hù)可以在運行時(shí)刻建立和刪除原型。

3.減少了子類(lèi)構造,Prototype模式是克隆一個(gè)原型而不是請求工廠(chǎng)方法創(chuàng )建一個(gè),所以它不需要一個(gè)與具體產(chǎn)品類(lèi)平行的Creater類(lèi)層次。

4Portotype模式具有給一個(gè)應用軟件動(dòng)態(tài)加載新功能的能力。由于Prototype的獨立性較高,可以很容易動(dòng)態(tài)加載新功能而不影響老系統。

5產(chǎn)品類(lèi)不需要非得有任何事先確定的等級結構,因為Prototype模式適用于任何的等級結構

6Prototype模式的最主要缺點(diǎn)就是每一個(gè)類(lèi)必須配備一個(gè)克隆方法。而且這個(gè)克隆方法需要對類(lèi)的功能進(jìn)行通盤(pán)考慮,這對全新的類(lèi)來(lái)說(shuō)不是很難,但對已有的類(lèi)進(jìn)行改造時(shí),不一定是件容易的事。

適用性

在下列情況下,應當使用Prototype模式:

1.當一個(gè)系統應該獨立于它的產(chǎn)品創(chuàng )建,構成和表示時(shí);

2.當要實(shí)例化的類(lèi)是在運行時(shí)刻指定時(shí),例如,通過(guò)動(dòng)態(tài)裝載;

3.為了避免創(chuàng )建一個(gè)與產(chǎn)品類(lèi)層次平行的工廠(chǎng)類(lèi)層次時(shí);

4.當一個(gè)類(lèi)的實(shí)例只能有幾個(gè)不同狀態(tài)組合中的一種時(shí)。建立相應數目的原型并克隆它們可能比每次用合適的狀態(tài)手工實(shí)例化該類(lèi)更方便一些。

總結

Prototype模式同工廠(chǎng)模式,同樣對客戶(hù)隱藏了對象的創(chuàng )建工作,但是,與通過(guò)對一個(gè)類(lèi)進(jìn)行實(shí)例化來(lái)構造新對象不同的是,原型模式是通過(guò)拷貝一個(gè)現有對象生成新對象的,達到了“隔離類(lèi)對象的使用者和具體類(lèi)型(易變類(lèi))之間的耦合關(guān)系”的目的。

參考文獻

《設計模式》(中文版)

DesignPatternsExplained

Java與模式》(閻宏 著(zhù))

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
原型模式(Prototype Pattern)
C#設計模式系列:原型模式(Prototype)
設計模式-原型模式
設計模式之Prototype(原型)
設計模式之八(原型模式)
原型模式(Prototype)解析例子
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久