【软考设计模式】抽象工厂模式:产品族构建与代码填空精讲

【软考设计模式】抽象工厂模式:产品族构建与代码填空精讲
软考设计模式系列第 2 篇。上一篇我们聊了简单工厂模式——用一个工厂类根据参数按需分配具体产品。但简单工厂有个局限它只能生产单一产品等级比如只生产按钮或只生产文本框。如果系统需要同时生产一组配套的产品比如 Win 风格的按钮 Win 风格的文本框或 Mac 风格的按钮 Mac 风格的文本框简单工厂就力不从心了。这时抽象工厂模式登场。一、模式定义抽象工厂模式Abstract Factory Pattern是一种创建型设计模式它为创建一组相关或相互依赖的对象提供一个接口而且无需指定它们的具体类。通俗地说抽象工厂不生产单个产品它生产整套产品族。1.1 核心概念产品族 vs 产品等级概念含义举例产品等级结构同一类产品的继承结构按钮 ← Win按钮 / Mac按钮产品族同一具体工厂生产的所有产品Win工厂Win按钮 Win文本框 Win组合框抽象工厂解决的核心问题是保证同一个产品族中的对象被一起使用避免 Windows 按钮配 Mac 文本框这种混搭问题。二、UML 类图与角色┌─────────────────────┐ │ interface │ │ AbstractFactory │ │ createButton() │ │ createTextField() │ └──────────┬──────────┘ │ ┌──────┴──────┐ ▼ ▼ ┌───────────┐ ┌───────────┐ │ WinFactory│ │ MacFactory│ │ │ │ │ └────┬──────┘ └─────┬─────┘ │ │ ▼ ▼ ┌─────────────┐ ┌─────────────┐ │interface│ │interface│ │ Button │ │ TextField │ │ draw() │ │ display() │ └──────┬──────┘ └──────┬──────┘ │ │ ┌──┴──┐ ┌──┴──┐ ▼ ▼ ▼ ▼ ┌──────┐┌──────┐ ┌─────┐┌─────┐ │WinBtn││MacBtn│ │WinTF││MacTF│ └──────┘└──────┘ └─────┘└─────┘角色说明角色职责AbstractFactory抽象工厂接口声明创建各个产品的方法ConcreteFactory具体工厂如 WinFactory、MacFactory实现抽象工厂接口生产同一产品族的所有对象AbstractProduct抽象产品接口如 Button、TextFieldConcreteProduct具体产品如 WinButton、MacButtonClient客户端通过抽象工厂和抽象产品接口操作不依赖具体类三、Java 代码实现以跨平台 UI 组件库为例实现 Windows 和 Mac 两个产品族。3.1 抽象产品接口// 抽象产品按钮 public interface Button { void draw(); } // 抽象产品文本框 public interface TextField { void display(); }3.2 具体产品Windows 族public class WinButton implements Button { Override public void draw() { System.out.println(绘制 Windows 风格按钮); } } public class WinTextField implements TextField { Override public void display() { System.out.println(显示 Windows 风格文本框); } }3.3 具体产品Mac 族public class MacButton implements Button { Override public void draw() { System.out.println(绘制 Mac 风格按钮); } } public class MacTextField implements TextField { Override public void display() { System.out.println(显示 Mac 风格文本框); } }3.4 抽象工厂public interface GUIFactory { Button createButton(); TextField createTextField(); }3.5 具体工厂public class WinFactory implements GUIFactory { Override public Button createButton() { return new WinButton(); } Override public TextField createTextField() { return new WinTextField(); } } public class MacFactory implements GUIFactory { Override public Button createButton() { return new MacButton(); } Override public TextField createTextField() { return new MacTextField(); } }3.6 客户端代码public class Client { public static void main(String[] args) { // 通过配置或参数决定使用哪个产品族 String osType Win; // 或 Mac GUIFactory factory; if (osType.equals(Win)) { factory new WinFactory(); } else { factory new MacFactory(); } // 客户端只依赖抽象接口 Button btn factory.createButton(); TextField tf factory.createTextField(); btn.draw(); tf.display(); // 输出绘制 Windows 风格按钮 // 显示 Windows 风格文本框 } }四、软考代码填空常见考法软考下午题中抽象工厂模式通常以代码填空形式出现重点考察以下位置典型填空点 1抽象工厂接口声明public interface GUIFactory { Button (1); // 创建按钮 TextField (2); // 创建文本框 }答案(1) createButton()(2) createTextField()典型填空点 2具体工厂实现public class WinFactory implements GUIFactory { public Button createButton() { return (3); // 填空 } }答案(3) new WinButton()典型填空点 3客户端依赖关系public class Client { private (4) factory; // 声明类型 private Button btn; public Client((5) factory) { // 参数类型 this.factory factory; } }答案(4) GUIFactory(5) GUIFactory软考核心原则客户端应依赖抽象接口GUIFactory / Button而非具体类WinFactory / WinButton。五、抽象工厂 vs 工厂方法 vs 简单工厂表格维度简单工厂工厂方法抽象工厂产品数量单一产品等级单一产品等级多个产品等级产品族工厂数量一个工厂类一个产品对应一个工厂一个产品族对应一个工厂扩展性新增产品需改工厂新增产品等级只需加工厂新增产品族只需加工厂新增产品等级需改所有工厂复杂度低中高软考考频中高高关键区别记忆口诀工厂方法一个工厂造一种东西的不同款式抽象工厂一个工厂造一套东西的配套款式。六、优缺点分析优点产品族一致性同一工厂生产的对象一定是兼容的不会出现风格混搭。隔离具体类客户端只依赖抽象接口符合依赖倒置原则。易于切换产品族将WinFactory换成MacFactory整套 UI 风格统一切换。缺点扩展产品等级困难如果要在产品族中新增下拉框ComboBox需要修改所有具体工厂类WinFactory、MacFactory...违反开闭原则。类数量膨胀N 个产品族 × M 个产品等级 大量类文件。七、适用场景系统需要独立于产品的创建、组合和表示如跨平台 UI 框架。系统需要由多个产品族中的一个来配置如不同数据库厂商MySQL 族 / Oracle 族。需要强调一系列相关产品的配套使用如游戏开发中的精灵族精灵建筑 精灵兵种 精灵魔法。八、软考备考要点总结表格考点要点定义填空为创建一组相关或相互依赖的对象提供接口无需指定具体类角色识别能区分 AbstractFactory / ConcreteFactory / AbstractProduct / ConcreteProduct代码填空工厂返回值类型为具体产品客户端声明类型为抽象产品/抽象工厂与工厂方法区别抽象工厂处理产品族多个产品等级工厂方法处理单一产品等级扩展性陷阱新增产品族容易加工厂新增产品等级难改所有工厂——这是软考常考的缺点九、完整记忆图抽象工厂 GUIFactory │ ┌───────┴───────┐ ▼ ▼ WinFactory MacFactory ← 产品族容易扩展新增 LinuxFactory │ │ ├─Button ├─Button │ │ │ │ │ WinButton │ MacButton │ │ ├─TextField ├─TextField │ │ │ │ │ WinTF MacTF │ └─ComboBox? ← 新增产品等级困难所有工厂都要改十、结语抽象工厂模式是软考下午题中出镜率极高的创建型模式。掌握它的关键在于理解产品族这个概念——它不是生产一个对象而是生产一套配套对象。记住它的优缺点扩展产品族易、扩展产品等级难分清它与工厂方法模式的边界代码填空时留意抽象类型声明具体类型实例化这一原则软考中遇到抽象工厂的题目就能从容应对。