Factory Method: 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
现在根据依赖倒转原则,将工厂类抽象出一个接口,这个接口只有1个方法,就是创建抽象产品的工厂方法。所有要生产具体类的工厂,就去实现这样的接口。
举例来说:阿三想买鞋子,以前是直接去鞋子工厂就行,工厂根据需求,提供不同品牌的鞋子。现在工厂要做的事情太多了,阿三想买新品牌,工厂就得增加新的产品线,生产新品牌的鞋子。
现在不同了,为了缓解工厂压力,和增加工厂的灵活性,工厂提供原材料,分发给各品牌工厂,如A品牌工厂,B品牌工厂。阿三想买什么牌子的鞋子,就去对应品牌工厂即可。

最大的优点在于工厂类包含了必要的逻辑判断,根据用户端的选择条件,动态地实例化相关的类,对于客户端来说,去除了具体产品的依赖。
如果要添加功能,就要修改原来的类,违反了开放-封闭原则,于是就得用工厂模式。

客户端需要决定实例化哪一个工厂来实现,选择判断还是存在的,但是把简单工厂的内部逻辑判断移到了客户端代码来进行。
想要加功能的,本来是想改工厂类的,现在是修改客户端。

Prototype: 用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

比如大头想找工作,因此他要制作简历。对于不同的岗位,他可能需要制作多份简历。如果单纯地建立一个简历类,那么他需要实例化多个对象,而且很多个人信息需要重复设置。这就很不人性化了。
原型模式就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
#region 原型模式
// 原型类
abstract class Prototype
{
private string id;
public Prototype(string id)
{
this.id = id;
}
public String Id
{
get { return id; }
}
// 抽象类关键就是有这样一个Clone方法
public abstract Prototype Clone();
}
// 具体原型类
class ConcretePrototype1 : Prototype
{
public ConcretePrototype1(string id): base(id)
{
}
public override Prototype Clone()
{
// 创建当前对象的浅表副本。方法就是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。
// 如果字段是值类型的,则对该字段执行逐位复制。
// 如果字段是引用类型的,则复制引用,但是不复制引用的对象;原始对象及其副本引用同一对象。
return (Prototype)this.MemberwiseClone();
}
}
// 客户端代码
static void Main(string[] args)
{
ConcretePrototype1 p1 = new ConcretePrototype1("I");
ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();
Console.WriteLine("Cloned: {0}", c1.Id);
Console.Read();
}
#endregion
结果:
ICloneable接口.NET在System命名空间中提供了ICloneable接口,其中就是唯一的一个方法Clone(),只需要实现这个接口就可以完成原型模式了,不需要实现原型抽象类Prototype
举个例子: 老师布置了一套试卷,阿三和大头都要完成,于是他们都将试卷抄了一遍,并写下了答案。这么做的话,两人都抄了一遍试卷,做了很多重复操作。
所以老师一般的做法是,将试卷做成模板,复印2份,发给阿三和大头,这样他们只要把答案写上去就可以了,不用重复抄试卷即可。这就是模板模式。
模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

#region 模板方法模式
abstract class AbstractClass
{
//一些抽象行为,放到子类去实现
public abstract void PrimitiveOperation1();
public abstract void PrimitiveOperation2();
// 模板方法,给出了逻辑的骨架
// 而逻辑的组成是一些相应的抽象操作,
// 它们都推迟到子类实现
public void TemplateMethod()
{
PrimitiveOperation1();
PrimitiveOperation2();
Console.WriteLine("");
}
}
// ConcreteClass 实现父类所定义的一个或多个实现方法,
// 给出父类抽象方法的具体不同实现,
// 从而使得顶级逻辑的实现各不相同
class ConcreteClassA : AbstractClass
{
public override void PrimitiveOperation1()
{
Console.WriteLine("具体类A方法1实现");
}
public override void PrimitiveOperation2()
{
Console.WriteLine("具体类A方法2实现");
}
}
// 与ConcreteClass A 不同实现方法
class ConcreteClassB : AbstractClass
{
public override void PrimitiveOperation1()
{
Console.WriteLine("具体类B方法1实现");
}
public override void PrimitiveOperation2()
{
Console.WriteLine("具体类B方法2实现");
}
}
// 客户端代码
static void Main(string[] args)
{
AbstractClass c;
c = new ConcreteClassA();
c.TemplateMethod();
c = new ConcreteClassB();
c.TemplateMethod();
Console.Read();
}
#endregion

核心在于:将子类变量的声明改成父类,利用多态性,实现了代码的复用。