一、什么是工厂模式?
工厂模式就是创建一个对象的工厂接口,创建对象不再是通过new这个对象来直接实现,而是通过工厂来对对象进行创建。应用工厂模式可以降低系统间的耦合度。
工厂模式中一般有以下角色:
1. 抽象产品类:是具体产品对象的基类
2. 具体产品类:实现了抽象产品类接口,每一个具体产品类都会对应一个工厂
3. 抽象工厂:工厂模式的基类,定义了工厂类必须实现的接口
4. 具体工厂:实现了抽象工厂类的接口,是与客户端直接交互的类,负责具体的产品对象的创建
我们平时都是通过new来创建一个对象实例的,假设我们在多个方法中都对类A进行了实例化,而现在我们需要对A做一点改动,比如我们要修改A的构造方法的入参,那么接下来会发生什么?那就是我们需要修改所有实例化A类的代码,这个改动量无疑是巨大的,而且我们也不保证在改动的过程中不会出错。这样的一种对象创建模式无疑违反了设计模式中的“开放关闭原则”(即对扩展开放,对修改关闭)。这个时候应用工厂模式就是很合适的,对象实例是通过工厂来创建的,如果我们要修改或者扩展类A,我们不再需要修改所有实例化A的地方,而只是需要修改对应的工厂类即可。
工厂模式分有两种,简单工厂模式和工厂模式。简单工厂模式即静态工厂模式,是一个用来实例化目标类的静态类。工厂模式是一个具体工厂对应一个具体目标对象。
二、工厂模式框图
我们通过买包子这个例子来讲述下工厂模式在其中的应用,并比较下静态工厂和工厂模式。
先来看下静态工厂模式:
图1. 静态工厂模式框图
现在看下工厂模式:
图2. 工厂模式框图
三、工厂模式的具体代码
3.1 Bun接口,包子抽象类,内部有一个stuffing方法,显示是什么馅
package designpatterns.factory;
/**
* Created by Olive on 2017/12/18.
* 包子的接口
*/
public interface Bun {
// 显示是什么馅
void stuffing();
}
3.2 BunFactory接口,抽象包子工厂类,有一个getBun方法,返回一个包子实例
package designpatterns.factory;
/**
* Created by Olive on 2017/12/18.
* 抽象包子工厂接口
*/
public interface BunFactory {
Bun getBun();
}
3.3 BeefBun类,牛肉馅的包子,实现了Bun接口
package designpatterns.factory;
/**
* Created by Olive on 2017/12/18.
*/
public class BeefBun implements Bun{
public void stuffing() {
System.out.println("Beef Bun!");
}
}
3.4 PorkBun类,大肉馅(不清真 = =)的包子,实现了Bun接口
package designpatterns.factory;
/**
* Created by Olive on 2017/12/18.
* 猪肉包子类(Emmmm,一点都不清真)
*/
public class PorkBun implements Bun{
public void stuffing() {
System.out.println("Pork Bun!");
}
}
3.5 BeefBunFactory类,牛肉包子工厂,只做牛肉包子,实现了BunFactory接口
package designpatterns.factory;
/**
* Created by Olive on 2017/12/18.
*/
public class BeefBunFactory implements BunFactory{
public Bun getBun() {
return new BeefBun();
}
}
3.6 PorkBunFactory类,猪肉包子工厂,只做猪肉包子,实现了BunFactory接口
package designpatterns.factory;
/**
* Created by Olive on 2017/12/18.
*/
public class PorkBunFactory implements BunFactory{
public Bun getBun() {
return new PorkBun();
}
}
3.7 BunsStaticFactory,静态包子工厂,什么包子都做
package designpatterns.factory;
/**
* Created by Olive on 2017/12/18.
* 静态包子工厂
*/
public class BunsStaticFactory {
public static Bun getPorkBun(){
return new PorkBun();
}
public static Bun getBeefBun(){
return new BeefBun();
}
}
3.8 Client,客户端
package designpatterns.factory;
/**
* Created by Olive on 2017/12/18.
* 客户,来买包子
*/
public class Client {
public static void main(String[] args){
// 静态工厂
Bun pork = BunsStaticFactory.getPorkBun();
pork.stuffing();
Bun beef = BunsStaticFactory.getBeefBun();
beef.stuffing();
System.out.println("*******************");
// 普通工厂
Bun porkBun = new PorkBunFactory().getBun();
porkBun.stuffing();
Bun beefBun = new BeefBunFactory().getBun();
beefBun.stuffing();
}
}
3.8 结果
Pork Bun!
Beef Bun!
*******************
Pork Bun!
Beef Bun!
Process finished with exit code 0
四、一点小总结
静态工厂模式通过在工厂中建立静态方法来获得目标对象实例,但是静态工厂模式是不完全满足“开放关闭原则”的,例子中如果要增加一个“豆沙包”类,则需要在静态工厂类中增加“获取豆沙包”的方法。而工厂模式是完全满足“开放关闭原则”的,静态工厂模式只有一个工厂类,而工厂模式有一组实现了相同接口的工厂类。
从上述的类图中可以看到,在结构上来说,静态工厂模式更加简单,工厂模式的工厂类会随着产品种类的增多而增多,这会使系统中有很多个工厂类,使结构更加复杂。而在设计模式的角度来看,工厂模式具有相当好的扩展性。这两种模式各有千秋,需要根据实际情况来选用。