原型模式(Prototype Pattern)
原型模式,使我们可以灵活地动态创建拥有某些稳定接口的“易变”对象。原型模式中涉及到了深拷贝(deep copy)的概念,所谓深拷贝就是对使用了引用类型的类对象的完整拷贝,如果拷贝的类中没有用到引用类型,则可以使用object自带的MemberWiseClone()方法实现拷贝。
下面的例子使用了原型模式实现匹萨店的原料生成,结构图与实现代码中的对应关系如下
IngredientManager = Client
Dough(Sauce/Cheese/Clams) = Prototype
ThickCrustDough(PlumTomatoSauce/MozzarellaCheese/FrozenClams) = ConcretePrototype1
ThinCrustDough(MarinaraSauce/ReggianoCheese/FreshClams) = ConcretePrototype2
class App
{
static void Main()
{
//在纽约的一家匹萨店,一位客人订购了一份干酪匹萨
PizzaStore nyStore = new NYPizzaStore();
Pizza nyPizza = nyStore.CreatePizza(PizzaType.干酪匹萨);
Console.ReadLine();
}
}
#region 匹萨快餐店
public abstract class PizzaStore
{
public abstract Pizza CreatePizza(PizzaType type);
}
/// <summary>
/// 纽约匹萨店
/// </summary>
public class NYPizzaStore : PizzaStore
{
public override Pizza CreatePizza(PizzaType type)
{
Pizza pizza = null;
switch (type)
{
case PizzaType.干酪匹萨:
pizza = new CheesePizza(new ThinCrustDough(), new MarinaraSauce(), new ReggianoCheese(), new FreshClams());
pizza.Name = "纽约式干酪匹萨";
break;
case PizzaType.蛤蜊匹萨:
pizza = new ClamPizza(new ThinCrustDough(), new MarinaraSauce(), new ReggianoCheese(), new FreshClams());
pizza.Name = "纽约式蛤蜊匹萨";
break;
default:
break;
}
if (pizza != null) pizza.Produce();
return pizza;
}
}
/// <summary>
/// 芝加哥匹萨店
/// </summary>
public class ChicagoPizzaStore : PizzaStore
{
public override Pizza CreatePizza(PizzaType type)
{
Pizza pizza = null;
switch (type)
{
case PizzaType.干酪匹萨:
pizza = new CheesePizza(new ThickCrustDough(), new PlumTomatoSauce(), new MozzarellaCheese(), new FrozenClams());
pizza.Name = "芝加哥式干酪匹萨";
break;
case PizzaType.蛤蜊匹萨:
pizza = new ClamPizza(new ThickCrustDough(), new PlumTomatoSauce(), new MozzarellaCheese(), new FrozenClams());
pizza.Name = "芝加哥式蛤蜊匹萨";
break;
default:
break;
}
if (pizza != null) pizza.Produce();
return pizza;
}
}
#endregion
#region 匹萨
public enum PizzaType
{
干酪匹萨 = 1,
蛤蜊匹萨 = 2
}
public abstract class Pizza
{
protected PizzaIngredient ingredient;
protected abstract void Prepare();
protected virtual void Bake()
{
Console.WriteLine("350度烘烤25分钟");
}
protected virtual void Cut()
{
Console.WriteLine("将匹萨切成尖角型");
}
protected virtual void Box()
{
Console.WriteLine("将匹萨打包成商务餐装");
}
public virtual void Produce()
{
Prepare();
Bake();
Cut();
Box();
}
public string Name { get; set; }
}
public class CheesePizza : Pizza
{
Dough dough;
Sauce sauce;
Cheese cheese;
Clams clams;
public CheesePizza(Dough dough, Sauce sauce, Cheese cheese, Clams clams)
{
this.dough = dough;
this.sauce = sauce;
this.cheese = cheese;
this.clams = clams;
}
protected override void Prepare()
{
this.ingredient = IngredientManager.Construct(dough, sauce, cheese, clams);
Console.WriteLine("准备做一个 {0}", Name);
Console.WriteLine(" 准备{0}{1}份", ingredient.DoughIngredient[0].PizzaDough(), ingredient.DoughIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.SauceIngredient[0].PizzaSauce(), ingredient.SauceIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.CheeseIngredient[0].PizzaTopCheese(), ingredient.CheeseIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.ClamsIngredient[0].PizzaTopClams(), ingredient.ClamsIngredient.Count);
}
}
public class ClamPizza : Pizza
{
Dough dough;
Sauce sauce;
Cheese cheese;
Clams clams;
public ClamPizza(Dough dough, Sauce sauce, Cheese cheese, Clams clams)
{
this.dough = dough;
this.sauce = sauce;
this.cheese = cheese;
this.clams = clams;
}
protected override void Prepare()
{
this.ingredient = IngredientManager.Construct(dough, sauce, cheese, clams);
Console.WriteLine("准备做一个 {0}", Name);
Console.WriteLine(" 准备{0}{1}份", ingredient.DoughIngredient[0].PizzaDough(), ingredient.DoughIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.SauceIngredient[0].PizzaSauce(), ingredient.SauceIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.CheeseIngredient[0].PizzaTopCheese(), ingredient.CheeseIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.ClamsIngredient[0].PizzaTopClams(), ingredient.ClamsIngredient.Count);
}
}
#endregion
#region 匹萨原料
public class IngredientManager
{
public static PizzaIngredient Construct(Dough dough, Sauce sauce, Cheese cheese, Clams clams)
{
PizzaIngredient ingredient = new PizzaIngredient();
ingredient.DoughIngredient.Add(dough.Clone(true));
ingredient.DoughIngredient.Add(dough.Clone(true));
ingredient.DoughIngredient.Add(dough.Clone(true));
ingredient.SauceIngredient.Add(sauce.Clone(true));
ingredient.SauceIngredient.Add(sauce.Clone(true));
ingredient.CheeseIngredient.Add(cheese.Clone(true));
ingredient.ClamsIngredient.Add(clams.Clone(true));
return ingredient;
}
}
public class PizzaIngredient
{
private List<Dough> dough = new List<Dough>();
public List<Dough> DoughIngredient
{
get { return dough; }
set { dough = value; }
}
private List<Sauce> sauce = new List<Sauce>();
public List<Sauce> SauceIngredient
{
get { return sauce; }
set { sauce = value; }
}
private List<Cheese> cheese = new List<Cheese>();
public List<Cheese> CheeseIngredient
{
get { return cheese; }
set { cheese = value; }
}
private List<Clams> clams = new List<Clams>();
public List<Clams> ClamsIngredient
{
get { return clams; }
set { clams = value; }
}
}
#endregion
#region 匹萨使用的原料
public interface Dough
{
string PizzaDough();
Dough Clone(bool deep);
}
[Serializable]
public class ThickCrustDough : Dough
{
public string PizzaDough()
{
return "厚皮面团";
}
public Dough Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Dough;
}
else
{
return this.MemberwiseClone() as Dough;
}
}
}
[Serializable]
public class ThinCrustDough : Dough
{
public string PizzaDough()
{
return "薄皮面团";
}
public Dough Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Dough;
}
else
{
return this.MemberwiseClone() as Dough;
}
}
}
public interface Sauce
{
string PizzaSauce();
Sauce Clone(bool deep);
}
[Serializable]
public class PlumTomatoSauce : Sauce
{
public string PizzaSauce()
{
return "番茄沙司";
}
public Sauce Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Sauce;
}
else
{
return this.MemberwiseClone() as Sauce;
}
}
}
[Serializable]
public class MarinaraSauce : Sauce
{
public string PizzaSauce()
{
return "意式沙司";
}
public Sauce Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Sauce;
}
else
{
return this.MemberwiseClone() as Sauce;
}
}
}
public interface Cheese
{
string PizzaTopCheese();
Cheese Clone(bool deep);
}
[Serializable]
public class MozzarellaCheese : Cheese
{
public string PizzaTopCheese()
{
return "意式奶酪";
}
public Cheese Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Cheese;
}
else
{
return this.MemberwiseClone() as Cheese;
}
}
}
[Serializable]
public class ReggianoCheese : Cheese
{
public string PizzaTopCheese()
{
return "乳酪奶酪";
}
public Cheese Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Cheese;
}
else
{
return this.MemberwiseClone() as Cheese;
}
}
}
public interface Clams
{
string PizzaTopClams();
Clams Clone(bool deep);
}
[Serializable]
public class FrozenClams : Clams
{
public string PizzaTopClams()
{
return "冰冻蛤蜊";
}
public Clams Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Clams;
}
else
{
return this.MemberwiseClone() as Clams;
}
}
}
[Serializable]
public class FreshClams : Clams
{
public string PizzaTopClams()
{
return "生鲜蛤蜊";
}
public Clams Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Clams;
}
else
{
return this.MemberwiseClone() as Clams;
}
}
}
#endregion
public class Utility
{
public static object DeepCopy(object obj)
{
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Position = 0;
return formatter.Deserialize(stream);
}
}
{
static void Main()
{
//在纽约的一家匹萨店,一位客人订购了一份干酪匹萨
PizzaStore nyStore = new NYPizzaStore();
Pizza nyPizza = nyStore.CreatePizza(PizzaType.干酪匹萨);
Console.ReadLine();
}
}
#region 匹萨快餐店
public abstract class PizzaStore
{
public abstract Pizza CreatePizza(PizzaType type);
}
/// <summary>
/// 纽约匹萨店
/// </summary>
public class NYPizzaStore : PizzaStore
{
public override Pizza CreatePizza(PizzaType type)
{
Pizza pizza = null;
switch (type)
{
case PizzaType.干酪匹萨:
pizza = new CheesePizza(new ThinCrustDough(), new MarinaraSauce(), new ReggianoCheese(), new FreshClams());
pizza.Name = "纽约式干酪匹萨";
break;
case PizzaType.蛤蜊匹萨:
pizza = new ClamPizza(new ThinCrustDough(), new MarinaraSauce(), new ReggianoCheese(), new FreshClams());
pizza.Name = "纽约式蛤蜊匹萨";
break;
default:
break;
}
if (pizza != null) pizza.Produce();
return pizza;
}
}
/// <summary>
/// 芝加哥匹萨店
/// </summary>
public class ChicagoPizzaStore : PizzaStore
{
public override Pizza CreatePizza(PizzaType type)
{
Pizza pizza = null;
switch (type)
{
case PizzaType.干酪匹萨:
pizza = new CheesePizza(new ThickCrustDough(), new PlumTomatoSauce(), new MozzarellaCheese(), new FrozenClams());
pizza.Name = "芝加哥式干酪匹萨";
break;
case PizzaType.蛤蜊匹萨:
pizza = new ClamPizza(new ThickCrustDough(), new PlumTomatoSauce(), new MozzarellaCheese(), new FrozenClams());
pizza.Name = "芝加哥式蛤蜊匹萨";
break;
default:
break;
}
if (pizza != null) pizza.Produce();
return pizza;
}
}
#endregion
#region 匹萨
public enum PizzaType
{
干酪匹萨 = 1,
蛤蜊匹萨 = 2
}
public abstract class Pizza
{
protected PizzaIngredient ingredient;
protected abstract void Prepare();
protected virtual void Bake()
{
Console.WriteLine("350度烘烤25分钟");
}
protected virtual void Cut()
{
Console.WriteLine("将匹萨切成尖角型");
}
protected virtual void Box()
{
Console.WriteLine("将匹萨打包成商务餐装");
}
public virtual void Produce()
{
Prepare();
Bake();
Cut();
Box();
}
public string Name { get; set; }
}
public class CheesePizza : Pizza
{
Dough dough;
Sauce sauce;
Cheese cheese;
Clams clams;
public CheesePizza(Dough dough, Sauce sauce, Cheese cheese, Clams clams)
{
this.dough = dough;
this.sauce = sauce;
this.cheese = cheese;
this.clams = clams;
}
protected override void Prepare()
{
this.ingredient = IngredientManager.Construct(dough, sauce, cheese, clams);
Console.WriteLine("准备做一个 {0}", Name);
Console.WriteLine(" 准备{0}{1}份", ingredient.DoughIngredient[0].PizzaDough(), ingredient.DoughIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.SauceIngredient[0].PizzaSauce(), ingredient.SauceIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.CheeseIngredient[0].PizzaTopCheese(), ingredient.CheeseIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.ClamsIngredient[0].PizzaTopClams(), ingredient.ClamsIngredient.Count);
}
}
public class ClamPizza : Pizza
{
Dough dough;
Sauce sauce;
Cheese cheese;
Clams clams;
public ClamPizza(Dough dough, Sauce sauce, Cheese cheese, Clams clams)
{
this.dough = dough;
this.sauce = sauce;
this.cheese = cheese;
this.clams = clams;
}
protected override void Prepare()
{
this.ingredient = IngredientManager.Construct(dough, sauce, cheese, clams);
Console.WriteLine("准备做一个 {0}", Name);
Console.WriteLine(" 准备{0}{1}份", ingredient.DoughIngredient[0].PizzaDough(), ingredient.DoughIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.SauceIngredient[0].PizzaSauce(), ingredient.SauceIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.CheeseIngredient[0].PizzaTopCheese(), ingredient.CheeseIngredient.Count);
Console.WriteLine(" 准备{0}{1}份", ingredient.ClamsIngredient[0].PizzaTopClams(), ingredient.ClamsIngredient.Count);
}
}
#endregion
#region 匹萨原料
public class IngredientManager
{
public static PizzaIngredient Construct(Dough dough, Sauce sauce, Cheese cheese, Clams clams)
{
PizzaIngredient ingredient = new PizzaIngredient();
ingredient.DoughIngredient.Add(dough.Clone(true));
ingredient.DoughIngredient.Add(dough.Clone(true));
ingredient.DoughIngredient.Add(dough.Clone(true));
ingredient.SauceIngredient.Add(sauce.Clone(true));
ingredient.SauceIngredient.Add(sauce.Clone(true));
ingredient.CheeseIngredient.Add(cheese.Clone(true));
ingredient.ClamsIngredient.Add(clams.Clone(true));
return ingredient;
}
}
public class PizzaIngredient
{
private List<Dough> dough = new List<Dough>();
public List<Dough> DoughIngredient
{
get { return dough; }
set { dough = value; }
}
private List<Sauce> sauce = new List<Sauce>();
public List<Sauce> SauceIngredient
{
get { return sauce; }
set { sauce = value; }
}
private List<Cheese> cheese = new List<Cheese>();
public List<Cheese> CheeseIngredient
{
get { return cheese; }
set { cheese = value; }
}
private List<Clams> clams = new List<Clams>();
public List<Clams> ClamsIngredient
{
get { return clams; }
set { clams = value; }
}
}
#endregion
#region 匹萨使用的原料
public interface Dough
{
string PizzaDough();
Dough Clone(bool deep);
}
[Serializable]
public class ThickCrustDough : Dough
{
public string PizzaDough()
{
return "厚皮面团";
}
public Dough Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Dough;
}
else
{
return this.MemberwiseClone() as Dough;
}
}
}
[Serializable]
public class ThinCrustDough : Dough
{
public string PizzaDough()
{
return "薄皮面团";
}
public Dough Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Dough;
}
else
{
return this.MemberwiseClone() as Dough;
}
}
}
public interface Sauce
{
string PizzaSauce();
Sauce Clone(bool deep);
}
[Serializable]
public class PlumTomatoSauce : Sauce
{
public string PizzaSauce()
{
return "番茄沙司";
}
public Sauce Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Sauce;
}
else
{
return this.MemberwiseClone() as Sauce;
}
}
}
[Serializable]
public class MarinaraSauce : Sauce
{
public string PizzaSauce()
{
return "意式沙司";
}
public Sauce Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Sauce;
}
else
{
return this.MemberwiseClone() as Sauce;
}
}
}
public interface Cheese
{
string PizzaTopCheese();
Cheese Clone(bool deep);
}
[Serializable]
public class MozzarellaCheese : Cheese
{
public string PizzaTopCheese()
{
return "意式奶酪";
}
public Cheese Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Cheese;
}
else
{
return this.MemberwiseClone() as Cheese;
}
}
}
[Serializable]
public class ReggianoCheese : Cheese
{
public string PizzaTopCheese()
{
return "乳酪奶酪";
}
public Cheese Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Cheese;
}
else
{
return this.MemberwiseClone() as Cheese;
}
}
}
public interface Clams
{
string PizzaTopClams();
Clams Clone(bool deep);
}
[Serializable]
public class FrozenClams : Clams
{
public string PizzaTopClams()
{
return "冰冻蛤蜊";
}
public Clams Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Clams;
}
else
{
return this.MemberwiseClone() as Clams;
}
}
}
[Serializable]
public class FreshClams : Clams
{
public string PizzaTopClams()
{
return "生鲜蛤蜊";
}
public Clams Clone(bool deep)
{
if (deep)
{
return Utility.DeepCopy(this) as Clams;
}
else
{
return this.MemberwiseClone() as Clams;
}
}
}
#endregion
public class Utility
{
public static object DeepCopy(object obj)
{
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Position = 0;
return formatter.Deserialize(stream);
}
}