设计模式之工厂模式
鲁迅说程序设计的思想来源于生活 !!!工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式。该模式用于封装和管理对象的创建,是一种创建型模式。
简单工厂模式
先说下简单工厂模式,其实这个没啥好说的挺简单
将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来都相对容易。
例子
文件IO的操作我们会经常用得到吧,所以BufferedReader对象经常要创建的:
1
2// 创建一个BufferedReader对象
BufferedReader bf = new BufferedReader(new FileReader(new File("aa.txt")));你说麻烦吗?其实也不麻烦,就一行代码嘛,哪里麻烦了~如果不太熟悉IO流的同学就没有那么机灵了,创建一个BufferedReader可能就是以下的代码了:
1
2
3File file = new File("aa.txt");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);你说麻烦吗?其实也不麻烦,不就是三行代码嘛,哪里麻烦了~如果这个应用很多的类上都用到了BufferedReader对象的话,那每个类都写上这三行代码了。那你说麻烦吗?那肯定麻烦啊,还用想啊….
可以看出来,创建一个BufferReader对象里面需要一个FileReader对象,而FileReader对象又要File对象。那创建这个BufferReader对象还是比较麻烦的(代码上看不麻烦,从构造上看还是挺麻烦的)!
虽然比较麻烦,但我们还能用,能用就行!于是乎,我们就去写代码了,现在有三个类都要进行文件的读写操作,于是他们就有这样的代码:
1
2
3
4
5
6
7
8
9
10
11public class FileOperateA {
public static void main(String[] args) throws FileNotFoundException {
File file = new File("aa.txt");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
// 读写文件....
}
}此时:上头说,我要换成LineNumberReader来读写,有这个需求!那我们作为一个写代码的,能怎么办?很绝望也需要去完成呀。
- 不熟悉IDE的小伙子就一个一个将BufferedReader改成LineNumberReader,现在就3个类用到了BufferedReader,也就改6次而已。(ps:那如果很多地方都用到了呢?)
- 熟悉IDE的小伙子就全局替换重构,妥妥的!
哎,写个代码屁事真多…那有没有一种方法能够让创建对象变得简单而且修改对象时能很方便呢?
哎,工厂模式就行了。
我们可以
1
2
3
4
5
6
7
8
9
10
11
12public class Factory {
public static Reader use(String type){
Reader reader = null;
if (type == "Buffer"){
reader = new BufferedReader();
}else if (type == "Line"){
reader = new LineNumberReader();
}else {
return reader
}
}
}其中BufferedReader和LineNumberReader是Reader的子类。
1
2
3
4
5
6
7
8
9
10public class FileOperateA {
public static void main(String[] args) throws FileNotFoundException {
File file = new File("aa.txt");
FileReader fileReader = new FileReader(file);
Factroy f = new Factory;
f.use("Buffer")
// 读写文件....
}
}这时候修改的话只需要将f.use(“Buffer”)中的参数改为“Line”即可修改完毕。
在调用工厂类的工厂方法时,由于工厂方法是静态方法,使用起来很方便,可通过类名直接调用,而且只需要传入一个简单的参数即可,在实际开发中,还可以在调用时将所传入的参数保存在XML等格式的配置文件中,修改参数时无须修改任何源代码。
简单工厂模式最大的问题在于工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,这一点与开闭原则是相违背的。而且一旦工厂类中发生错误,会导致整个程序发生很大的破坏。
简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。
工厂方法模式
- 工厂方法模式又称为工厂模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
- 工厂方法模式包含四个角色:抽象产品是定义产品的接口,是工厂方法模式所创建对象的超类型,即产品对象的共同父类或接口;具体产品实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,它们之间往往一一对应;抽象工厂中声明了工厂方法,用于返回一个产品,它是工厂方法模式的核心,任何在模式中创建对象的工厂类都必须实现该接口;具体工厂是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户调用,返回一个具体产品类的实例。
- 工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。
- 工厂方法模式的主要优点是增加新的产品类时无须修改现有系统,并封装了产品对象的创建细节,系统具有良好的灵活性和可扩展性;其缺点在于增加新产品的同时需要增加新的工厂,导致系统类的个数成对增加,在一定程度上增加了系统的复杂性。
- 工厂方法模式适用情况包括:一个类不知道它所需要的对象的类;一个类通过其子类来指定创建哪个对象;将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。
代码演示
1 | //抽象产品类 |
抽象工厂模式:
抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂,非常适合解决两个维度的组合产品的构造问题,取其中一个维度作为产品族,另外一个维度作为产品族中具体的多个产品。
产品族是具有相同属性的同类型产品;如宝马车,宝马1系,宝马2系,都属于宝马;
由于产品族可能会有很多产品,这样的话如果按照工厂方法模式的写法,那样就需要每次添加一个产品类和工厂类;这样就会添加很多类文件,这里抽象工厂模式,其实就是将产品抽象成产品族,一个产品可能具有不同属性,这里工厂类只需要产品属性的共性抽象出来。
抽象工厂模式的构成
- 抽象工厂角色:是具体工厂角色必须实现的接口或者必须继承的父类。
- 具体工厂角色:继承抽象工厂类,实现创建对应的具体产品的对象。
- 抽象产品角色:它是具体产品继承的父类或者是实现的接口。这里抽象产品至少2个维度;
- 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。
1 | //抽象形状类 |
UML图如下:简单工厂、工厂方法、
个人总结
简单工厂模式是将new对象变成由工厂类中的方法进行创建对象,工厂方法模式,则在此基础之上抽象工厂概念,将工厂类抽象为接口,由子类来创建具体产品。而抽象方法对象再在此基础之上,再次增加抽象产品,解决产品的组合和构造问题。