六个创建模式之工厂方法模式(Factory Method Pattern)
问题:
在使用简单工厂模式的时候,如果添加新的产品类,则必需修改工厂类,违反了开闭原则。
定义:
定义一个用于创建对象的接口,让子类决定具体实例化哪个产品类。此时工厂和产品都具有相同的继承结构,抽象产品类与抽象工厂对应,具体的产品类和具体的工厂类对应。工厂方法模式又称为:工厂模式(Factory Pattern)、虚拟构造器模式(Virtual Constructor Pattern)、多态工厂模式(Polymorphic Factory Pattern)等。
结构图:
- Product:抽象产品类,是所有具体产品的超类型,封装了具体产品的公共方法。
- ConcreteProduct:具体产品类,实现了抽象产品类的接口,和具体工厂一一对应。
- Factory:抽象工厂类,定义了返回抽象产品类的工厂方法,是工厂方法模式的核心。
- ConcreteFactory:具体工厂类,实现了抽象工厂定义的工厂方法,由客户端直接调用,返回其对应的具体产品类。
注意:
为了让系统有更好的灵活性和可扩展性,可以使用XML技术和反射技术让客户端通过配置文件指定具体工厂类。
可以在抽象工厂中定义多个重载的工厂方法,包含不同的业务逻辑,来满足对不同产品对象的需求。例如可以传入数据库配置信息,文件配置信息等。
interface LoggerFactory {
public Logger createLogger();
public Logger createLogger(String args);
public Logger createLogger(Object obj);
}
class DatabaseLoggerFactory implements LoggerFactory {
public Logger createLogger() {
//使用默认方式连接数据库,代码省略
Logger logger = new DatabaseLogger();
//初始化数据库日志记录器,代码省略
return logger;
}
public Logger createLogger(String args) {
//使用参数args作为连接字符串来连接数据库,代码省略
Logger logger = new DatabaseLogger();
//初始化数据库日志记录器,代码省略
return logger;
}
public Logger createLogger(Object obj) {
//使用封装在参数obj中的连接字符串来连接数据库,代码省略
Logger logger = new DatabaseLogger();
//使用封装在参数obj中的数据来初始化数据库日志记录器,代码省略
return logger;
}
}
- 还可以由工厂直接调用具体产品的业务方法,而隐藏工厂创建具体实例的方法。
abstract class LoggerFactory {
//在工厂类中直接调用日志记录器类的业务方法writeLog()
public void writeLog() {
Logger logger = this.createLogger();
logger.writeLog();
}
public abstract Logger createLogger();
}
优点:
- 利用工厂的工厂方法类创建具体的实例,隐藏了具体实例的创建细节,无需知道具体实例的类名,只需关心对应工厂。
- 加入新的产品类是,只需要同时加入工厂类就可以实现扩展。如果利用反射和XML技术,不需要修改任何源码,符合“开闭原则”
缺点:
- 系统中类的个数显著增加,不利于系统的维护,增加系统编译和运行的开销。
适用场景
- 具体产品类数目不多,客户不需要知道具体产品类的详细信息,只需要知道具体对应的工厂。
实例:
六个创建模式之工厂方法模式(Factory Method Pattern)的更多相关文章
- 使用C# (.NET Core) 实现简单工厂(Simple Factory) 和工厂方法设计模式 (Factory Method Pattern)
本文源自深入浅出设计模式. 只不过我是使用C#/.NET Core实现的例子. 前言 当你看见new这个关键字的时候, 就应该想到它是具体的实现. 这就是一个具体的类, 为了更灵活, 我们应该使用的是 ...
- 23种设计模式之工厂方法(Factory Method Pattern)
工厂方法 前面我们学习了简单工厂,发现一个问题就是简单工厂集合了矛盾,为了解决这个问题我们针对每一种产品提供一个工厂类.通过不同的工厂实例来创建不同的产品实例.在同一等级结构中,支持增加任意产品这种设 ...
- 设计模式---对象创建模式之工厂方法模式(Factory Method)
前提:“对象创建”模式 通过“对象创建”模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式(表现最为突出) 工 ...
- 设计模式学习之工厂方法(Factory Method,创建型模式)(2)
接着上一讲中的简单工厂继续讲解,假如我们有了需要采集新的水果梨子,如果我们使用简单工厂中的方式的话,就会新增一个Pear类,然后实现Fruit类,然后修改FruitFactory类中获取实例的方法 g ...
- Java设计模式(2)——创建型模式之工厂方法模式(Factory Method)
一.概述 上一节[简单工厂模式]介绍了通过工厂创建对象以及简单的利弊分析:这一节来看看工厂方法模式对类的创建 工厂方法模式: 工厂方法与简单工厂的不同,主要体现在简单工厂的缺点的改进: 工厂类不再负责 ...
- JAVA设计模式(01):创建型-工厂模式【工厂方法模式】(Factory Method)
简单工厂模式尽管简单,但存在一个非常严重的问题.当系统中须要引入新产品时,因为静态工厂方法通过所传入參数的不同来创建不同的产品,这必然要改动工厂类的源码,将违背"开闭原则".怎样实 ...
- 工厂方法(Factory Method)模式
一.工厂方法(Factory Method)模式 工厂方法(FactoryMethod)模式是类的创建模式,其用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟的子类中. 工厂方法模式是简单工厂 ...
- 设计模式的征途—3.工厂方法(Factory Method)模式
上一篇的简单工厂模式虽然简单,但是存在一个很严重的问题:当系统中需要引入新产品时,由于静态工厂方法通过所传入参数的不同来创建不同的产品,这必定要修改工厂类的源代码,将违背开闭原则.如何实现新增新产品而 ...
- 小菜学习设计模式(三)—工厂方法(Factory Method)模式
前言 设计模式目录: 小菜学习设计模式(一)—模板方法(Template)模式 小菜学习设计模式(二)—单例(Singleton)模式 小菜学习设计模式(三)—工厂方法(Factory Method) ...
- Java 工厂模式(一)— 工厂方法(Factory Method)模式
一.工厂方法(Factory Method)模式: 1.什么是工厂方法模式? 工厂方法模式是类的创建型模式,又叫做虚拟构造子模式或者多态工厂模式.它的意义是创建产品对象的工厂接口,将实际创建工作推迟到 ...
随机推荐
- 在UWP应用中实现Gif播放
众所周知,在UWP应用框架中,Image控件是无法播放GIF的图片,只能显示静态图,这样的体验不是特别友好.我在Win8.WP8.1的时候实现过gif播放功能,但是最近发现性能和播放效果都差强人意,大 ...
- jQuery easyui combobox级联及内容联想
1.需求:已有一个下拉框A表示地区,现新增需求,需要在A选择不同地区时,增加一个展示该地区所有城市的下拉框B, 由于城市较多,要求B能实现用户输入和模糊匹配展示功能. 2.实现: (1)首先在A下面把 ...
- Android之线程回掉更新ui
一:工作线程中的回掉更新UI public class MainActivity extends AppCompatActivity { private int i; private Callback ...
- 制作便携版 FireFox 火狐浏览器
Firefox是一款可高度自定义的开源浏览器: 你可以访问 火狐DIY 定制自己的Firefox安装包, 此外,你还可以自己动手定制一款可以放在U盘随身携带的便携版Firefox火狐浏览器. 制作便携 ...
- 编写高质量JS代码的68个有效方法(七)
[20141220]编写高质量JS代码的68个有效方法(七) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...
- [IR] Tolerant Retrieval & Spelling Correction & Language Model
Dictionary不一定是个list,它可以是多种形式. 放弃Hash的原因: 通常,tree是比较适合的结构. From: http://www.cnblogs.com/v-July-v/arch ...
- [mysql]增加用户 授权 远程登录
mysql创建用户和授权 1.创建用户: (注意:下面的指令,请在root用户下输入) CREATE USER "用户名" IDENTIFIED BY "密码" ...
- js中offsetLeft,offsetTop,offsetParent计算边距方法
封装一个函数获得任一元素在页面的位置 var GetPosition= function (obj) { var left = 0; var top = 0; while(obj.offsetPare ...
- 利用session做国际化引起的old区内存爆满及修复方法
题记:昨天加班打车回家,看见前面有辆路虎在高速上开的巨慢,挡住了我坐的出租车的路,于是就跟司机吐槽了一句:“前面这车怎么这么面啊?”,司机沉默了大概3秒,说了一句富含哲理性的话:“没有面车,只有面人” ...
- 如何花样展示自己的摄影作品?CSS+JS+Html
注意:Windows平台推荐使用Edge.Chrome.FireFox,部分浏览器打不开 P.S.慢慢用鼠标在图片上拖拽会感觉更神奇 // 0.5 ? 1 : -1; }, ease: fun ...