引言(Introduction)
上一篇博客以手机工厂为例介绍了简单工厂模式,将创造OPPO手机和OPPO手机对象的逻辑都放在了内部PhoneFactory里面,并且分别创建了两个具体手机产品类OPPOPhone,OPPOPhone,具体Create哪类手机,就要看传入的参数了。这时,如果该手机工厂想要扩大生产规模,加入小米手机的生产,我们需要变动2个地方:增加一个XiaoMiPhone的具体产品类;修改工厂的内部逻辑,增加一个XiaoMiPhone的分支判断;这样不仅对于扩展开放了,而且对修改也开放了(修改了工厂类),这就违背了开闭原则。解决这个问题,就需要用到工厂方法(Factory Method)模式了。
意图(Intention)
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟到子类。
结构(struct)
角色(Roles)
抽象工厂(Creator):工厂方法的核心,任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator):实现抽象工厂接口的具体工厂类。
抽象产品(Producr):工厂方法所创建的对象的父类(或者说这些产品共同拥有的接口)。
具体产品(ConcreteProduct):由其对应的具体工厂创建,是抽象产品的子类(或者说实现了抽象产品的接口)
举例(Example)
创建一个工厂接口
interface IFactory
{
Phone CreatePhone();
}
三个牌的手机各建一个具体工厂去实现这个接口
class HuaWeiFactory : IFactory
{
public Phone CreatePhone()
{
return new HuaweiPhone();
}
}
class OPPOFactory : IFactory
{
public Phone CreatePhone()
{
return new OPPOPhone();
}
}
class XiaoMiFactory : IFactory
{
public Phone CreatePhone()
{
return new XiaoMiPhone();
}
}
抽象产品类:手机类
public class Phone
{
public virtual void Start(){}
}
具体产品类:HuaweiPhone,OPPOPhone,XiaoMiPhone,是Phone类的子类
class HuaweiPhone:Phone
{
public override void Start()
{
Console.WriteLine("华为手机开机了");
}
}
class OPPOPhone : Phone
{
public override void Start()
{
Console.WriteLine("OPPO手机开机了");
}
}
class XiaoMiPhone : Phone
{
public override void Start()
{
Console.WriteLine("小米手机开机了");
}
}
客户端代码的实现
IFactory phoneFactory = new HuaWeiFactory();
Phone phone = phoneFactory.CreatePhone();
phone.Start();
运行结果
与简单工厂相比,用抽象工厂模式,我们想要增加一个小米手机,只需要增加一个小米手机类和一个小米手机的具体工厂类就可以了,不需要修改原有的工厂类了。这样就只有扩展的变化,而没有修改的变化,就完全符合了开-闭原则。工厂方法模式在实现时,由客户端代码决定实例化哪一个工厂来实现创建哪一个品牌的手机,也存在判断,工厂方法将简单工厂内部逻辑判断移到了客户端代码来进行,不需要再改工厂类,只需要修改客户端就可以了。