设计模式初探之工厂方法模式
2017-12-03 12:25
204 查看
这篇博客更新距离上一篇时间格得有点长,一方面是最近工作较忙,另一方面得检讨下是不是又变懒了。
1、简单工厂模式中工厂类用于创建所有的产品,工厂类职责较重,业务逻辑较为复杂,具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性。各种创建产品的代码混在工厂类中。容易造成代码的混乱。
2、简单工厂模式违背了"开源-封闭原则",当加入新的产品时,除了去创建新的产品之外,还得去修改工厂类。当然,在简单工厂模式的那篇文章中,通过反射可以在新增产品时不用修改工厂类,但这种实现是有局限的,它的使用条件在于各个产品创建都不需要做些独特处理,当每个产品的创建都需要做不同的初始化时,这种方式就不能使用了。
3、工厂类过于庞大,包含了大量的if…else…代码,导致维护和测试难度增大。
基于以上简单工厂模式的缺点,工厂方法模式在简单工厂模式进行改进。
看了类图,是不是感觉很简单,是的,工厂方法模式是比较简单,容易理解的一种模式。其中有几个元素。
1、抽象产品类,对产品的抽象,定义产品的一些共性。2、具体产品,具体产品的实现。3、抽象工厂类,定义具体工厂类该实现的方法。4、具体工厂类,实现创建产品的方法。
相比静态工厂模式,工厂模式为每个产品添加自己的工厂类。这样每个产品的创建都在自己的工厂类内实现,这样就分离了各个产品创建混杂在一起,从而更容易测试,也减低了静态工厂模式下,单一工厂类的职责和复杂度。同时,每创建新产品,只需新增产品及产品对应的工厂类,而无需修改其他工厂类,这就符合了“开闭原则”。使得代码的结构,各产品更清晰,更适合阅读。
日志抽象类。
将日志打印到文件,具体实现类。
将日志打印到控制台,具体实现类。
有了具体的产品,这是我们就需要创建他们的工厂类。
抽象工厂类:
打印日志到控制台具体工厂类:
这样我们就实现就工厂方法模式。具体的测试类如下。
这时如果我们想增加一个实现将日志输出成字节流是,我们只需新增日志的打印字节流实现,还有新增他的工厂类,无需修改其他任何的代码。
这样,我们的简例就实现了工厂方法模式,是不是很简单啊,不知道你理解了么。
优点
1、工厂方法模式同简单工厂方法模式一样,实现了对客户端隐藏具体对象创建的具体细节,客户端不需要知道对象创建的过程,只需要知道通过工厂类即可创建具体的产品。
2、工厂类完全符合开源封闭原则,各产品直接没有耦合,新增产品方便,而且易于测试。
缺点
1、每新增一个产品,就得对应着新增一个工厂类,这样就会造成需新建的类比较多。
一、概述简单工厂模式的缺点,工厂方法模式的改进
这一篇将带来的是工厂方法模式,我的第一篇设计模式的博客写的就是简单工厂模式:简单工厂模式,工厂模式可以说是简单工厂模式的一个升级版,克服了简单工厂模式存在的一些问题。所以两者都是非常相似的,都是通过工厂类去创建对象,从而对客户端隐藏对象创建的细节。首先先看看简单工厂模式的缺点。1、简单工厂模式中工厂类用于创建所有的产品,工厂类职责较重,业务逻辑较为复杂,具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性。各种创建产品的代码混在工厂类中。容易造成代码的混乱。
2、简单工厂模式违背了"开源-封闭原则",当加入新的产品时,除了去创建新的产品之外,还得去修改工厂类。当然,在简单工厂模式的那篇文章中,通过反射可以在新增产品时不用修改工厂类,但这种实现是有局限的,它的使用条件在于各个产品创建都不需要做些独特处理,当每个产品的创建都需要做不同的初始化时,这种方式就不能使用了。
3、工厂类过于庞大,包含了大量的if…else…代码,导致维护和测试难度增大。
基于以上简单工厂模式的缺点,工厂方法模式在简单工厂模式进行改进。
二、工厂方法模式的类图:
看了类图,是不是感觉很简单,是的,工厂方法模式是比较简单,容易理解的一种模式。其中有几个元素。
1、抽象产品类,对产品的抽象,定义产品的一些共性。2、具体产品,具体产品的实现。3、抽象工厂类,定义具体工厂类该实现的方法。4、具体工厂类,实现创建产品的方法。
相比静态工厂模式,工厂模式为每个产品添加自己的工厂类。这样每个产品的创建都在自己的工厂类内实现,这样就分离了各个产品创建混杂在一起,从而更容易测试,也减低了静态工厂模式下,单一工厂类的职责和复杂度。同时,每创建新产品,只需新增产品及产品对应的工厂类,而无需修改其他工厂类,这就符合了“开闭原则”。使得代码的结构,各产品更清晰,更适合阅读。
三、例子。
我们在开发中免不了要打印日志,但日志的打印地点有许多不同的要求,比如说,我们在开发中,经常希望将日志打印在控制台,方便开发工程中的调试,而在上线后,我们希望通过文件来记录日志。甚至还有需要将日志输出成字节流的形式保存到其他地方的需求。不同的打印需要不同的类来实现。实现打印在不同地点的类就是我们这里工厂模式的产品,我们还需创建他们的工厂类,实现打印日志对象的创建。日志抽象类。
package product; public interface ILog { void writeLog(); }
将日志打印到文件,具体实现类。
package product; public class FileLog implements ILog { private String filePath; public FileLog(String filePath) { super(); this.filePath = filePath; } @Override public void writeLog() { // TODO Auto-generated method stub System.out.println("将日志打印到文件:"+filePath); } }
将日志打印到控制台,具体实现类。
package product; import java.util.Date; public class ConsoleLog implements ILog { private Date logDate; @Override public void writeLog() { // TODO Auto-generated method stub logDate = new Date(); System.out.println("日志打印到控制台,时间:"+logDate); } }
有了具体的产品,这是我们就需要创建他们的工厂类。
抽象工厂类:
package factory; import product.ILog; public interface IFactory { ILog createProduct(); }打印日志到文件的具体工厂类。
package factory; import product.FileLog; import product.ILog; public class FileLogFactory implements IFactory { @Override public ILog createProduct() { // TODO Auto-generated method stub ILog log = new FileLog("c:/log/test.log"); return log; } }
打印日志到控制台具体工厂类:
package factory; import product.ConsoleLog; import product.ILog; public class ConsoleLogFactory implements IFactory { @Override public ILog createProduct() { // TODO Auto-generated method stub return new ConsoleLog(); } }
这样我们就实现就工厂方法模式。具体的测试类如下。
import factory.ConsoleLogFactory; import factory.FileLogFactory; import factory.IFactory; import product.ConsoleLog; import product.ILog; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub IFactory factory = new FileLogFactory(); ILog fileLog = factory.createProduct(); fileLog.writeLog(); factory = new ConsoleLogFactory(); ILog consoleLog = factory.createProduct(); consoleLog.writeLog(); } }
这时如果我们想增加一个实现将日志输出成字节流是,我们只需新增日志的打印字节流实现,还有新增他的工厂类,无需修改其他任何的代码。
package product; public class StreamLog implements ILog { @Override public void writeLog() { // TODO Auto-generated method stub System.out.println("将日志输出成字节流的形式"); } }
package factory; import product.ILog; import product.StreamLog; public class StreamLogFactory implements IFactory{ @Override public ILog createProduct() { // TODO Auto-generated method stub return new StreamLog(); } }
这样,我们的简例就实现了工厂方法模式,是不是很简单啊,不知道你理解了么。
四、总结
接下来我们从优点还有缺陷中总结一下工厂方法模式。优点
1、工厂方法模式同简单工厂方法模式一样,实现了对客户端隐藏具体对象创建的具体细节,客户端不需要知道对象创建的过程,只需要知道通过工厂类即可创建具体的产品。
2、工厂类完全符合开源封闭原则,各产品直接没有耦合,新增产品方便,而且易于测试。
缺点
1、每新增一个产品,就得对应着新增一个工厂类,这样就会造成需新建的类比较多。
相关文章推荐
- Java设计模式(一) 设计模式初探——简单工厂和工厂方法模式
- 设计模式初探-工厂方法模式(Factory Method)
- 设计模式初探-工厂方法模式
- 设计模式初探-工厂方法模式
- 设计模式--工厂方法模式(Factory Method)
- 一起学Java设计模式--工厂方法模式(不在23种设计模式之内)
- 设计模式 - 工厂方法模式
- 设计模式初探(一)「适配器模式」
- Ruby中使用设计模式中的简单工厂模式和工厂方法模式
- .NET设计模式(5):工厂方法模式(Factory Method)(转)
- .NET设计模式(2): 工厂方法模式
- Android设计模式之 工厂方法模式
- 设计模式——工厂方法模式
- 【设计模式】初探
- 【设计模式学习】工厂方法模式
- 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)
- 设计模式:(1)工厂方法模式(Factory Method)
- 设计模式初探-桥接(Bridge)模式
- 设计模式初探-代理模式(PROXY)
- 设计模式初探-Prototype模式