设计模式之三个工厂
来源:互联网 发布:sql语句教程 编辑:程序博客网 时间:2024/05/16 08:20
在学习设计模式的过程中,看到了三个模式很相似的名称,这一篇博客,就拿它们在一起说说。首先,这三个模式的名称分别是简单工厂、工厂方法和抽象工厂模式。对于前两个模式,感觉还比较好理解,抽象工厂模式真的很糊涂。也许,等这篇博客完工后,自己对它会更亲密些了。首先说第一个简单工厂模式。从类型上来说,它应该属于创建型模式,但它并不包含在上篇23种模式总结的范围之中。至于为什么,自己也不清楚。这也就让自己想到了一个问题,模式的分类为什么分为创建、结构和行为三大类呢?这个问题可以在第三遍设计模式的时候思考思考。言归正传,还是回到简单工厂模式。【简单工厂模式】其是由一个工厂对象决定创建出哪一种产品类的实例。● 该模式中包含的角色及其职责:① 工厂(Creator)角色:该模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。② 抽象产品(Product)角色:该模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。③ 具体产品(Concrete Product)角色:该模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。● 该模式的最大优点:工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。● 该模式的缺点:由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则需要改变工厂类,也就相应地违背了开放-封闭原则。● 该模式何时使用:① 工厂类负责创建的对象比较少;② 客户只知道传入工厂类的参数,对于如何创建对象不关心;③ 由于很容易违反设计原则,所以一般只在很简单的情况下应用。【工厂方法模式】其定义一个用于创建对象的接口,让子类决定实例化哪一个类。其使一个类的实例化延迟到其子类。● 该模式中包含的角色及其职责:① 工厂接口:该模式的核心,与调用者直接交互用来提供产品。② 工厂实现:在编程中,其决定如何实例化产品。需要有多少种产品,就需要有多少个具体的工厂实现。③ 产品接口:其主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。④ 产品实现:实现产品接口的具体类,决定了产品在客户端中的具体行为。● 该模式的优点:① 可以使代码结构清晰,有效地封装变化。② 对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以。至于具体的实现,调用者无需关心。即使变更了具体的实现,对调用者来说没有任何影响。③ 降低耦合度。下面,就以大鸟和小菜一开始就讨论的一个计算器的程序为例,也正是因为这个程序,我才把更加清楚它们两个。先用简单工厂模式的方法看如何实现计算器:首先包含一个运算类:
- public class Operation
- {
- private double _numberA = 0;
- private double _numberB = 0;
- public double NumberA
- {
- get { return _numberA; }
- set { _numberA = value; }
- }
- public double NumberB
- {
- get { return _numberB; }
- set { _numberB = value; }
- }
- public virtual double GetResult()
- {
- double result = 0;
- return result;
- }
- }
其次各个具体的加减乘除类都继承运算类:
最后利用一个运算工厂类负责其中的实例化:
- class OperationAdd : Operation
- {
- public override double GetResult()
- {
- double result = 0;
- result = NumberA + NumberB;
- return result;
- }
- }
- class OperationSub : Operation
- {
- public override double GetResult()
- {
- double result = 0;
- result = NumberA - NumberB;
- return result;
- }
- }
这样的代码确实比面向过程方便很多,但是还是存在问题,比如现在想要增加一个其他的具体运算类,如求根,这下,就必须依靠修改代码去实现实例化,这也就违背了只扩展不修改的原则。办法总比问题多,这样,第二个说的工厂方法模式就可以用来解决问题了。下面看如何利用工厂方法模式的方法是如何实现计算器的:首先是前者方法中的运算类和各个具体运算类保持不变;其次增加一个工厂接口:
- public class OperationFactory
- {
- public static Operation createOperate(string operate)
- {
- Operation oper = null;
- switch (operate)
- {
- case "+":
- oper = new OperationAdd();
- break;
- case "-":
- oper = new OperationSub();
- break;
- case "*":
- oper = new OperationMul();
- break;
- case "/":
- oper = new OperationDiv();
- break;
- }
- return oper;
- }
- }
最后加减乘除各建一个具体的工厂去实现这个接口:
- interface IFactory
- {
- Operation CreateOperation();
- }
这样的代码就解决了上面去修改代码的问题,如果是要增加一个其他的具体运算类,只需要添加一个它的运算工厂以及具体运算类本身就行,也就是扩展就行。从两者的结构图看,也更加清晰一些:
- //加法类工厂
- class AddFactory:IFactory
- {
- public Operation CreateOperation()
- {
- return new OperationAdd();
- }
- }
- //减法类工厂
- class SubFactory:IFactory
- {
- public Operation CreateOperation()
- {
- return new OperationAdd();
- }
- }
到此,我们也可以很容易发现其实它们两者是极为相似的,区别也就是:简单工厂只有三个要素,它没有工厂接口,所以在工厂实现的扩展性方面弱,可以算是工厂方法模式的简化版吧。第三个,抽象工厂模式。【抽象工厂模式】提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。● 该模式何时使用:当每个抽象产品都有多于一个的具体子类的时候,工厂角色怎么知道实例化哪一个子类呢?:读到这句话,自己才明白那么一点为什么有抽象工厂模式的出现了。其提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂产品角色只负责一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。● 该模式优点:① 分离了具体的类;② 使得易于交换产品系列;③ 有利于产品的一致性。● 该模式缺点:难以支持新种类的产品对于其优点还是有些体会的。下面以大鸟和小菜讨论的访问数据的例子,看看它与工厂方法模式间的差别。先看用工厂方法模式实现数据访问程序:其中包含IUser接口(用于客户端访问)和IFactory接口(用于访问User表对象的抽象的工厂接口)
另外,还有具体类(AccessUser)和具体工厂(AccessFactory)。
- //IUser接口
- interface IUser
- {
- void Insert(User user);
- User GetUser(int id);
- }
- //IFactory接口
- interface IFactory
- {
- IUser CreateUser();
- }
这样,就用工厂方法模式实现了对数据的访问。下面同样一个问题:如果要增加某一具体类,在这里也就是指访问数据库中的其他表呢?这就必将增加一个个类对应一个个表。这时候,抽象工厂模式就来解决问题了。它实现不光是对User表的访问,同样访问Department表的访问。大体上都和工厂方法一致,只是它又通过增加接口来实现。同样看看两者的结构图:
- //AccessUser类
- class AccessUser:IUser
- {
- public void Insert(User user)
- {
- Console.WriteLine("在Access中给User表增加一条记录");
- }
- public User GetUser(int id)
- {
- Console.WriteLine("在Access中根据ID得到User表一条记录");
- return null;
- }
- }
- //AccessFactory类
- class AccessFactory:IFactory
- {
- public IUser CreateUser()
- {
- return new AccessUser();
- }
- }
最后,大鸟和小菜的对话,很好地说明了两者的区别。小菜以为后者也是工厂方法模式的实现,大鸟的回答是:“只有一个User类和User操作类的时候,是只需要工厂方法模式的,但是现在数据库中有很多表,而SQL Server与Access又是两大不同的分类,所以解决这种涉及到多个产品系列的问题,有一个专门的工厂模式叫做抽象工厂模式。
至此,三个工厂的总结就结束了。现在,也确实对三个工厂的了解更加深入了些。学习这三个模式,也让我们看到了遇到问题,就相应地解决问题的重要性,否则编写的程序永远不会有所进步的。
0 0
- 设计模式之三个工厂
- 设计模式之三个工厂
- 设计模式之三个工厂
- 【设计模式】三个工厂模式
- 设计模式—三个工厂
- java设计模式:三个工厂模式对比
- 【设计模式】一石三鸟——三个工厂
- 设计模式之工厂:
- 设计模式之工厂
- 设计模式之工厂
- 设计模式之工厂
- 设计模式之工厂
- 设计模式之工厂
- 设计模式之工厂
- 设计模式之工厂
- 【设计模式】单例模式、三个工厂模式
- 设计模式之工厂设计
- 设计模式——三个工厂模式(简单工厂,工厂方法,抽象工厂)
- 一次线上运营活动实操
- DLL函数导出类型
- IOS5 ARC unsafe_unretained等说明
- SQL Server 2008 1433端口启用的解决方案
- 用CppWebBrowser读写html元素值
- 设计模式之三个工厂
- 动态计算UITableViewCell高度详解
- 迭代二总结--包煜
- EGL接口介绍
- odbcad32.exe ODBC 32 and 64 bit version
- 《程序员 你伤不起》读后感(一)
- dom4j基础教程
- Windows下 maven3.0.4的安装步骤+maven配置本地仓库
- EXIF知识学习(2013/2/4)