简单工厂
在介绍工厂方法和抽象工厂前,我们要先简单介绍一下简单工厂
老麻花准备在大学城开一家奶茶店,名字就叫麻花茶馆吧。因为一开始只有一家店,麻花可能采用简单工厂的模式进行开发:
先定义奶茶的接口:
public interface Tea {
void prepare();
void boil();
void pack();
}
建一个简单工厂,制造两款奶茶试试水:
class TeaA implements Tea {
@Override
public void prepare() {
System.out.println("prepare tea A");
}
@Override
public void boil() {
System.out.println("boil tea A");
}
@Override
public void pack() {
System.out.println("pack tea A");
}
}
class TeaB implements Tea {
@Override
public void prepare() {
System.out.println("prepare tea B");
}
@Override
public void boil() {
System.out.println("boil tea B");
}
@Override
public void pack() {
System.out.println("pack tea B");
}
}
public class SimpleTeaFactory {
public static Tea createTea(String type) {
Tea tea = null;
if (type.equals("A")) {
tea = new TeaA();
} else if (type.equals("B")) {
tea = new TeaB();
}
if (tea != null) {
tea.prepare();
tea.boil();
tea.pack();
}
return tea;
}
}
最后把奶茶店开到大学城:
public class TeaStore {
SimpleTeaFactory simpleTeaFactory;
public TeaStore(SimpleTeaFactory simpleTeaFactory) {
this.simpleTeaFactory = simpleTeaFactory;
}
public Tea orderTea(String type) {
return SimpleTeaFactory.createTea(type);
}
public static void main(String[] args) {
TeaStore teaStore = new TeaStore(new SimpleTeaFactory());
teaStore.orderTea("A");
teaStore.orderTea("B");
}
}
简单工厂存在的问题
虽然我们已经将产品、工厂、门店进行了分离。但如果我要开发一款新的品类(坤不离手),就需要在工厂类中新增if-else逻辑判断else if (type.equals("坤不离手"))
工厂方法
为了解决上面的问题,我们对工厂进行升级,创建一个抽象工厂类,定义创建奶茶的接口。对于每一个奶茶品类,我们都要实例化一个工厂类来制作该奶茶,这样我们就移除了简单工厂中的if-else逻辑判断
public interface AbstractTeaFactory {
public Tea createTea();
}
class TeaA implements Tea {
@Override
public void prepare() {
System.out.println("prepare TeaA");
}
@Override
public void boil() {
System.out.println("boil TeaA");
}
@Override
public void pack() {
System.out.println("pack TeaA");
}
}
class FactoryA implements AbstractTeaFactory {
@Override
public Tea createTea() {
Tea tea = new TeaA();
tea.prepare();
tea.boil();
tea.pack();
return tea;
}
}
class TeaB implements Tea {
@Override
public void prepare() {
System.out.println("prepare TeaB");
}
@Override
public void boil() {
System.out.println("boil TeaB");
}
@Override
public void pack() {
System.out.println("pack TeaB");
}
}
class FactoryB implements AbstractTeaFactory {
@Override
public Tea createTea() {
Tea tea = new TeaB();
tea.prepare();
tea.boil();
tea.pack();
return tea;
}
}
当我们需要添加一个新品类时,只需要实例化一个新的工厂类,实现新品类的制作。 接下来,我们升级后的奶茶店就可以开业了:
public class TeaStore {
public static void main(String[] args) {
Tea teaA = new FactoryA().createTea();
Tea teaB = new FactoryB().createTea();
}
}
工厂方法的缺点
虽然工厂方法通过实例化工厂类,实现createTea方法,生成具体的产品,避免了简单工厂中的if-else判断。但随着业务的增加,系统中的类可能会成倍增加,增加代码的复杂性。
抽象工厂
随着麻花茶馆的生意越做越好,我们决定出海!出海的第一站就是印度。但印度老哥干净又卫生,总有些特殊需求。如果把针对印度老哥的工厂都开在国内,工厂太多了,公司不好管理。因此,我们决定,把针对印度老哥的工厂与国内的工厂区分开来,打包运往印度。
我们先想好印度和国内都会生产的品类:
public interface BubbleTea {
void prepare();
void boil();
void pack();
}
public interface FruitTea {
void prepare();
void pack();
}
修改抽象工厂,国内工厂和印度工厂都是从同一个模子里造出来的
public interface AbstractTeaFactory {
public BubbleTea createBubbleTea();
public FruitTea createFruitTea();
}
国内的工厂有自己的特色:
class PutianBubbleTea implements BubbleTea{
@Override
public void prepare() {
System.out.println("Prepare PutianBubbleTea");
}
@Override
public void boil() {
System.out.println("Boiling PutianBubbleTea");
}
@Override
public void pack() {
System.out.println("Pack PutianBubbleTea");
}
}
class PutianFruitTea implements FruitTea {
@Override
public void prepare() {
System.out.println("Prepare PutianFruitTea");
}
@Override
public void pack() {
System.out.println("Pack PutianFruitTea");
}
}
public class PutianTeaFactory implements AbstractTeaFactory{
@Override
public BubbleTea createBubbleTea() {
BubbleTea bubbleTea = new PutianBubbleTea();
bubbleTea.prepare();
bubbleTea.boil();
bubbleTea.pack();
return bubbleTea;
}
@Override
public FruitTea createFruitTea() {
FruitTea fruitTea = new PutianFruitTea();
fruitTea.prepare();
fruitTea.pack();
return fruitTea;
}
}
印度老哥的工厂也有自己的特色:
class IndiaBubbleTea implements BubbleTea {
@Override
public void prepare() {
System.out.println("Preparing India Bubble Tea");
System.out.println("干净又卫生");
}
@Override
public void boil() {
System.out.println("Boiling India Bubble Tea");
System.out.println("干净又卫生");
}
@Override
public void pack() {
System.out.println("Packing India Bubble Tea");
System.out.println("干净又卫生");
}
}
class IndiaFruitTea implements FruitTea {
@Override
public void prepare() {
System.out.println("Preparing India Fruit Tea");
System.out.println("干净又卫生");
}
@Override
public void pack() {
System.out.println("Packing India Fruit Tea");
System.out.println("干净又卫生");
}
}
public class IndiaTeaFactory implements AbstractTeaFactory {
@Override
public BubbleTea createBubbleTea() {
BubbleTea bubbleTea = new IndiaBubbleTea();
bubbleTea.prepare();
bubbleTea.boil();
bubbleTea.pack();
return bubbleTea;
}
@Override
public FruitTea createFruitTea() {
FruitTea fruitTea = new IndiaFruitTea();
fruitTea.prepare();
fruitTea.pack();
return fruitTea;
}
}
最后,开业大吉!
public class TeaStore {
public static void main(String[] args) {
new PutianTeaFactory().createBubbleTea();
new PutianTeaFactory().createFruitTea();
System.out.println("============================");
new IndiaTeaFactory().createBubbleTea();
new IndiaTeaFactory().createFruitTea();
}
}
总结
- 简单工厂:适用业务简单,产品比较固定,不会经常改变的工厂类
- 工厂方法:实例化工厂类,通过实现createTea方法,生成具体的产品。可扩展性强于简单工厂,但随着业务的增加,系统中的类可能会成倍增加,使代码变得复杂。
- 抽象工厂:针对工厂方法类成倍增加的问题,通过分组的方式减少工厂类的数量。但凡事都有代价,抽象工厂通过分组减少了工厂类的数量,但在分组中扩展产品就会变得比较困难。