在简单工厂模式和工厂方法模式中,针对的场景都是生产同类产品,比如菜品类,其中在工厂方法模式中,我们可以通过定义菜品工厂类接口,然后把具体的创建工作交给子类。如果是生产多种类的产品该怎么办呢?比如,我们新增饮品类,如果还是按照工厂方法模式,我们就需要再次创建饮品工厂类接口,然后交给子类去创建,最后业务类需要创建每一个具体饮品工厂对象。如果还需要新增其它品类,不仅会导致类数目的增加,还会增加业务层与底层代码的耦合性。
工厂方法模式是针对创建同一类产品的设计模式,而抽象工厂模式则是针对创建多种类产品的设计模式。抽象工厂模式的定义是:为一组相关或相互依赖的产品提供一个接口,无需指定它们的具体类。何为相关或相互依赖?首先,它们一定是不同的产品,比如汉堡属于菜品类,可乐属于饮品类;其次,它们都是快餐店必不可少的,所以它们是相关或相互依赖的,所以汉堡和可乐也被称为属于同一个产品族,其中产品族可以有很多个,KFC的汉堡和可乐属于KFC产品族,麦当劳的汉堡和可乐属于麦当劳产品族。接下来,我们将通过代码来介绍抽象工厂模式:
创建两种抽象产品,一般有多少种抽象产品,在抽象工厂接口中就有多少种创建产品的方法:
public interface IDishes {
void eat();
}
public interface IWater {
void drink();
}
创建产品的具体实现类:
public class KFCHamburger implements IDishes {
@Override
public void eat() {
System.out.println("KFC汉堡");
}
}
public class KFCCola implements IWater {
@Override
public void drink() {
System.out.println("KFC可乐");
}
}
创建一个抽象工厂接口,它提供了创建多种产品的方法:
public interface IFactory {
IDishes produceHamburger();
IWater produceCola();
}
创建抽象工厂的具体实现类:
public class KFCFactory implements IFactory {
@Override
public IWater produceCola() {
return new KFCCola();
}
@Override
public IDishes produceHamburger() {
return new KFCHamburger();
}
}
创建业务类Test:
public class Test {
public static void main(String[] args) {
IFactory kfcFactory = new KFCFactory();
kfcFactory.produceCola().drink();
kfcFactory.produceHamburger().eat();
}
}
在代码里,每一个产品族是实现了抽象工厂接口的实现类,比如KFCFactory类就是一个产品族。假如我们要新增一个麦当劳产品族,代码如下:
创建麦当劳汉堡和可乐:
public class McDonaldHamburger implements IDishes {
@Override
public void eat() {
System.out.println("McDonald汉堡");
}
}
public class McDonaldCola implements IWater {
@Override
public void drink() {
System.out.println("McDonald可乐");
}
}
创建麦当劳产品族工厂类:
public class McDonaldFactory implements IFactory {
@Override
public IDishes produceHamburger() {
return new McDonaldHamburger();
}
@Override
public IWater produceCola() {
return new McDonaldCola();
}
}
最后,在业务类中添加代码:
public class Test {
public static void main(String[] args) {
IFactory kfcFactory = new KFCFactory();
kfcFactory.produceCola().drink();
kfcFactory.produceHamburger().eat();
IFactory mcDonaldFactory = new McDonaldFactory();
mcDonaldFactory.produceCola().drink();
mcDonaldFactory.produceHamburger().eat();
}
}
原有的底层代码都没有修改,只是在业务类中新增了一个新的产品族,符合开闭原则,同时业务类中不必了解产品的创建细节。但是如果要新增一个产品种类的时候,就需要在抽象工厂接口中添加新的方法,其实现类也要修改,就不符合开闭原则了,这也是抽象工厂模式的一个弊端。