在开发一款游戏时,我们需要开发按钮Button及展板Board等组件,我们有多种风格Ligth或Dark,不同风格下组件的颜色、形状也不相同。如果按照工厂方法模式,则设计如下:
图 工厂方法模式实现上述需求
以上方法存在两个问题: 1) Factory的数量过多,系统变得更加臃肿;2)不能保证同风格下,生成一致的组件。比如在开发中,可能会出现LightButton + DarkBoard的组合。
1 抽象工厂
1.1 产品族与产品等级结构
图 apple产品系列
在每年apple公司都几乎会推出系列产品,比如2022年推出的iPhone 14与iPad 十代,这属于一个产品族。而 2010年推出 iphone 4 及 2022年推出iPhone 14,这属于一个产品等级结构。
1.2 抽象工厂模式概述
为创建一组对象提供了一组解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,而是创建一族产品。
图 抽象工厂模式
AbstractProductA、AbstractProductB: 产品族的产品抽象。
ProductA1、ProductA2等:产品族中具体的产品。
Factory:抽象工厂,声名了一组用于创建一族产品的方法,每个方法对应一种产品。
ConcreteFactory1:具体工厂,实现了创建产品族的方法,用于创建某一等级的产品族。
public interface Board {
}public class DarkBoard implements Board{
}public class LightBoard implements Board{
}public interface Button {
}public class DarkButton implements Button{
}public class LightButton implements Button{
}public interface AbstractFactory {Button createButton();Board createBoard();}public class DarkFactory implements AbstractFactory{@Overridepublic Button createButton() {return new DarkButton();}@Overridepublic Board createBoard() {return new DarkBoard();}
}public class LightFactory implements AbstractFactory {@Overridepublic Button createButton() {return new LightButton();}@Overridepublic Board createBoard() {return new LightBoard();}}/*** 在开发一款游戏时,我们需要开发按钮Button及展板Board等组件,* 我们有多种风格Ligth或Dark,不同风格下组件的颜色、形状也不相同。*/
public class Client {public static void main(String[] args) {AbstractFactory factory = null;factory = new DarkFactory();Board board = factory.createBoard();Button button = factory.createButton();System.out.println(button);System.out.println(board);}}
2 优缺点
优点:
1)隔离了类的实例化过程,使得客户并不需要知道怎么创建。
2)当一个产品族的多个对象被设计成一起工作时,能保证客户端始终只使用同一个产品族的对象。
3)增加新的产品族方便,符合开闭原则。
缺点:
1)往产品族中添加新的产品麻烦,需要对原有系统进行大量修改,违背了开闭原则。
3 适用场景
- 系统中有多于一个的产品族需要创建且产品族群稳定,不会向族群再添加新的产品;
- 需保证统一产品族的产品有共同约束时。