工厂方法模式(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的地方。相对于简单工厂而言,对修改封闭了,符合开放封闭原则。但是带来了代价就是类比较多(工厂类太多了,找死你)。

 
 
分类: 设计模式
 
0
0
 
(请您对文章做出评价)
 
« 上一篇:代理模式 - OK
» 下一篇:原型模式 - OK

工厂方法模式 - OK的更多相关文章

  1. 工厂方法模式——创建型模式02

    1. 简单工厂模式     在介绍工厂方法模式之前,先介绍一下简单工厂模式.虽然简单工厂模式不属于GoF 23种设计模式,但通常将它作为学习其他工厂模式的入门,并且在实际开发中使用的也较为频繁. (1 ...

  2. 设计模式C#合集--工厂方法模式

    简单工厂,代码: public interface ISpeak { public void Say(); } public class Hello : ISpeak { public void Sa ...

  3. PHP设计模式(二)工厂方法模式(Factory Method For PHP)

    简单工厂简述: 简单工厂模式实现了生产产品类的代码跟客户端代码分离,在工厂类中你可以添加需要生成长跑的逻辑代码(new 产品类),但是问题来了,优秀的代码是符合"开闭原则"如果你要 ...

  4. javascript设计模式-工厂方法模式

    工厂方法模式笔记  通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例  对于创建多类对象,简单工厂不太实用,这是简单工厂模式的应用局限,当然这正是工厂方法模式的价值之所在  通过工厂方法模 ...

  5. C#设计模式(3)——工厂方法模式

    一.概念:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 二.代码实现 namespace 设计模式之工厂方法模式 { /// <summary&g ...

  6. C#设计模式系列:工厂方法模式(Factory Method)

    1. 工厂方法模式简介 1.1 定义 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法模式是以一个类的实例化延迟到其子类. Factory Method模式用于在不指定待创建 ...

  7. 设计模式(三)工厂方法模式(Factory Pattern)

    一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是——简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以 ...

  8. php实现设计模式之 工厂方法模式

    <?php /* * *工厂方法模式,创建型模式 定义一个用于创建对象的工厂接口,让子类决定实例化哪一个类.Factory Method使用一个类的实例化延迟到其子类 * * 四个角色: * 工 ...

  9. 【2016-10-17】【坚持学习】【Day8】【工厂方法模式】

    工厂方法模式又叫工厂模式,虚拟构造器模式 定义: 工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该 ...

  10. 工厂方法模式与IoC/DI

    IoC——Inversion of Control  控制反转 DI——Dependency Injection   依赖注入 1:如何理解IoC/DI        要想理解上面两个概念,就必须搞清 ...

随机推荐

  1. convert app to 64-bit for ios7

    https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/Introd ...

  2. prepareStatement的用法和解释

    1. PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程2. 使用 Statement 对象.在对数据库只执行一次性存取的时侯,用 Statement ...

  3. php form表单post提交获取不到数据,而使用get提交能获取到数据 的解决办法

    开发环境:xampp,mac,phpstorm 其实出现这个问题的原因就是在于phpstorm,它默认使用的是自带的内部服务器,这个服务器使用63342端口,而且服务器内部有问题,导致POST方法异常 ...

  4. Using HttpClient properly to avoid CLOSE_WAIT TCP connections

    Apache的HttpComponent组件,用的人不在少数.但是能用好的人,却微乎其微,为什么?很简单,TCP里面的细节实现不是每个人都能捕获到的(细节是魔鬼),像并发请求控制&资源释放,N ...

  5. 经常使用的自己定义UI组件- 一:TimeView

     近期做蛋疼的机顶盒项目,以后遇到哪些经常使用的组件,记录于此. 反编译 youku视频TV偷来的..也希望各位童鞋多学习别人的代码,为己所用. 当然还有其它的办法,比方监听系统发出的广播等等.等 ...

  6. qemu-img 快照的一些总结

    qemu-img 快照的一些总结 http://www.openext.org/2014/06/qemu-img-snapshot-re http://blog.csdn.net/muge0913/a ...

  7. 忘记mysql 5.7的密码

    for windows: http://blog.chinaunix.net/uid-27570589-id-3511820.html 一.将net stop mysql; 二.在命令行中 C:\Us ...

  8. Json格式的http请求

    服务端PHP代码可以从这里下载:https://github.com/lornajane/PHP-Web-Services 1.使用volley实现: request要用JsonObjectReque ...

  9. tomcat程序记录客户端真实IP

    需求: 开发告知:让后端tomcat日志获取真实的IP,而不是nginx 服务器的IP tomcat前面是nginx做的反向代理,所以tomcat取到的是nginx的ip. 日志名称是localhos ...

  10. EasyUI 1.4.4 DataGrid(大数据量) bufferview滚动时不加载下一页数据解决方案

    在使用Easyui DataGrid 过程中,发现若单页数据量超过300,IE浏览器加载速度很慢.也通过网上找寻了很多解决方案,最典型的就是去掉datagrid的自动列宽以及自动行高判断. 1.解决自 ...