任何可以产生对象的方法和类从广泛的意义上来说都可以被称为工厂,为什么有了 new 方法还需要专门的工厂设计模式呢?这是因为工厂设计模式非常灵活,可以控制对象产生的过程,不论是给对象添加上修饰还是权限控制等的操作都非常方便灵活======
工厂设计模式的前世今生
工厂设计模式一开始只有两种,一种是工厂方法(factory method);一种是抽象工厂(abstract factory)。但是后面又有人给工厂设计模式添加了额外两种设计模式,一种是简单工厂(simple factory),一种是静态工厂(static factory),最简单的静态工厂就是单例,将工厂设置为静态的类,没有什么值得单独讲解的
从交通工具说起
我们选择出行可以有很多的交通工具,每当我们想要使用交通工具的时候,我们就可以将之new出来
public interface Movable {
public void run();
}
public class Car implements Movable {
@Override
public void run() {
System.out.println("汽车启动......");
}
}
public class plain implements Movable {
@Override
public void run() {
System.out.println("飞机启动......");
}
}
public class Main {
public static void main(String[] args) {
Movable car = new Car();
Movable plain = new Plain();
car.run();
plain.run();
}
}
- 这样的写法虽然交通工具制作出来了,但是想要给交通工具添加上一些修饰,例如喷个漆,装个最新引擎就会变得非常麻烦,使得代码变得杂乱
- 这个时候,我们就可以使用工厂设计模式来改造这个 “交通工具生产工厂” 了
简单工厂(simple factory)
public class SimpleMovableFactory {
public static final SimpleMovableFactory INSTANCE = new SimpleMovableFactory();
private SimpleMovableFactory() {
}
public Movable createCar(){
System.out.println("准备喷漆");
Movable car = new Car();
System.out.println("给汽车涂喷漆");
return car;
}
public Movable createPlain(){
System.out.println("准备引擎");
Movable plain = new Plain();
System.out.println("给飞机换引擎");
return plain;
}
}
public class Main {
public static void main(String[] args) {
Movable car = SimpleMovableFactory.INSTANCE.createCar();
Movable plain = SimpleMovableFactory.INSTANCE.createPlain();
car.run();
plain.run();
}
}
- 通过这样的方法,我们就可以比较简洁有序地更换汽车的喷漆,飞机引擎,不会在主方法中写上各种各样的代码,规范了代码
- 虽然这样完成了工厂类的部分需求,但是如果我想给汽车更换引擎,而不是给汽车更换涂漆,那么我们就需要在这个工厂类里面写上一个写的工厂,这样违背了“对修改关闭,对扩展开放”的开闭原则,于是我们将每一个小工厂拆分出来,独立成一个工厂,这样就是工厂方法(factory method)
工厂方法(factory method)
public class GreatEngineCarFactory {
public static Movable create(){
System.out.println("准备跑车引擎");
Movable car = new Car();
System.out.println("给车换上跑车引擎");
return car;
}
}
public class PinkCarFactory {
public static Movable create(){
System.out.println("准备粉色涂漆");
Movable car = new Car();
System.out.println("给车涂上粉色涂漆");
return car;
}
}
public class Main {
public static void main(String[] args) {
Movable movable = PinkCarFactory.create();
Movable movable1 = GreatEngineCarFactory.create();
System.out.println("粉色汽车准备");
movable.run();
System.out.println("======");
System.out.println("跑车引擎汽车准备");
movable1.run();
}
}
- 从工厂方法我们可以看出来,这个方法比简单工厂更加优秀,如果我们需要添加新的工厂的话,我们就只需要通过编写新的工厂方法就可以,不需要破坏“开闭原则”
- 工厂方法有一个缺点,如果想要生产的种类太多,就有可能产生类爆炸现象
- 假如我有一个游戏,这个游戏里面每一个角色都有海陆空三种交通工具,每当我要出一组皮肤的时候,我都需要写至少三个工厂类来制作三个不同的皮肤,但是这样的成本太高了,为此,我们可以选择一个新的工厂策略抽象工厂
抽象工厂(abstract factory)
/**抽象工厂的父类**/
public abstract class AbstractMovableFactory {
public abstract Runnable createRunnable();
public abstract Flyable createFlyable();
public abstract Swimable createSwimable();
}
/**现代抽象工厂,可以制作出现代的交通工具**/
public class ModernMovableFactory extends AbstractMovableFactory {
@Override
public Runnable createRunnable() {
Runnable car = new Car();
return car;
}
@Override
public Flyable createFlyable() {
Flyable plain = new Plain();
return plain;
}
@Override
public Swimable createSwimable() {
Swimable submarine = new Submarine();
return submarine;
}
}
/**修仙工厂,可以制作出修仙世界的交通工具**/
public class XiuXianMovableFactory extends AbstractMovableFactory {
@Override
public Runnable createRunnable() {
return new Horse();
}
@Override
public Flyable createFlyable() {
return new FeiJian();
}
@Override
public Swimable createSwimable() {
return new JiaoLong();
}
}
/**我们只需要改变工厂,就可以制作出一套不同的交通工具**/
public class Main {
public static void main(String[] args) {
AbstractMovableFactory factory = new ModernMovableFactory();
/*AbstractMovableFactory factory = new XiuXianMovableFactory();*/
Flyable flyable = factory.createFlyable();
Runnable runnable = factory.createRunnable();
Swimable swimable = factory.createSwimable();
flyable.fly();
runnable.run();
swimable.swim();
}
}
- 我们发现,通过抽象工厂,我们可以一次性扩展一整个产品组,可以避免工厂方法有可能出现的类爆炸现象
抽象工厂 Vs 工厂方法
- 抽象工厂可以以产品组为单位进行扩展,每一次扩展都是一阵套的扩展
- 工厂方法更加的灵活,可以选择不同的产品进行扩展
- 抽象工厂每次扩展都是以产品组为单位扩展,一旦你的产品组的格式固定,那么这个这个产品组就不能轻易地添加新产品,添加新产品的代价极大
- 工厂方法在面临大量扩展的情况下有可能会出现类爆炸情况
抽象工厂和工厂方法之间各有优劣,没有哪一个是绝对优于另一个的,不同的工厂模式选择要看具体生产环境