标签:简单工厂 block key 可扩展性 复用 除了 window 设计模式 htm
引言:上一篇写的的是简单工厂模式,简单工厂模式只有三个要素(工厂、抽象产品、具体产品),它没有
工厂接口
,并且得到产品的方法一般是静态的,所以在工厂实现的扩展性上面较差,可以当作工厂模式的简化版。在简单工厂模式中,当增加一个产品子类的时候,还需要在工厂方法的Switch分支中新增一个判断,只做到了对扩展的开放,并没有做到对修改关闭,而这点在工厂方法模式中得到了一定的克服,作为简单工厂模式的升级版,工厂方法模式更适用于复杂一点的创建方法中。
? 工厂方法模式(FACTORY METHOD)是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽象工厂、具体工厂、抽象产品、具体产品 。
抽象工厂(Creator)角色:
是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator)角色:
这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。在上图中有两个这样的角色:BulbCreator与TubeCreator。
抽象产品(Product)角色:
工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
具体产品(Concrete Product)角色:
这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
可以看到,对比简单工厂模式,工厂方法模式多了个抽象工厂(Creator)的角色,这也是工厂方法模式的核心。
? 上一篇的例子中,我们使用了简单工厂模式根据系统的不同从而创建不同的系统实例,这一次我们使用工厂方法模式实现上一篇的需求。
上一篇的需求如下??
说起操作系统,市面上大概可以分为三种:
? 现在老板有个需求,根据用户使用的操作系统的不同,分别调用不同操作系统的 SayHello()
方法,和用户打招呼。
工厂接口:任何在模式中创建的对象的工厂类必须实现这个接口
/// <summary>
/// 工厂抽象接口
/// </summary>
interface IOSFactory
{
/// <summary>
/// 创建操作系统类
/// </summary>
/// <returns></returns>
OS CreateOS();
}
具体工厂:实现抽象工厂接口的具体工厂类
/// <summary>
/// Windows操作系统工厂
/// </summary>
class WindowsOSFactory : IOSFactory
{
public OS CreateOS()
{
return new WindowsOS();
}
}
/// <summary>
/// Mac操作系统工厂
/// </summary>
class MacOSFactory : IOSFactory
{
public OS CreateOS()
{
return new MacOS();
}
}
/// <summary>
/// Linux操作系统工厂
/// </summary>
class LinuxOSFactory : IOSFactory
{
public OS CreateOS()
{
return new LinuxOS();
}
}
抽象产品角色:工厂方法模式所创建的超类型,也就是产品对象的共同父类或者共同拥有的接口,在此例中为OS
类
//包含SayHello()方法
interface ISayHelloAble
{
string SayHello();
}
/// <summary>
/// 操作系统抽象父类
/// </summary>
public abstract class OS:ISayHelloAble
{
public abstract string SayHello();
}
具体产品角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应,此例中为不同的操作系统。
/// <summary>
/// 具体的Windows操作系统,继承抽象的OS类
/// </summary>
class WindowsOS : OS
{
public override string SayHello()
{
string result = "你好,我是Windows操作系统,很高兴为您服务~";
return result;
}
}
/// <summary>
/// 具体的Linux操作系统
/// </summary>
class LinuxOS : OS
{
public override string SayHello()
{
string result = "你好,我是Linux操作系统,很高兴为您服务~";
return result;
}
}
/// <summary>
/// 具体的Mac操作系统
/// </summary>
class MacOS : OS
{
public override string SayHello()
{
string result = "你好,我是Mac OS操作系统,很高兴为您服务~";
return result;
}
}
客户端:
static void Main(string[] args)
{
//之后可以利用反射原理优化代码
IOSFactory oSFactory = new WindowsOSFactory();
OS concreteOS = oSFactory.CreateOS();
string greetings = concreteOS.SayHello();
Console.WriteLine(greetings);
Console.ReadKey();
}
结果:
? ?使用工厂方法模式之后,一个简单工厂模式的工厂类,变成了一个工厂抽象接口和多个具体生成对象的工厂,如果我们要对其它的操作系统进行支持,那么我们就不需要更改原有的工厂类了
? 例如我们需要增加Netware操作系统,我们只需要增加此功能的操作系统类和对应的工厂就行了。??
/// <summary>
/// 具体的Netware操作系统
/// </summary>
class NetwareOS : OS
{
public override string SayHello()
{
string result = "你好,我是Netware操作系统,很高兴为您服务~";
return result;
}
}
/// <summary>
/// Netware操作系统工厂
/// </summary>
class NetwareOSFactory : IOSFactory
{
public OS CreateOS()
{
return new NetwareOS();
}
}
?
但是仔细观察发现,工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现操作系统类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行,你想要增加功能,本来是改工厂类的,而现在是修改客户端!
? 那么有什么办法,让选择问题抛在客户端之外解决呢?我们可以使用“反射”。。
关于反射与工厂方法模式的结合将会在下一篇博客《抽象工厂模式》实现。
步骤1: 创建抽象工厂类,定义具体工厂的公共接口;
步骤2: 创建抽象产品类 ,定义具体产品的公共接口;
步骤3: 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;
步骤4:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
步骤5:外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例
工厂方法经常用在以下两种情况中:
————————————————————————————————————————————
版权声明:本文为吴恺的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
为获得更好的阅读体验,推荐至我的个人博客阅读:https://www.wukailiving.cn/er-gong-han-fang-fa-mo-shi.html
原文链接:https://www.cnblogs.com/zaijianba/p/11519672.html
如有不足之处,欢迎指正!
标签:简单工厂 block key 可扩展性 复用 除了 window 设计模式 htm
原文地址:https://www.cnblogs.com/zaijianba/p/11519672.html