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

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

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

C#——工厂模式的更多相关文章

  1. 23种设计模式--工厂模式-Factory Pattern

    一.工厂模式的介绍       工厂模式让我们相到的就是工厂,那么生活中的工厂是生产产品的,在代码中的工厂是生产实例的,在直白一点就是生产实例的类,代码中我们常用new关键字,那么这个new出来的实例 ...

  2. javascript工厂模式和构造函数模式创建对象

    一.工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程(本书后面还将讨论其他设计模式及其在JavaScript 中的实现).考虑到在ECMAScript 中无法创 ...

  3. PHP设计模式(三)抽象工厂模式(Abstract Factory For PHP)

    一.什么是抽象工厂模式 抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象 ,而且使用抽象工厂模式还要满足以下条件: 系统中有多个产品族,而系统一次只可能消费其中一族产品. 同 ...

  4. PHP设计模式(一)简单工厂模式 (Simple Factory For PHP)

    最近天气变化无常,身为程序猿的寡人!~终究难耐天气的挑战,病倒了,果然,程序猿还需多保养自己的身体,有句话这么说:一生只有两件事能报复你:不够努力的辜负和过度消耗身体的后患.话不多说,开始吧. 一.什 ...

  5. 设计模式之工厂模式VS抽象工厂

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...

  6. 菜鸟理解的工厂模式(Factory Pattern)是什么样子的?

    直接开始说了,不浪费园友宝贵的时间! 什么是工厂模式? 在学习前,先问一下:"它是什么?". 工厂模式,它是项目里面常用的设计模式之一. 它是属于创建型模式,简单的理解创建型模式就 ...

  7. PHP 面向对象编程和设计模式 (3/5) - 单例模式和工厂模式

    PHP高级程序设计 学习笔记 2014.06.11 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容 ...

  8. 《JS设计模式笔记》构造函数和工厂模式创建对象

    工厂模式 function createPerson (name,age,job) { var o=new Object(); o.name=name; o.age=age; o.job=job; o ...

  9. 从接口、抽象类到工厂模式再到JVM来总结一些问题

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习! 涉及到的知识点总结如下: 为什么使用接口? 接口和抽象类的区别 简单工厂模式总结 Java中new和newInstance的区别 J ...

  10. C#设计模式之简单工厂模式(Simple Factory)

    1. 概述 简单工厂模式就是将一个类的实例化交给一个静态工厂来执行. 2. 使用频率 中 3. 模式结构 3.1 机构图 3.2 模式中的角色 Product:抽象类,把具体产品类公共的代码进行抽象和 ...

随机推荐

  1. [bzoj 2705][SDOI2012]Longge的问题(数学)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2705 分析: 设k为n的因数 设f[k]为gcd(x,n)==k的x的个数,容易知道a ...

  2. Ubuntu 16.04安装Adobe AIR

    安装: wget -O adobe-air.sh http://drive.noobslab.com/data/apps/AdobeAir/adobe-air.sh chmod +x adobe-ai ...

  3. PayPal加密证书.pem的生成

    How do I create a public certificate for use with PayPal Encrypted Website Payments?   Before you ca ...

  4. Date.parse函数的兼容问题

    由于要用Date.parse函数解析一个日期时间的字符串.在谷歌浏览器中解析成功,但是IE.火狐中却不行. 不知何故.firefox对于类似"2010-12-20 15:55:00" ...

  5. C#反射发出System.Reflection.Emit学习

    一.System.Reflection.Emit概述 Emit,可以称为发出或者产生.与Emit相关的类基本都存在于System.Reflection.Emit命名空间下.反射,我们可以取得形如程序集 ...

  6. 安装ubuntu远程桌面xrdp可视化设置界面

    ubuntu 远程桌面的时候须要从系统-首选项-远程桌面 可是有的ubuntu远程桌面的应用须要自己安装.例如以下是安装命令: sudo apt-get install xrdp

  7. WebSocket握手总结

    网址:http://blog.csdn.net/edwingu/article/details/44040961 WebSocket protocol 是HTML5一种新的协议.它实现了浏览器与服务器 ...

  8. LIBTOOL is undefined 问题的解决方法

    configure.ac:10: error: possibly undefined macro: AC_PROG_LIBTOOL If this token and others are legit ...

  9. E20170925-hm

    arc  n. 综合症状; 弧(度); 天穹; 电弧,弧光.; vi. 形成拱状物; 循弧线行进; wrap  vt. 包; 缠绕; 用…包裹(或包扎.覆盖等); 掩护;            n. ...

  10. Going Home(MCMF)

    http://poj.org/problem?id=2195 题意:在一个n*m的图中,'m'代表人,'H'代表房子,人每移动一次的费用为1,求所有人移动到房子里的最小花费. 思路:最小费用最大流问题 ...