C#——工厂模式

之前我们接介绍了简单工厂,这次我们介绍一种更为常用的模式——工厂模式。

工厂方法模式Factory Method,又称多态性工厂模式。在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。

工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。

开闭原则(OCP):)是面向对象设计中“可复用设计”的基石,是面向对象设计中最重要的原则之一,其它很多的设计原则都是实现开闭原则的一种手段。对于扩展是开放的,对于修改是关闭的,这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。也就是说,我们可以改变模块的功能。对模块行为进行扩展时,不必改动模块的源代码或者二进制代码。模块的二进制可执行版本,无论是可链接的库、DLL或者.EXE文件,都无需改动。实现开闭原则的关键就在于“抽象”。把系统的所有可能的行为抽象成一个抽象底层,这个抽象底层规定出所有的具体实现必须提供的方法的特征。作为系统设计的抽象层,要预见所有可能的扩展,从而使得在任何扩展情况下,系统的抽象底层不需修改;同时,由于可以从抽象底层导出一个或多个新的具体实现,可以改变系统的行为,因此系统设计对扩展是开放的。

之前简单工厂的核心工厂就是根据需求不断制造类的实例,现在我们将这个行为抽象化,就会达到多种效果:单一化,模块化,拓展性强,便于修改。主程序的代码可以不用动,只需要增加类就行了(实现某种功能的类,往往继承于一个接口)。下面看代码:

public interface IFactory { IPerson GetSay(); }
public interface IPerson { void Say(); }
public class Student : IPerson
{
    public void Say()
    {
        Console.WriteLine("我是学生....");
    }
}
public class Teacher : IPerson
{
    public void Say()
    {
        Console.WriteLine("我是老师....");
    }
}

public class StudentFactory : IFactory
{
    public IPerson GetSay()
    {
        return new Student();
    }
}

public class TeacherFactory : IFactory
{
    public IPerson GetSay()
    {
        return new Teacher();
    }
}

上面我们把最重要的两个东西都抽象画了——工厂和产品。产品IPerson我们就不说了还是遵循简单工厂。最大变化是这里的工厂IFactory不再直接参与生产,而是把这项具体工作将给了子类StudentFactory、TeachFactory,让他们去生产类的实例。将这个生产动作抽象化,完美的实现了开闭原则。下面是主程序调用:

<appSettings>
  <add key="AssemblyPath" value="ConsoleApp2"/>
  <add key="NameSpace" value="ConsoleApp2"/>
  <add key="StudentFactory" value="StudentFactory"/>
</appSettings>
private static readonly string assemblyName = ConfigurationManager.AppSettings["AssemblyPath"];//程序集
private static readonly string nameSpace = ConfigurationManager.AppSettings["NameSpace"];//命名空间
private static readonly string className = ConfigurationManager.AppSettings["StudentFactory"];//类名

public static object CreateInstance(string assemblyName, string nameSpace, string className)
{
    try
    {
        string fullName = nameSpace + "." + className;//命名空间.类型名
        object ect = Assembly.Load(assemblyName).CreateInstance(fullName);//加载程序集,创建程序集里面的 命名空间.类型名 实例
        return ect;//类型转换并返回    
    }
    catch (Exception ex) { Console.WriteLine(ex.Message + "===" + ex.StackTrace); return false; }
}

static void Main(string[] args)
{
    IFactory ifc = CreateInstance(assemblyName, nameSpace, className) as IFactory;
    IPerson ip = ifc.GetSay();
    ip.Say();
    Console.ReadKey();
}

这里有个技巧就是利用之前介绍过的反射,修改配置文件就可以创建类的实例。这里我们通过反射创建了StudentFactory的实例,然后利用类的多态特性,调用GetSay方法。得到继承于接口IPerson的子类实例,然后又利用类的多态特性,调用Say方法,最终完成。主程序中两次抽象,两次创建了类的实例,最开始还用到了反射,从头至尾,目的就是为了解耦,达到开闭的原则,便于以后的功能拓展。

参考:开闭原则详解设计模式之工厂模式(简单工厂+工厂方法+抽象工厂)

原文地址:https://www.cnblogs.com/wuqiuxue/p/7726554.html