一、故事解说:麦当劳如何制作汉堡
假设你去麦当劳点汉堡:
-
你不需要知道汉堡怎么做:告诉服务员 “我要一个巨无霸”,服务员不会让你自己去煎肉饼、烤面包,而是让后厨(工厂)制作。
-
后厨分工明确:
- 巨无霸工厂:专门做巨无霸(面包 + 双层肉饼 + 芝士);
- 麦辣鸡腿堡工厂:专门做麦辣鸡腿堡(面包 + 炸鸡腿 + 生菜);
-
你只关心结果:拿到手的是包装好的汉堡,不用管中间步骤。
工厂模式核心:把对象的创建(做汉堡)和使用(吃汉堡)分离,客户端不用知道具体创建逻辑,只需告诉工厂要什么。
二、工厂模式核心角色(以汉堡为例)
- Product(产品) :汉堡接口,定义所有汉堡共有的方法(如
getDescription()); - ConcreteProduct(具体产品) :巨无霸、麦辣鸡腿堡等具体汉堡;
- Factory(工厂) :定义创建汉堡的方法(如
createHamburger()); - ConcreteFactory(具体工厂) :巨无霸工厂、麦辣鸡腿堡工厂,实现创建具体汉堡的逻辑。
三、Android 常用工厂模式案例与实现
案例 1:View 的创建(LayoutInflater 工厂)
java
// Product:View接口(Android中View是抽象类)
public abstract class View {
// View的共同方法
public abstract void onClick();
public abstract void setText(String text);
// 省略其他方法...
}
// ConcreteProduct:具体View
public class Button extends View {
private String text;
@Override
public void onClick() {
Log.d("Button", "Clicked: " + text);
}
@Override
public void setText(String text) {
this.text = text;
}
}
public class TextView extends View {
private String text;
@Override
public void onClick() {
Log.d("TextView", "TextView can't be clicked");
}
@Override
public void setText(String text) {
this.text = text;
Log.d("TextView", "Text set: " + text);
}
}
// Factory:LayoutInflater(Android中的视图工厂)
public class LayoutInflater {
private Context context;
private LayoutInflater(Context context) {
this.context = context;
}
// 简单工厂模式:根据类型创建View
public static View createView(Context context, String viewType) {
if ("button".equals(viewType)) {
return new Button();
} else if ("textview".equals(viewType)) {
return new TextView();
} else {
throw new IllegalArgumentException("Unknown view type: " + viewType);
}
}
// 工厂方法模式:子类实现具体创建逻辑(Android中通过子类实现)
public View inflate(int layoutResId) {
// 实际Android中会解析XML布局,创建对应View
// 简化示例:假设layoutResId对应不同View
if (layoutResId == R.layout.button_layout) {
return new Button();
} else if (layoutResId == R.layout.textview_layout) {
return new TextView();
}
return null;
}
}
// 使用示例(类似Android中LayoutInflater的用法)
View button = LayoutInflater.createView(context, "button");
button.setText("点击我");
button.onClick(); // 输出:Clicked: 点击我
优点:
-
解耦创建与使用:Activity 不用知道 Button 如何创建,只需调用工厂方法;
-
扩展性好:新增 View 类型(如 EditText)只需修改工厂,客户端代码不变;
-
符合 Android 设计:Android 系统大量使用此模式,如
LayoutInflater.from(context).inflate(...)。
缺点:
- 简单工厂违反开闭原则:新增 View 类型需要修改
createView方法; - 类型安全依赖字符串:通过字符串("button")指定类型,可能因拼写错误导致异常。
案例 2:Adapter 创建(RecyclerView.Adapter 工厂)
java
// Product:Adapter接口
public abstract class Adapter {
public abstract int getItemCount();
public abstract View onCreateViewHolder(ViewGroup parent, int viewType);
public abstract void onBindViewHolder(ViewHolder holder, int position);
}
// ConcreteProduct:具体Adapter
public class UserAdapter extends Adapter {
private List<User> users;
public UserAdapter(List<User> users) {
this.users = users;
}
@Override
public int getItemCount() {
return users.size();
}
@Override
public View onCreateViewHolder(ViewGroup parent, int viewType) {
// 创建Item View
return LayoutInflater.createView(parent.getContext(), "textview");
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// 绑定数据
}
}
public class PhotoAdapter extends Adapter {
private List<Photo> photos;
public PhotoAdapter(List<Photo> photos) {
this.photos = photos;
}
@Override
public int getItemCount() {
return photos.size();
}
@Override
public View onCreateViewHolder(ViewGroup parent, int viewType) {
// 创建不同的Item View
return LayoutInflater.createView(parent.getContext(), "imageview");
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// 绑定图片数据
}
}
// Factory:AdapterFactory
public class AdapterFactory {
// 工厂方法模式:根据数据类型创建对应的Adapter
public static Adapter createAdapter(List data) {
if (data instanceof List<User>) {
return new UserAdapter((List<User>) data);
} else if (data instanceof List<Photo>) {
return new PhotoAdapter((List<Photo>) data);
} else {
throw new IllegalArgumentException("Unsupported data type");
}
}
}
// 使用示例
List<User> users = getUsersFromServer();
Adapter userAdapter = AdapterFactory.createAdapter(users);
recyclerView.setAdapter(userAdapter);
优点:
-
数据与 UI 解耦:Adapter 负责数据展示,工厂负责创建 Adapter,Activity 只需传入数据;
-
多类型适配:不同数据类型(用户列表、图片列表)对应不同 Adapter,工厂自动匹配;
-
符合 Android 规范:RecyclerView 强制要求使用 Adapter,工厂模式简化创建流程。
缺点:
- 类型检查依赖运行时:
instanceof判断在运行时进行,编译时无法发现类型错误; - 工厂逻辑可能复杂:当 Adapter 类型过多时,工厂的
createAdapter方法会变得臃肿。
案例 3:系统服务获取(Context 的工厂方法)
java
// Product:系统服务接口(Android中以接口或抽象类存在)
public interface SystemService {
void start();
void stop();
}
// ConcreteProduct:具体系统服务
public class NotificationService implements SystemService {
@Override
public void start() {
Log.d("NotificationService", "Notification service started");
}
@Override
public void stop() {
Log.d("NotificationService", "Notification service stopped");
}
}
public class NetworkService implements SystemService {
@Override
public void start() {
Log.d("NetworkService", "Network service started");
}
@Override
public void stop() {
Log.d("NetworkService", "Network service stopped");
}
}
// Factory:Context(Android中的系统服务工厂)
public class Context {
// 简化的系统服务获取方法(类似Android的getSystemService)
public SystemService getSystemService(String serviceType) {
if (Context.NOTIFICATION_SERVICE.equals(serviceType)) {
return new NotificationService();
} else if (Context.NETWORK_SERVICE.equals(serviceType)) {
return new NetworkService();
} else {
throw new IllegalArgumentException("Unknown service: " + serviceType);
}
// Android中实际返回的是系统服务的代理对象
}
// 常量定义(类似Android的Context类)
public static final String NOTIFICATION_SERVICE = "notification";
public static final String NETWORK_SERVICE = "network";
}
// 使用示例(类似Android中获取系统服务)
Context context = getAppContext();
SystemService notificationService = context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationService.start(); // 输出:Notification service started
优点:
-
统一服务获取接口:所有系统服务通过
getSystemService获取,客户端无需知道服务实现细节; -
隐藏复杂逻辑:系统服务的创建、初始化、权限检查等逻辑封装在工厂内部;
-
符合单例模式:Android 中系统服务实际是单例,工厂模式可方便实现单例(示例中未体现,实际会缓存服务实例)。
缺点:
- 字符串类型安全问题:使用字符串(如 "notification")获取服务,拼写错误会导致异常;
- 工厂职责过重:Context 类除了创建服务,还有其他大量职责,违反单一职责原则。
四、工厂模式的适用场景与总结
适用场景:
- 对象创建逻辑复杂:如 View 需要初始化、设置属性,工厂封装这些步骤;
- 需要解耦创建与使用:客户端只关心 “用什么”,不关心 “怎么造”;
- 多类型产品管理:如 Adapter 有多种类型,工厂根据数据自动匹配;
- 系统服务获取:如 Android 的
getSystemService,隐藏服务创建细节。
核心优点:
- 解耦代码:客户端与具体产品解耦,代码更灵活;
- 扩展性好:新增产品类型只需扩展工厂,符合开闭原则;
- 封装复杂性:隐藏对象创建的复杂逻辑(如 View 的布局解析、服务的权限检查)。
核心缺点:
- 类数量增加:每个产品需要对应的工厂和类,小型项目可能过度设计;
- 工厂逻辑可能臃肿:简单工厂模式中,工厂方法可能包含大量
if-else; - 类型安全依赖运行时:通过字符串或
instanceof判断类型,编译时无法校验。
Android 中的最佳实践:
-
优先使用系统工厂:如
LayoutInflater、Context.getSystemService,避免重复造轮子; -
自定义工厂时:
- 用枚举替代字符串(如
ServiceType.NOTIFICATION),避免拼写错误; - 结合泛型减少类型转换(如
AdapterFactory.<User>createAdapter(users)); - 复杂场景使用工厂方法模式(每个产品对应一个工厂类),避免单一工厂过度复杂。
- 用枚举替代字符串(如