設計模式筆記(6)---原型模式(創建型)

 

Gof定義

使用原型實例指定創建對象的種類,然後通過拷貝這些原型來創建新的對象。

動機

在軟件系統中,經常面臨着“某些結構複雜的對象”的創建工作,但由於需求的變化,這些對象將成面臨着劇烈的變化,但他們擁有比較穩定一致的接口。

假設在一些打鬥遊戲場景中,有這樣一些角色,普通(NormalActor),可以飛的(FlyActor),可以潛水的(WaterActor)

public abstract class NormalActor { }
public abstract class FlyActor { }
public abstract class WaterActor { }

上面的三個類都是抽象類,自然會有具體的類來繼承這些抽象類

public class NormalActorA : NormalActor { }
public class FlyActorA : FlyActor { }
public class WaterActorA : WaterActor { }

在遊戲運行中就會去使用這些角色的具體類,如下

public class GameSystem
{
    public void Run()
    {
        NormalActorA normalActor1 = new NormalActorA();
        NormalActorA normalActor2 = new NormalActorA();
        NormalActorA normalActor3 = new NormalActorA();
        NormalActorA normalActor4 = new NormalActorA();
        NormalActorA normalActor5 = new NormalActorA();

        FlyActorA flyActor1 = new FlyActorA();
        FlyActorA flyActor2 = new FlyActorA();

        WaterActorA waterActor1 = new WaterActorA();
        WaterActorA waterActor2 = new WaterActorA();
    }
}
 

在GameSystem類中,我們直接使用具體類(NormalActorA)等來創建對象,GameSystem就對這些具體類產生了依賴,在DIP(依賴倒置原則)中講到抽象不應依賴具體實現,具體實現應依賴於抽象,所以GameSystem中的代碼要進行如下改動

public class GameSystem
{
    public void Run(NormalActor normalActor, FlyActor flyActor,
        WaterActor waterActor)
    {
        NormalActor normalActor1 = normalActor.Clone();
        NormalActor normalActor2 = normalActor.Clone();
        NormalActor normalActor3 = normalActor.Clone();
        NormalActor normalActor4 = normalActor.Clone();
        NormalActor normalActor5 = normalActor.Clone();

        FlyActor flyActor1 = flyActor.Clone();
        FlyActor flyActor2 = flyActor.Clone();

        WaterActor waterActor1 = waterActor.Clone();
        WaterActor waterActor2 = waterActor.Clone();
    }
}
 

經過修改在GameSystem類中已經看不到具體類的影子了,創建對象是通過傳入的抽象類類型的參數的Clone方法來創建,關於Clone方法在後面講到,這樣GameSystem就只依賴於抽象了。

下面來說說Clone方法了,首先在抽象類中定義Clone方法

public abstract class NormalActor 
{
    public abstract NormalActor Clone();
}
public abstract class FlyActor 
{
    public abstract FlyActor Clone();
}
public abstract class WaterActor 
{
    public abstract WaterActor Clone();
}

然後在具體類中來實現Clone,使用MemberwiseClone方法來實現克隆,使用MemberwiseClone方法需要注意的是他只能實現值類型的拷貝,如果被拷貝對象中包含有引用類型,只會拷貝引用地址。

public class NormalActorA : NormalActor 
{
    public override NormalActor Clone()
    {
        return (NormalActor)this.MemberwiseClone();
    }
}
public class FlyActorA : FlyActor 
{
    public override FlyActor Clone()
    {
        return (FlyActor)this.MemberwiseClone();
    }
}
public class WaterActorA : WaterActor 
{
    public override WaterActor Clone()
    {
        return (WaterActor)this.MemberwiseClone();
    }
}

至此,原型模式的代碼結構基本完成,下面看看在程序中試怎麼來調用的

public class App
{
    public static void Main()
    {
        GameSystem gameSystem = new GameSystem();
        gameSystem.Run(new NormalActorA(), new FlyActorA(), new WaterActorA());
    }
}

 

原型模式(Prototype)的幾個要點

Prototype模式同樣用於隔離類對象的使用者和具體類型(易變類型)之間的耦合關係,同樣要求這些易變類型具有穩定的接口。

Prototype模式對於“如何創建易變類的實體對象”採用原型克隆的方法來做,他使得我們可以非常靈活的動態創建“擁有某些穩定接口”的新對象--所需工作僅僅是註冊一個新類的對象(原型),然後在任何需要的地方不斷地Clone。

Prototype模式中的克隆方法可以利用Net中的Object類的MemberwiseClone方法或是序列化來實現深拷貝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章