模型
工厂方法模式(factory method):定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法是一个类的实例化延迟到其子类。
工厂方法和简单工厂方法看起来大部分是一样的,只是在工厂这里,简单工厂是通过Switch语句进行选择然后实例化对象,而在工厂方法里面,对工厂进一步抽象,定义了一个工厂接口,让每一类产品对应一个工厂接口,在实例化具体产品的时候,要通过实现工厂接口的类进行。
两种方法的比较:
工厂方法克服了简单工厂违背开放—封闭原则的缺点,又保持了封装对象创建过程的优点。
它们都是集中封装了对象的创建,使得要更换对象时,不需要做大的改动就可实现,降低了客户程序与产品对象的耦合。工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。但缺点是由于每加一个产品,就需要加一个产品工厂的类,增加了额外的开发量。
示例
在学习简单工厂的时候,我写过一个CPU生产的例子(简单工厂模式),现在把这个例子稍加改动,它就成了工厂方法的例子。如图:
在这里,将工厂类去掉,但是抽象出来Client接口,并让3个具体的工厂方法去实现这个接口。也就是说,用子类的Client8085,Client8080,Client8086去决定实例化哪一个类。通过这样的改动,将一个类的实例化延迟到了其子类。
代码如下:
namespace 生产CPU { public class Cpu8086 : CPU //8086CPU { public Cpu8086() { this.size = "8086"; Console.WriteLine("生产的是8086CPU。"); } } public class Cpu8080 : CPU //8080CPU { public Cpu8080() { this.size = "8080"; Console.WriteLine("生产的是8080CPU。"); } } public class Cpu8085 : CPU //8085CPU { public Cpu8085() { this.size = "8085"; Console.WriteLine("生产的是8085CPU。"); } } public class CPU //CPU类 { private string Size; public string size { get { return Size; } set { Size = value; } } } interface Client //定义一个选择生产CPU的接口(客户的抽象) { CPU ChooseCpu(); } class Client8086 : Client //生产8086CPU的工厂类 { public CPU ChooseCpu() { return new Cpu8086(); } } class Client8085 : Client //生产8085CPU的工厂类 { public CPU ChooseCpu() { return new Cpu8085(); } } class Client8080 : Client //生产8080CPU的工厂类 { public CPU ChooseCpu() { return new Cpu8080(); } } class Program { static void Main(string[] args) { Client client = new Client8080(); //生产8080CPU CPU CpuType = client.ChooseCpu(); } } }
工厂方法虽然增加了额外的类,但是这样做是有好处的,例如: