一、故事解说:豪华汽车工厂如何生产不同品牌
假设你要开一家豪华汽车工厂,专门生产高端车:
-
系列化生产:
- 奔驰系列:生产奔驰发动机、奔驰轮胎、奔驰内饰;
- 宝马系列:生产宝马发动机、宝马轮胎、宝马内饰;
-
工厂分工:
- 抽象工厂:定义生产发动机、轮胎、内饰的接口;
- 具体工厂:奔驰工厂只生产奔驰部件,宝马工厂只生产宝马部件;
-
客户需求:客户说 “我要一辆奔驰”,工厂自动匹配生产奔驰的全套部件,无需关心细节。
抽象工厂核心:创建一系列相关或依赖的对象(如发动机 + 轮胎 + 内饰),将对象的创建逻辑封装在具体工厂中,客户端只需指定系列,无需知道具体实现。
二、抽象工厂模式核心结构(汽车工厂案例)
java
// 1. 抽象产品1:发动机
interface Engine {
void start();
}
// 2. 具体产品1:奔驰发动机
class BenzEngine implements Engine {
@Override
public void start() {
System.out.println("奔驰发动机启动,声音低沉有力");
}
}
// 3. 具体产品1:宝马发动机
class BmwEngine implements Engine {
@Override
public void start() {
System.out.println("宝马发动机启动,声浪澎湃");
}
}
// 4. 抽象产品2:轮胎
interface Tire {
void inflate();
}
// 5. 具体产品2:奔驰轮胎
class BenzTire implements Tire {
@Override
public void inflate() {
System.out.println("奔驰轮胎充气至2.5Bar,舒适静音");
}
}
// 6. 具体产品2:宝马轮胎
class BmwTire implements Tire {
@Override
public void inflate() {
System.out.println("宝马轮胎充气至2.8Bar,运动性能佳");
}
}
// 7. 抽象工厂:定义生产系列产品的接口
interface CarFactory {
Engine createEngine();
Tire createTire();
}
// 8. 具体工厂:奔驰工厂
class BenzFactory implements CarFactory {
@Override
public Engine createEngine() {
return new BenzEngine();
}
@Override
public Tire createTire() {
return new BenzTire();
}
}
// 9. 具体工厂:宝马工厂
class BmwFactory implements CarFactory {
@Override
public Engine createEngine() {
return new BmwEngine();
}
@Override
public Tire createTire() {
return new BmwTire();
}
}
// 10. 客户端:使用工厂生产汽车
public class Client {
public static void main(String[] args) {
// 创建奔驰工厂
CarFactory benzFactory = new BenzFactory();
Engine benzEngine = benzFactory.createEngine();
Tire benzTire = benzFactory.createTire();
benzEngine.start(); // 输出:奔驰发动机启动...
benzTire.inflate(); // 输出:奔驰轮胎充气...
// 创建宝马工厂
CarFactory bmwFactory = new BmwFactory();
Engine bmwEngine = bmwFactory.createEngine();
Tire bmwTire = bmwFactory.createTire();
bmwEngine.start(); // 输出:宝马发动机启动...
bmwTire.inflate(); // 输出:宝马轮胎充气...
}
}
三、Android 常用抽象工厂模式案例与实现
案例 1:UI 主题工厂(生产不同主题的控件)
java
// 1. 抽象产品1:按钮
interface Button {
void setBackgroundColor(int color);
void setText(String text);
}
// 2. 具体产品1:深色主题按钮
class DarkButton implements Button {
@Override
public void setBackgroundColor(int color) {
System.out.println("深色按钮设置背景色:" + color);
}
@Override
public void setText(String text) {
System.out.println("深色按钮设置文字:" + text);
}
}
// 3. 具体产品1:浅色主题按钮
class LightButton implements Button {
@Override
public void setBackgroundColor(int color) {
System.out.println("浅色按钮设置背景色:" + color);
}
@Override
public void setText(String text) {
System.out.println("浅色按钮设置文字:" + text);
}
}
// 4. 抽象产品2:文本框
interface EditText {
void setHint(String hint);
void setTextColor(int color);
}
// 5. 具体产品2:深色主题文本框
class DarkEditText implements EditText {
@Override
public void setHint(String hint) {
System.out.println("深色文本框设置提示:" + hint);
}
@Override
public void setTextColor(int color) {
System.out.println("深色文本框设置文字颜色:" + color);
}
}
// 6. 具体产品2:浅色主题文本框
class LightEditText implements EditText {
@Override
public void setHint(String hint) {
System.out.println("浅色文本框设置提示:" + hint);
}
@Override
public void setTextColor(int color) {
System.out.println("浅色文本框设置文字颜色:" + color);
}
}
// 7. 抽象工厂:主题工厂
interface ThemeFactory {
Button createButton();
EditText createEditText();
}
// 8. 具体工厂:深色主题工厂
class DarkThemeFactory implements ThemeFactory {
@Override
public Button createButton() {
return new DarkButton();
}
@Override
public EditText createEditText() {
return new DarkEditText();
}
}
// 9. 具体工厂:浅色主题工厂
class LightThemeFactory implements ThemeFactory {
@Override
public Button createButton() {
return new LightButton();
}
@Override
public EditText createEditText() {
return new LightEditText();
}
}
// 10. 在Activity中使用
public class MainActivity extends AppCompatActivity {
private ThemeFactory themeFactory;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 根据系统主题选择工厂(简化示例,实际中读取系统主题)
if (isDarkModeEnabled()) {
themeFactory = new DarkThemeFactory();
} else {
themeFactory = new LightThemeFactory();
}
// 创建按钮和文本框
Button button = themeFactory.createButton();
EditText editText = themeFactory.createEditText();
// 设置控件属性
button.setBackgroundColor(Color.BLUE);
button.setText("点击我");
editText.setHint("请输入内容");
editText.setTextColor(Color.BLACK);
}
private boolean isDarkModeEnabled() {
// 实际中检查系统主题
return false;
}
}
优点:
-
主题统一管理:同一主题的控件由同一工厂生产,保证风格一致性;
-
动态切换主题:运行时切换工厂即可切换整个界面风格;
-
扩展性好:新增主题(如红色主题、绿色主题)只需添加新工厂和产品,不修改现有代码。
缺点:
- 类数量爆炸:每个主题需要按钮、文本框等多个产品类,主题多了类数翻倍;
- 耦合度较高:产品之间存在隐含依赖(如深色按钮必须配深色文本框),修改一处可能影响整体。
案例 2:数据库工厂(生产不同类型的数据库连接)
java
// 1. 抽象产品1:数据库连接
interface DbConnection {
void connect();
void close();
}
// 2. 具体产品1:SQLite连接
class SqliteConnection implements DbConnection {
@Override
public void connect() {
System.out.println("连接SQLite数据库");
}
@Override
public void close() {
System.out.println("关闭SQLite连接");
}
}
// 3. 具体产品1:MySQL连接(Android中需通过JDBC驱动)
class MysqlConnection implements DbConnection {
@Override
public void connect() {
System.out.println("连接MySQL数据库(需JDBC驱动)");
}
@Override
public void close() {
System.out.println("关闭MySQL连接");
}
}
// 4. 抽象产品2:数据库操作
interface DbOperation {
void query(String sql);
void insert(String sql);
}
// 5. 具体产品2:SQLite操作
class SqliteOperation implements DbOperation {
@Override
public void query(String sql) {
System.out.println("SQLite执行查询:" + sql);
}
@Override
public void insert(String sql) {
System.out.println("SQLite执行插入:" + sql);
}
}
// 6. 具体产品2:MySQL操作
class MysqlOperation implements DbOperation {
@Override
public void query(String sql) {
System.out.println("MySQL执行查询:" + sql);
}
@Override
public void insert(String sql) {
System.out.println("MySQL执行插入:" + sql);
}
}
// 7. 抽象工厂:数据库工厂
interface DbFactory {
DbConnection createConnection();
DbOperation createOperation();
}
// 8. 具体工厂:SQLite工厂
class SqliteFactory implements DbFactory {
@Override
public DbConnection createConnection() {
return new SqliteConnection();
}
@Override
public DbOperation createOperation() {
return new SqliteOperation();
}
}
// 9. 具体工厂:MySQL工厂
class MysqlFactory implements DbFactory {
@Override
public DbConnection createConnection() {
return new MysqlConnection();
}
@Override
public DbOperation createOperation() {
return new MysqlOperation();
}
}
// 10. 在Activity中使用
public class DbActivity extends AppCompatActivity {
private DbFactory dbFactory;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 根据配置选择数据库(简化示例)
if (useLocalDb()) {
dbFactory = new SqliteFactory();
} else {
dbFactory = new MysqlFactory();
}
// 获取连接和操作对象
DbConnection connection = dbFactory.createConnection();
DbOperation operation = dbFactory.createOperation();
// 执行数据库操作
connection.connect();
operation.query("SELECT * FROM users");
operation.insert("INSERT INTO logs VALUES(...)");
connection.close();
}
private boolean useLocalDb() {
// 实际中读取配置
return true;
}
}
优点:
-
数据库解耦:客户端不依赖具体数据库实现,便于切换(如本地 SQLite 或远程 MySQL);
-
统一操作接口:无论哪种数据库,操作方式一致,降低学习成本;
-
测试方便:测试时可使用轻量级 SQLite 工厂,生产环境切换到 MySQL 工厂。
缺点:
- 实现复杂度高:需要为每种数据库实现全套产品,工作量大;
- 性能考虑:抽象工厂的多层调用可能带来微小性能开销,需权衡。
案例 3:网络请求工厂(生产不同类型的请求)
java
// 1. 抽象产品1:GET请求
interface GetRequest {
void send(String url);
}
// 2. 具体产品1:OkHttp GET请求
class OkHttpGetRequest implements GetRequest {
@Override
public void send(String url) {
System.out.println("OkHttp发送GET请求:" + url);
}
}
// 3. 具体产品1:Retrofit GET请求
class RetrofitGetRequest implements GetRequest {
@Override
public void send(String url) {
System.out.println("Retrofit发送GET请求:" + url);
}
}
// 4. 抽象产品2:POST请求
interface PostRequest {
void send(String url, String data);
}
// 5. 具体产品2:OkHttp POST请求
class OkHttpPostRequest implements PostRequest {
@Override
public void send(String url, String data) {
System.out.println("OkHttp发送POST请求到" + url + ",数据:" + data);
}
}
// 6. 具体产品2:Retrofit POST请求
class RetrofitPostRequest implements PostRequest {
@Override
public void send(String url, String data) {
System.out.println("Retrofit发送POST请求到" + url + ",数据:" + data);
}
}
// 7. 抽象工厂:网络请求工厂
interface NetworkFactory {
GetRequest createGetRequest();
PostRequest createPostRequest();
}
// 8. 具体工厂:OkHttp工厂
class OkHttpFactory implements NetworkFactory {
@Override
public GetRequest createGetRequest() {
return new OkHttpGetRequest();
}
@Override
public PostRequest createPostRequest() {
return new OkHttpPostRequest();
}
}
// 9. 具体工厂:Retrofit工厂
class RetrofitFactory implements NetworkFactory {
@Override
public GetRequest createGetRequest() {
return new RetrofitGetRequest();
}
@Override
public PostRequest createPostRequest() {
return new RetrofitPostRequest();
}
}
// 10. 在Activity中使用
public class NetworkActivity extends AppCompatActivity {
private NetworkFactory networkFactory;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 根据配置选择网络框架(简化示例)
if (useOkHttp()) {
networkFactory = new OkHttpFactory();
} else {
networkFactory = new RetrofitFactory();
}
// 创建请求对象
GetRequest getRequest = networkFactory.createGetRequest();
PostRequest postRequest = networkFactory.createPostRequest();
// 发送请求
getRequest.send("https://api.example.com/data");
postRequest.send("https://api.example.com/upload", "{"key":"value"}");
}
private boolean useOkHttp() {
// 实际中读取配置
return true;
}
}
优点:
-
框架解耦:客户端不依赖具体网络框架(OkHttp/Retrofit),便于切换或升级;
-
统一请求接口:无论哪种框架,GET/POST 请求接口一致,代码更统一;
-
扩展性好:新增网络框架(如 Volley)只需添加新工厂和产品,不影响现有代码。
缺点:
- 维护成本高:需要为每个框架维护一套请求产品,框架升级时可能需要同步修改;
- 过度设计风险:对于小型项目,抽象工厂可能增加复杂度,不如直接使用单一框架。
四、抽象工厂模式的适用场景与总结
适用场景:
- 系列产品创建:需要创建一系列相关或依赖的对象(如主题控件、数据库连接、网络请求);
- 多产品线支持:系统需要支持多个产品系列(如深色 / 浅色主题、SQLite/MySQL 数据库);
- 解耦具体实现:客户端不希望依赖具体产品的创建逻辑,只关心抽象接口;
- 统一产品风格:确保同一工厂生产的产品风格一致(如同一主题的所有控件)。
核心优点:
- 封装系列创建:将系列产品的创建逻辑封装在工厂中,客户端无需关心细节;
- 解耦产品与客户端:客户端只依赖抽象接口,不依赖具体实现,提高可维护性;
- 保证产品一致性:同一工厂生产的产品相互兼容,避免风格或功能冲突;
- 符合开闭原则:新增产品系列只需添加新工厂和产品,不修改现有代码。
核心缺点:
- 类数量爆炸:每个产品系列需要多个产品类和工厂类,导致类数快速增加;
- 扩展新产品困难:若要新增一种产品(如主题中添加 TextView),需修改所有工厂接口和实现;
- 性能开销:多层抽象和接口可能带来微小的性能开销,不过在 Android 中通常可忽略。
Android 中的最佳实践:
-
主题切换场景:使用抽象工厂管理不同主题的控件,保证界面一致性;
-
多数据源支持:如同时支持本地数据库和远程 API,用抽象工厂封装数据源创建;
-
框架适配层:当项目需要支持多种框架(如图片加载库)时,用抽象工厂隔离框架差异;
-
结合其他模式:与单例模式结合(工厂使用单例),与 builder 模式结合(复杂产品的构建)。
抽象工厂模式是大型项目中管理系列化对象创建的有力工具,虽然实现成本较高,但在需要支持多产品线或动态切换产品系列的场景中,能带来显著的架构优势。