工厂方法模式 - OK
工厂方法模式(Factory Method),定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。
工厂方法模式在实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还存在,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。想要加功能,本来是修改工厂类的,而现在是修改客户端。
下面给出工厂方法模式UML图:
工厂方法模式示例:

- namespace 工厂方法模式
- {
- //数据库类
- class DataBase
- {
- public virtual string SelectTopOne()
- {
- return "SELECT TOP 1 * FROM Table";
- }
- }
- //SQLServer类
- class SQLServer : DataBase
- {
- public override string SelectTopOne()
- {
- return "SELECT TOP 1 * FROM Table";
- }
- }
- //Oracle类
- class Oracle : DataBase
- {
- public override string SelectTopOne()
- {
- return "SELECT * FROM Table WHERE ROWRUM <= 1";
- }
- }
- //总结来说,下面的1个接口两个类实现的就是简单工厂中switch的功能
- //数据库工厂
- interface IFactory
- {
- DataBase GetDataBase();
- }
- //SQLServer工厂
- class SQLServerFactory : IFactory
- {
- public DataBase GetDataBase() { return new SQLServer(); }
- }
- //Oracle工厂
- class OracleFactory : IFactory
- {
- public DataBase GetDataBase() { return new Oracle(); }
- }
- class Program
- {
- static void Main(string[] args)
- {
- IFactory factory = new SQLServerFactory(); //依赖于具体工厂类,但不依赖具体实现了了
- DataBase DB = factory.GetDataBase(); //从获得的工厂中 获取学雷锋对象
- Console.WriteLine(DB.SelectTopOne());
- //但是我有一种很强烈的感觉,既然如此,何不这样,虽然依赖了具体实现类,但是少了3个类
- //DataBase DB = new SQLServer();
- //Console.WriteLine(DB.SelectTopOne());
- Console.ReadKey();
- }
- }
- }

类图如下:
为了对比与简单工厂模式的区别,以下再写个简单工厂模式的来比较下:

- namespace 简单工厂
- {
- public class Program
- {
- static void Main(string[] args)
- {
- DataBase DB = SimpleFactory.GetInstance("Oracle");
- Console.WriteLine(DB.SelectTopOne());
- DataBase DB2 = SimpleFactory.GetInstance("SQLServer");
- Console.WriteLine(DB2.SelectTopOne());
- Console.ReadKey();
- }
- }
- //简单工厂类,判断类,用于返回对应的的对象
- public class SimpleFactory
- {
- public static DataBase GetInstance(string type)
- {
- DataBase db = null;
- switch (type)
- {
- default:
- case "SQLServer":
- db = new SQLServer();
- break;
- case "Oracle":
- db = new Oracle();
- break;
- }
- return db;
- }
- }
- //基类
- public class DataBase
- {
- public virtual string SelectTopOne()
- {
- return "SELECT TOP 1 * FROM Table";
- }
- }
- //实现类1
- public class SQLServer : DataBase
- {
- public override string SelectTopOne()
- {
- return "SELECT TOP 1 * FROM Table";
- }
- }
- //实现类2
- public class Oracle : DataBase
- {
- public override string SelectTopOne()
- {
- return "SELECT * FROM Table WHERE ROWRUM <= 1";
- }
- }
- }

比较一下,两者实现的代码类似。
对于简单工厂模式,在客户端方面,去除了对具体雷锋的依赖,即可以不出现具体的雷锋类(如大学生,社区志愿者)。但如果要添加一个学雷锋的中学生,就需要修改工厂类里面的case判断,以及添加一个具体类。
对于工厂方法模式,由客户端方面来决定实例化哪一个工厂来实现运算类,当然判断的问题还是存在。相比于简单工厂,判断的工作交到客户端来处理。但是有一个好处,就是当需要添加一个DB2实现时,就没有必要再修改原有的工厂类,只需要添加一个工厂类(这就是为何这么多工厂类,一个实现类就有一个工厂类),以及具体类(如例子中的SQLServer、Oracle)。
客户端new的地方。相对于简单工厂而言,对修改封闭了,符合开放封闭原则。但是带来了代价就是类比较多(工厂类太多了,找死你)。
工厂方法模式 - OK的更多相关文章
- 工厂方法模式——创建型模式02
1. 简单工厂模式 在介绍工厂方法模式之前,先介绍一下简单工厂模式.虽然简单工厂模式不属于GoF 23种设计模式,但通常将它作为学习其他工厂模式的入门,并且在实际开发中使用的也较为频繁. (1 ...
- 设计模式C#合集--工厂方法模式
简单工厂,代码: public interface ISpeak { public void Say(); } public class Hello : ISpeak { public void Sa ...
- PHP设计模式(二)工厂方法模式(Factory Method For PHP)
简单工厂简述: 简单工厂模式实现了生产产品类的代码跟客户端代码分离,在工厂类中你可以添加需要生成长跑的逻辑代码(new 产品类),但是问题来了,优秀的代码是符合"开闭原则"如果你要 ...
- javascript设计模式-工厂方法模式
工厂方法模式笔记 通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例 对于创建多类对象,简单工厂不太实用,这是简单工厂模式的应用局限,当然这正是工厂方法模式的价值之所在 通过工厂方法模 ...
- C#设计模式(3)——工厂方法模式
一.概念:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 二.代码实现 namespace 设计模式之工厂方法模式 { /// <summary&g ...
- C#设计模式系列:工厂方法模式(Factory Method)
1. 工厂方法模式简介 1.1 定义 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法模式是以一个类的实例化延迟到其子类. Factory Method模式用于在不指定待创建 ...
- 设计模式(三)工厂方法模式(Factory Pattern)
一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是——简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以 ...
- php实现设计模式之 工厂方法模式
<?php /* * *工厂方法模式,创建型模式 定义一个用于创建对象的工厂接口,让子类决定实例化哪一个类.Factory Method使用一个类的实例化延迟到其子类 * * 四个角色: * 工 ...
- 【2016-10-17】【坚持学习】【Day8】【工厂方法模式】
工厂方法模式又叫工厂模式,虚拟构造器模式 定义: 工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该 ...
- 工厂方法模式与IoC/DI
IoC——Inversion of Control 控制反转 DI——Dependency Injection 依赖注入 1:如何理解IoC/DI 要想理解上面两个概念,就必须搞清 ...
随机推荐
- DPDK2.1开发者手册1-2
Programmer’s Guide Release 2.1.0 翻译的目的是强化自己对dpdk的理解,看看2.1版本和现在使用的版本的差异,其次就是可能要走了,为那些要上手dpdk,但是又不想看英文 ...
- zoj3422Go Deeper(2-sat + 二分)
题目请戳这里 题目大意: go(int dep, int n, int m) begin output the value of dep. if dep < m and x[a[dep]] + ...
- char和int的转换
import java.util.Scanner; public class test7 { public static void main(String[] args) { // TODO Auto ...
- iOS UITableView 修改滚动条颜色 默认选中第一条
//隐藏 self.tableView.showsVerticalScrollIndicator = NO; //修改颜色 self.tableView.indicatorStyle=UIScroll ...
- script标签的位置
1.在我们编写代码的时候,会在页面内使用<script>标签来写JS,虽然理论上script标签的位置放在哪里可以,但是还是有一点区别的. 2.为什么很多人把script标签放在底部: 初 ...
- Android应用程序的安装位置
Android应用程序的默认安装位置以及是否可移动取决于开发者在其AndroidManifest.xml中的设置: <manifestxmlns:android="http://s ...
- Netmon: A light-weight network monitor for Windows
Netmon is a light-weight network monitor that works on Windows operating systems. It provides differ ...
- 通知 Notification 详解
效果 通知栏-刚收到通知时 通知栏-收到通知几秒后 标准视图 大视图-下滑前是标准视图 大视图-下滑后显示大视图 自定义通知 讲解 Notification,俗称通知,是一种具有全局效果的通知,它展示 ...
- css中常用的标签
最常用的标签 left 左 top 上 right 右 bottom 下 font 字体 size 大小 width 宽度 height 高度 class 类 label 标签 form 表单 gro ...
- 如何获取外网Ip呢, 终于找到方法了
临时更换网址:http://20140507.ip138.com/ic.asp 这个网址能同时获取ip和城市名字 上面的网址如何来的呢,其实很简单,随便打开一个获取Ip的网站,比如http://www ...