zoukankan      html  css  js  c++  java
  • 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方法,最终完成。主程序中两次抽象,两次创建了类的实例,最开始还用到了反射,从头至尾,目的就是为了解耦,达到开闭的原则,便于以后的功能拓展。

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

  • 相关阅读:
    【java读书笔记】——java的异常处理
    《C程序猿:从校园到职场》出版预告(4):从“散兵游勇”到“正规部队”
    GIS+=地理信息+行业+大数据——纽约公开11亿条出租车和Uber原始数据下载及分析
    Java第二次作业
    Qt5的插件机制(6)--开发Qt插件时几个重要的宏
    如何获得(读取)web.xml配置文件的參数
    JavaScript、jQuery、HTML5、Node.js实例大全-读书笔记1
    虚幻4Matinee功能 基本概念及简单演示样例(Sequence编辑器)
    Loadrunner Analysis之Web Page Diagnostics
    Linux下Jenkins+git+gradle持续集成环境搭建
  • 原文地址:https://www.cnblogs.com/wuqiuxue/p/7726554.html
Copyright © 2011-2022 走看看