1.概念
核心思想: 不关心实现,只要给配置,得到结果! 定义统一引擎的方法,让它们各自实现
将对象的创建逻辑与使用逻辑分离。客户端无需关心对象的具体实现,只需通过工厂接口获取所需对象。
-
类型:
- 简单工厂:一个静态方法创建所有对象(非严格设计模式)
- 工厂方法:定义抽象工厂接口,子类决定实例化哪个类
- 抽象工厂:创建相关对象族(如不同UI风格控件)
注意: 创建对象有很多种方式,反射也是,所以下面也是工厂模式!
// 运行时实例化拦截器
IInterceptor interceptor = interceptorClass.newInstance(); // 工厂模式创建实例
这行代码借助反射机制来创建对象实例,就像是一个简单工厂,依据传入的类名生成对应的对象。
2.在Android源码中的应用场景
2.1 BitmapFactory.decodeXxx()
根据资源/流类型自动创建Bitmap对象,隐藏解码细节:
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img);
2. 2 LayoutInflater
模式类型:工厂方法模式
作用:解析XML布局文件,根据标签名(如 <TextView>)创建对应的View对象。子类可通过 setFactory() 自定义View创建逻辑(如换肤功能)。
源码调用:
View view = LayoutInflater.from(context).inflate(R.layout.item_view, parent, false);
3.UML图
4.语音项目的例子和没用设计模式的对比
场景:处理不同云端语音识别引擎(讯飞语音/百度语音)
4.1 没有使用工厂模式的实现
// 讯飞实现类(需了解具体构造细节)
public class IflytekRecognizerWithout {
private String appId;
public void setAppId(String id) { this.appId = id; }
public void connectServer() { /* 建立讯飞专有连接 */ }
public String recognize(byte[] data) {
// 调用讯飞SDK
return "Iflytek:识别结果";
}
}
// 百度实现类(接口不一致)
public class BaiduRecognizerWithout {
private String apiKey;
public void setApiKey(String key) { this.apiKey = key; }
public void authToken() { /* 百度鉴权流程 */ }
public String processAudio(byte[] data) {
// 调用百度SDK
return "Baidu:识别结果";
}
}
// 客户端代码直接依赖具体实现类
public class SpeechClient {
// ==== 使用示例 ====
public static void main(String[] args) {
SpeechClient client = new SpeechClient();
byte[] audioData = null;
// 调用讯飞(配置参数可抽离到配置文件)
client.recognize("Iflytek", "APP_ID=123456", audioData);
// 调用百度(客户端代码无需修改)
client.recognize("Baidu", "API_KEY=7890abc", audioData);
}
public void recognize(String engineType, byte[] audioData) {
if ("Iflytek".equals(engineType)) {
// 直接实例化讯飞引擎
IflytekRecognizerWithout iflytek = new IflytekRecognizerWithout();
iflytek.setAppId("your_iflytek_id");
iflytek.connectServer();
String result = iflytek.recognize(audioData);
System.out.println("讯飞结果: " + result);
} else if ("Baidu".equals(engineType)) {
// 直接实例化百度引擎
BaiduRecognizerWithout baidu = new BaiduRecognizerWithout();
baidu.setApiKey("your_baidu_key");
baidu.authToken();
String result = baidu.processAudio(audioData);
System.out.println("百度结果: " + result);
} else {
throw new IllegalArgumentException("不支持的引擎");
}
}
private final RecognizerFactory factory = new RecognizerFactory();
public void recognize(String engineType, String config, byte[] audioData) {
// 通过工厂创建实例(不感知具体类)
SpeechRecognizer recognizer = factory.createRecognizer(engineType);
// 统一接口操作
recognizer.initialize(config);
String result = recognizer.recognize(audioData);
System.out.println(engineType + "结果: " + result);
}
}
4.2 使用工厂模式的实现
// ===== 1. 统一定义产品接口 =====
public interface SpeechRecognizer {
void initialize(String config); // 统一初始化
String recognize(byte[] audioData); // 统一识别方法
}
public class BaiduRecognizer implements SpeechRecognizer {
private String apiKey;
@Override
public void initialize(String config) {
this.apiKey = config;
this.authToken();
}
private void authToken() { /* 百度鉴权 */ }
@Override
public String recognize(byte[] audioData) {
// 调用百度SDK(实际代码)
return "Baidu:识别结果";
}
}
// ===== 2. 实现具体产品 =====
public class IflytekRecognizer implements SpeechRecognizer {
private String appId;
@Override
public void initialize(String config) {
this.appId = config;
this.connectServer();
}
private void connectServer() { /* 讯飞专有连接 */ }
@Override
public String recognize(byte[] audioData) {
// 调用讯飞SDK(实际代码)
return "Iflytek:识别结果";
}
}
public class AliyunRecognizer implements SpeechRecognizer{
@Override
public void initialize(String config) {
}
@Override
public String recognize(byte[] audioData) {
return "";
}
}
// ===== 3. 工厂类封装创建逻辑 =====
public class RecognizerFactory {
public SpeechRecognizer createRecognizer(String engineType) {
switch (engineType) {
case "Iflytek":
return new IflytekRecognizer();
case "Baidu":
return new BaiduRecognizer();
// 新增引擎只需扩展此处
case "Aliyun":
return new AliyunRecognizer();
default:
throw new IllegalArgumentException("未知引擎类型");
}
}
}
4.3 扩展新引擎实战(阿里云)
只需新增两个类,无需修改已有客户端代码:
// 1. 实现产品接口
public class AliyunRecognizer implements SpeechRecognizer {
@Override
public void initialize(String config) {
// 阿里云特有的初始化
}
@Override
public String recognize(byte[] audioData) {
return "Aliyun:识别结果";
}
}
// 2. 扩展工厂类
public class RecognizerFactory {
public SpeechRecognizer createRecognizer(String engineType) {
switch (engineType) {
// ... 已有引擎
case "Aliyun": // 新增分支
return new AliyunRecognizer();
default: ...
}
}
}
4.4 处理不同云端语音识别引擎的架构图
✅ 工厂模式的核心优势
| 维度 | 无工厂模式 | 工厂模式 |
|---|---|---|
| 耦合度 | 客户端与具体引擎强耦合 | 客户端只依赖抽象接口 |
| 扩展性 | 新增引擎需修改所有调用点 | 只需扩展工厂类,符合开闭原则 |
| 代码复用 | 重复初始化逻辑(每个引擎单独处理) | 初始化逻辑封装在具体产品类中 |
| 维护成本 | 修改引擎需全局搜索调用代码 | 只需修改具体产品类或工厂类 |
| 接口规范 | 不同引擎接口不一致 | 通过接口强制统一行为 |
5.优点
- 解耦:对象创建与使用分离,降低模块耦合度
- 可扩展性:新增产品类型只需扩展工厂,符合开闭原则
- 代码复用:集中管理对象创建逻辑(如配置初始化)
- 可维护性:修改具体类不影响调用方(如替换Google SDK为阿里云SDK)
6.和相识的设计模式的区别
工厂模式和哪个模式比较像呢? 策略模式
对比下面2份代码,是不是发现都是if else 的结构!他们各自到底用的什么设计模式!
Arounter中的源码: 策略模式
if (obj instanceof IRouteRoot) {
registerRouteRoot((IRouteRoot) obj);
} else if (obj instanceof IProviderGroup) {
registerProvider((IProviderGroup) obj);
} else if (obj instanceof IInterceptorGroup) {
registerInterceptor((IInterceptorGroup) obj);
} else {
logger.info(TAG, "register failed, class name: " + className
+ " should implements one of IRouteRoot/IProviderGroup/IInterceptorGroup.");
}
上面的语音项目的例子:工厂模式
public SpeechRecognizer createRecognizer(String engineType) {
switch (engineType) {
case "Iflytek":
return new IflytekRecognizer();
case "Baidu":
return new BaiduRecognizer();
// 新增引擎只需扩展此处
case "Aliyun":
return new AliyunRecognizer();
default:
throw new IllegalArgumentException("未知引擎类型");
}
}
6.1 相同点: 条件分发的核心结构相同
// 策略模式的条件分支
if (obj instanceof IRouteRoot) {
// 处理路由表
} else if (obj instanceof IProviderGroup) {
// 处理服务
}
// 工厂模式的条件分支
switch (engineType) {
case "Iflytek": return new IflytekRecognizer();
case "Baidu": return new BaiduRecognizer();
}
- 都使用 条件判断(if-else 或 switch-case)作为核心分发机制
6.1.2 不同点分析:
策略模式特征分析:
-
核心目的:行为选择 - 根据输入对象的类型选择不同的处理算法
-
关注点:运行时行为决策(如何处理对象)
-
模式结构:
-
多种策略接口:
IRouteRoot,IProviderGroup,IInterceptorGroup -
策略实现:各种注册方法(
registerRouteRoot,registerProvider等)
-
工厂模式特征分析:
-
核心目的:对象创建 - 封装对象的实例化过程
-
关注点:创建何种对象(而非如何处理)
-
模式结构:
-
抽象产品接口:
SpeechRecognizer -
具体产品:
IflytekRecognizer,BaiduRecognizer等 -
工厂类:封装创建逻辑
-
核心区别对比
| 维度 | 策略模式 | 工厂模式 |
|---|---|---|
| 主要目的 | 选择算法,不同的实现 | 创建对象实例 |
| 核心关注点 | "怎么做"(行为实现) | "是什么"(对象类型) |
| 输入输出 | 不同的接口 | 相同的接口 |
6.2 简单工厂, 工厂方法, 抽象工厂 它们的区别是什么,用一个demo说明下
6.2.1 简单工厂模式 (Simple Factory)
核心特点:一个工厂类创建所有类型产品
// 产品接口
interface Button {
void render();
}
interface TextField {
void display();
}
// 具体产品
class LightButton implements Button {
public void render() { System.out.println("渲染浅色按钮"); }
}
class DarkButton implements Button {
public void render() { System.out.println("渲染深色按钮"); }
}
class LightTextField implements TextField {
public void display() { System.out.println("显示浅色文本框"); }
}
class DarkTextField implements TextField {
public void display() { System.out.println("显示深色文本框"); }
}
// 简单工厂 - 创建所有UI组件
class SimpleUIFactory {
public static Button createButton(String theme) {
return switch (theme) {
case "light" -> new LightButton();
case "dark" -> new DarkButton();
default -> throw new IllegalArgumentException("未知主题");
};
}
public static TextField createTextField(String theme) {
return switch (theme) {
case "light" -> new LightTextField();
case "dark" -> new DarkTextField();
default -> throw new IllegalArgumentException("未知主题");
};
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
Button btn = SimpleUIFactory.createButton("light");
TextField field = SimpleUIFactory.createTextField("light");
btn.render(); // 输出:渲染浅色按钮
field.display(); // 输出:显示浅色文本框
}
}
缺点:新增主题需要修改工厂类(违反开闭原则)
6.2.2. 工厂方法模式 (Factory Method)
核心特点:每个产品有专属工厂,通过子类决定实例化
// 抽象工厂接口
interface ButtonFactory {
Button createButton();
}
interface TextFieldFactory {
TextField createTextField();
}
// 具体工厂
class LightButtonFactory implements ButtonFactory {
public Button createButton() { return new LightButton(); }
}
class DarkButtonFactory implements ButtonFactory {
public Button createButton() { return new DarkButton(); }
}
class LightTextFieldFactory implements TextFieldFactory {
public TextField createTextField() { return new LightTextField(); }
}
class DarkTextFieldFactory implements TextFieldFactory {
public TextField createTextField() { return new DarkTextField(); }
}
// 客户端使用
public class Client {
public static void main(String[] args) {
ButtonFactory btnFactory = new LightButtonFactory();
TextFieldFactory fieldFactory = new LightTextFieldFactory();
Button btn = btnFactory.createButton();
TextField field = fieldFactory.createTextField();
btn.render(); // 输出:渲染浅色按钮
field.display(); // 输出:显示浅色文本框
}
}
缺点:组件之间没有约束(可混用浅色按钮+深色文本框)
6.2.3. 抽象工厂模式 (Abstract Factory)
核心特点:一个工厂创建整套相关产品,确保产品兼容性
// 抽象工厂接口 - 创建产品族
interface UIFactory {
Button createButton();
TextField createTextField();
}
// 具体工厂 - 创建整套浅色组件
class LightThemeFactory implements UIFactory {
public Button createButton() { return new LightButton(); }
public TextField createTextField() { return new LightTextField(); }
}
// 具体工厂 - 创建整套深色组件
class DarkThemeFactory implements UIFactory {
public Button createButton() { return new DarkButton(); }
public TextField createTextField() { return new DarkTextField(); }
}
// 客户端使用
public class Client {
public static void main(String[] args) {
// 选择整套主题
UIFactory factory = new LightThemeFactory();
Button btn = factory.createButton();
TextField field = factory.createTextField();
btn.render(); // 输出:渲染浅色按钮
field.display(); // 输出:显示浅色文本框
// 切换主题只需替换工厂
factory = new DarkThemeFactory();
btn = factory.createButton(); // 深色按钮
field = factory.createTextField(); // 深色文本框
}
}
通过上面的列子,对比他们的区别
| 维度 | 简单工厂 (Simple Factory) | 工厂方法 (Factory Method) | 抽象工厂 (Abstract Factory) |
|---|---|---|---|
| 工厂数量 | 1个万能工厂 | 每个产品1个工厂 | 每个产品族1个工厂 |
| 扩展性 | 修改工厂类 (违反开闭原则) | 新增产品需新增工厂类 (符合开闭原则) | 新增产品族需新增工厂类 (符合开闭原则) |
| 核心差异 | 一个工厂类创建所有对象 (静态方法) | 抽象工厂接口,子类决定实例化哪个类 | 创建多个相关对象族 (如整套UI组件) |
| 产品关系 | 独立创建产品 | 独立创建产品 | 创建相关产品族 (强制兼容性) |
| Android示例 | BitmapFactory.decodeResource() | LayoutInflater的不同实现类 | 跨平台UI组件库 (Material vs Cupertino) |
| 适用场景 | 产品类型少且固定 | 产品类型多且可能扩展 | 需要确保产品兼容性的系统 |
| 创建方式 | 静态方法+条件分支 | 工厂子类重写创建方法 | 工厂子类实现整套创建方法 |
| 复杂度 | ⭐☆☆☆☆ (简单) | ⭐⭐☆☆☆ (中等) | ⭐⭐⭐⭐⭐ (复杂) |
| 客户端依赖 | 依赖具体工厂类 | 依赖具体工厂类 | 只依赖抽象工厂接口 |
3者的架构图
总结: 通过上表可见,Android 系统对工厂模式的应用集中在 封装复杂对象的创建逻辑 与 支持动态扩展 两大方向,其核心价值在于:
- 降低耦合:客户端无需依赖具体类(如
Bitmap的实现类),只需面向接口编程。 - 简化扩展:新增产品类型(如新的日志器或View类型)只需扩展工厂,无需修改客户端代码。
- 统一入口:集中管理对象创建逻辑(如
LayoutInflater统一处理所有View的实例化)。
💡 规律总结:当遇到以下场景时,Android源码优先采用工厂模式:
- 对象创建依赖外部参数(如图片源、布局类型)
- 需支持多态或动态替换实现(如网络库、日志系统)
- 构造过程复杂(如
Bitmap解码需处理多种输入源) 在Android中,工厂模式尤其适合需要动态切换实现类的场景(如网络库、音视频模块、多引擎支持)。通过将变化封装在工厂中,显著提升代码应对需求变更的能力。
项目工程的地址: github.com/pengcaihua1…