安卓开发设计模式全解析

安卓开发设计模式全解析

一、设计模式概述

设计模式是解决特定场景下软件设计问题的可复用方案,由 GoF(四人组)在《设计模式:可复用面向对象软件的基础》中归纳为 23 种,核心价值在于:

  • 提高代码复用性:避免重复造轮子

  • 增强可维护性:代码结构清晰,便于修改

  • 提升扩展性:应对需求变更时更灵活

  • 降低复杂度:将复杂问题拆解为标准化模块

在安卓开发中,设计模式贯穿于 Framework(如ContextRecyclerView)、第三方库(如 Retrofit、Glide)及业务代码。

按功能可将设计模式分为三类:

类型 核心作用 安卓常用模式
创建型模式 管理对象创建,隐藏创建细节 单例、工厂、建造者、原型
结构型模式 优化类 / 对象组合,简化结构 适配器、装饰者、代理、外观
行为型模式 定义对象通信与职责分配 观察者、策略、命令、迭代器

二、创建型设计模式(5 种)

1. 单例模式(Singleton)

定义

确保一个类仅有一个实例,并提供全局唯一访问入口。

核心场景(安卓)
  • 全局状态管理(如用户信息、配置信息)

  • 资源密集型对象(如网络请求客户端、数据库连接)

  • Framework 中的Application类(本质是系统维护的单例)

实现方式与代码示例
(1)饿汉式(线程安全,加载时初始化)
java 复制代码
// 网络请求管理单例(饿汉式)

public class NetworkManager {

   // 类加载时直接初始化实例(JVM保证线程安全)

   private static final NetworkManager INSTANCE = new NetworkManager();

   // 私有构造:禁止外部new

   private NetworkManager() {

       // 初始化 Retrofit/OkHttp 等

   }

   // 全局访问入口

   public static NetworkManager getInstance() {

       return INSTANCE;

   }

   // 业务方法:发起网络请求

   public void request(String url, Callback callback) {

       // 实现请求逻辑

   }

}

优点 :简单高效,无线程安全问题;缺点:类加载时就初始化,若实例未被使用会浪费内存(如 APP 启动时加载但后续未用)。

(2)懒汉式(双重检查锁,按需初始化)
java 复制代码
// 网络请求管理单例(双重检查锁)

public class NetworkManager {

   // volatile:禁止指令重排,确保实例初始化完成后再被访问

   private static volatile NetworkManager INSTANCE;

   private NetworkManager() {}

   public static NetworkManager getInstance() {

       // 第一次检查:避免已初始化时的锁竞争

       if (INSTANCE == null) {

           // 加锁:确保多线程下仅一个线程进入初始化

           synchronized (NetworkManager.class) {

               // 第二次检查:防止多线程同时进入第一个if后重复初始化

               if (INSTANCE == null) {

                   INSTANCE = new NetworkManager();

               }

           }

       }

       return INSTANCE;

   }

}

优点 :按需初始化,节省内存;缺点 :实现复杂,需注意volatile关键字(否则可能出现 "半初始化实例" 问题)。

(3)静态内部类(推荐,兼顾安全与效率)
java 复制代码
// 网络请求管理单例(静态内部类)

public class NetworkManager {

   private NetworkManager() {}

   // 静态内部类:JVM加载外部类时不会初始化内部类

   private static class SingletonHolder {

       private static final NetworkManager INSTANCE = new NetworkManager();

   }

   // 调用getInstance时才加载内部类,初始化实例(线程安全)

   public static NetworkManager getInstance() {

       return SingletonHolder.INSTANCE;

   }

}

优点 :按需初始化、线程安全(JVM 保证)、实现简单;缺点 :无法传参初始化(如需传Context需额外调用init方法)。

(4)枚举单例(防反射 / 序列化破坏)

java

typescript 复制代码
// 枚举单例(最安全,推荐用于关键场景)

public enum NetworkManager {

   INSTANCE;

   // 初始化方法

   public void init(Context context) {

       // 初始化逻辑(如传入Application Context)

   }

   // 业务方法

   public void request(String url, Callback callback) {

       // 实现逻辑

   }

}

// 使用方式

NetworkManager.INSTANCE.init(getApplicationContext());

NetworkManager.INSTANCE.request("https://api.example.com", callback);

优点 :天然防反射(枚举构造器由 JVM 控制,无法通过反射调用)、防序列化(枚举的readObject方法会返回原实例);缺点:枚举类占用内存略高(安卓中影响可忽略),无法延迟初始化。

安卓注意事项
  • 避免持有Activity/FragmentContext:会导致内存泄漏,应使用Application Context

  • 多进程场景慎用:多进程会创建多个虚拟机,单例实例不共享(需用ContentProviderSP跨进程同步)

2. 工厂模式(Factory)

定义

定义一个创建对象的接口,但由子类决定实例化哪个类,将创建逻辑与使用逻辑分离。

分类与安卓场景
类型 核心逻辑 安卓应用场景
简单工厂 一个工厂类创建所有对象 Retrofit 创建 Service 接口
工厂方法 每个产品对应一个工厂子类 自定义 View 工厂(如多主题 View)
抽象工厂 工厂创建 "产品族"(多个相关产品) 多平台适配(如 Android/iOS 控件工厂)
代码示例:Retrofit 中的简单工厂

Retrofit 通过create方法隐藏Service接口的实现细节(动态代理生成实现类),本质是简单工厂模式:

java 复制代码
// 1. 定义产品接口(Service)

public interface ApiService {

   @GET("user")

   Call<User> getUser(@Query("id") String userId);

}

// 2. 工厂类(Retrofit)创建产品实例

Retrofit retrofit = new Retrofit.Builder()

       .baseUrl("https://api.example.com/")

       .addConverterFactory(GsonConverterFactory.create())

       .build();

// 工厂方法:create() 生成 ApiService 实例(无需关心实现)

ApiService apiService = retrofit.create(ApiService.class);

// 3. 使用产品(调用接口)

apiService.getUser("123").enqueue(new Callback<User>() {

   @Override

   public void onResponse(Call<User> call, Response<User> response) {}

   @Override

   public void onFailure(Call<User> call, Throwable t) {}

});
优点与缺点
  • 优点:解耦创建与使用、便于扩展(新增产品只需修改工厂,无需修改调用方)

  • 缺点:简单工厂违背 "开闭原则"(新增产品需修改工厂类);工厂方法会增加类数量(产品越多,工厂类越多)

3. 建造者模式(Builder)

定义

将复杂对象的构建过程与表示分离,使得同一构建过程可以创建不同的表示(链式调用是典型特征)。

安卓核心场景
  • 复杂对象创建(如AlertDialogOkHttp Request

  • 第三方库(Glide、Retrofit Builder、Room Database)

代码示例 1:原生 AlertDialog.Builder
java 复制代码
// 建造者模式创建AlertDialog

new AlertDialog.Builder(this)

       .setTitle("提示") // 设置标题(建造者方法)

       .setMessage("确定要删除吗?") // 设置内容(建造者方法)

       .setPositiveButton("确定", (dialog, which) -> {

           // 确定逻辑

       })

       .setNegativeButton("取消", null)

       .create() // 构建Dialog实例

       .show(); // 展示Dialog
代码示例 2:自定义建造者(User 对象)
java 复制代码
// 复杂对象:User(包含多个可选属性)

public class User {

   private final String id;         // 必选属性

   private final String name;       // 必选属性

   private final int age;           // 可选属性

   private final String phone;      // 可选属性

   private final String email;      // 可选属性

   // 私有构造:仅允许Builder调用

   private User(Builder builder) {

       this.id = builder.id;

       this.name = builder.name;

       this.age = builder.age;

       this.phone = builder.phone;

       this.email = builder.email;

   }

   // 建造者类(静态内部类)

   public static class Builder {

       // 必选属性(初始化时传入)

       private final String id;

       private final String name;

       // 可选属性(默认值)

       private int age = 0;

       private String phone = "";

       private String email = "";

       // 必选属性构造

       public Builder(String id, String name) {

           this.id = id;

           this.name = name;

       }

       // 可选属性设置(返回Builder自身,支持链式调用)

       public Builder setAge(int age) {

           this.age = age;

           return this;

       }

       public Builder setPhone(String phone) {

           this.phone = phone;

           return this;

       }

       public Builder setEmail(String email) {

           this.email = email;

           return this;

       }

       // 构建User实例

       public User build() {

           // 可在这里添加参数校验(如id不能为空)

           if (TextUtils.isEmpty(id)) {

               throw new IllegalArgumentException("id不能为空");

           }

           return new User(this);

       }

   }

}

// 使用方式(链式调用,清晰易读)

User user = new User.Builder("123", "张三")

       .setAge(25)

       .setPhone("13800138000")

       .build();
优点与缺点
  • 优点:参数设置清晰(链式调用)、支持参数校验、避免 "telescoping constructor"(多参数构造器)

  • 缺点:增加类数量(需额外定义 Builder)、构建过程略复杂(需手动实现 Builder 逻辑)

4. 原型模式(Prototype)

定义

通过复制现有对象来创建新对象,无需重新初始化(适合创建成本高的对象)。

安卓核心场景
  • Intentclone()方法(复制 Intent 实例,避免重新设置参数)

  • RecyclerViewViewHolder缓存(复用已有 ViewHolder,减少创建开销)

  • 复杂对象复制(如配置信息、列表数据)

代码示例:Intent 克隆
java 复制代码
// 原Intent:携带大量参数

Intent originalIntent = new Intent(this, TargetActivity.class);

originalIntent.putExtra("user_id", "123");

originalIntent.putExtra("user_info", new User("123", "张三"));

originalIntent.putExtra("is_login", true);

// 克隆Intent(浅克隆)

Intent clonedIntent = (Intent) originalIntent.clone();

// 修改克隆Intent的参数(不影响原Intent)

clonedIntent.putExtra("is_login", false);

// 启动Activity

startActivity(clonedIntent);
关键概念:浅克隆 vs 深克隆
  • 浅克隆 :仅复制对象本身,引用类型属性仍指向原对象(如Intent.clone()ArrayList.clone()

  • 深克隆:复制对象及所有引用类型属性(需手动实现,如通过序列化 / 反序列化)

优点与缺点
  • 优点:减少对象创建成本(尤其复杂对象)、简化创建逻辑

  • 缺点:浅克隆可能导致引用共享问题;深克隆实现复杂(需处理所有引用类型)

三、结构型设计模式(4 种)

1. 适配器模式(Adapter)

定义

将一个类的接口转换成客户端期望的另一个接口,使原本因接口不兼容而无法工作的类可以协同工作。

安卓核心场景
  • RecyclerView.Adapter(将数据适配为ViewHolder,供RecyclerView展示)

  • ViewPager.Adapter(将页面数据适配为View,供ViewPager切换)

  • BroadcastReceiver(将系统 / 应用广播适配为自定义逻辑)

代码示例:RecyclerView.Adapter(最典型)
java 复制代码
// 1. 目标接口:RecyclerView需要的Adapter接口(系统定义)

public abstract class RecyclerView.Adapter<VH extends RecyclerView.ViewHolder> {

   public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);

   public abstract void onBindViewHolder(VH holder, int position);

   public abstract int getItemCount();

}

// 2. 适配者:业务数据(如User列表)

List<User> userList = Arrays.asList(

       new User("1", "张三"),

       new User("2", "李四")

);

// 3. 适配器:将User列表适配为RecyclerView可识别的ViewHolder

public class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserViewHolder> {

   private List<User> mUserList;

   public UserAdapter(List<User> userList) {

       this.mUserList = userList;

   }

   // 创建ViewHolder(视图容器)

   @Override

   public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

       View itemView = LayoutInflater.from(parent.getContext())

               .inflate(R.layout.item_user, parent, false);

       return new UserViewHolder(itemView);

   }

   // 绑定数据(将User数据适配到ViewHolder)

   @Override

   public void onBindViewHolder(UserViewHolder holder, int position) {

       User user = mUserList.get(position);

       holder.tvName.setText(user.getName());

       holder.tvId.setText(user.getId());

   }

   // 数据数量

   @Override

   public int getItemCount() {

       return mUserList.size();

   }

   // 视图容器(ViewHolder)

   public static class UserViewHolder extends RecyclerView.ViewHolder {

       TextView tvId;

       TextView tvName;

       public UserViewHolder(View itemView) {

           super(itemView);

           tvId = itemView.findViewById(R.id.tv_id);

           tvName = itemView.findViewById(R.id.tv_name);

       }

   }

}

// 4. 使用适配器

RecyclerView recyclerView = findViewById(R.id.recycler_view);

recyclerView.setLayoutManager(new LinearLayoutManager(this));

recyclerView.setAdapter(new UserAdapter(userList));
优点与缺点
  • 优点:解耦接口与实现、复用现有类(无需修改原类即可适配新接口)

  • 缺点:增加适配层,可能导致代码复杂度上升;过多适配器可能影响性能

2. 装饰者模式(Decorator)

定义

动态地给一个对象添加额外功能,同时不改变其原有的结构(比继承更灵活)。

安卓核心场景
  • Context家族(ContextWrapper装饰ContextImpl,添加 Activity/Service 功能)

  • IO 流(如BufferedReader装饰FileReader,添加缓冲功能)

  • Glide 图片加载(添加圆角、模糊等效果,不修改原加载逻辑)

代码示例:Context 的装饰者模式

Context是抽象接口,ContextImpl是具体实现(负责 Context 的核心功能),ContextWrapper是装饰者(持有Context引用,添加额外功能):

java 复制代码
// 1. 抽象组件:Context(定义核心功能接口)

public abstract class Context {

   public abstract void startActivity(Intent intent);

   public abstract void sendBroadcast(Intent intent);

   // 其他核心方法...

}

// 2. 具体组件:ContextImpl(实现Context的核心功能)

class ContextImpl extends Context {

   @Override

   public void startActivity(Intent intent) {

       // 实现启动Activity的底层逻辑

   }

   @Override

   public void sendBroadcast(Intent intent) {

       // 实现发送广播的底层逻辑

   }

}

// 3. 装饰者:ContextWrapper(持有Context引用,添加额外功能)

public class ContextWrapper extends Context {

   Context mBase; // 持有被装饰的Context实例

   public ContextWrapper(Context base) {

       mBase = base;

   }

   // 转发核心方法到被装饰者

   @Override

   public void startActivity(Intent intent) {

       mBase.startActivity(intent);

   }

   @Override

   public void sendBroadcast(Intent intent) {

       mBase.sendBroadcast(intent);

   }

}

// 4. 具体装饰者1:Activity(装饰Context,添加界面功能)

public class Activity extends ContextWrapper {

   // 新增功能:管理Activity生命周期

   public void onCreate(Bundle savedInstanceState) {

       // 实现Activity创建逻辑

   }

   public void onDestroy() {

       // 实现Activity销毁逻辑

   }

}

// 5. 具体装饰者2:Service(装饰Context,添加后台功能)

public class Service extends ContextWrapper {

   // 新增功能:管理Service生命周期

   public void onStartCommand(Intent intent, int flags, int startId) {

       // 实现Service启动逻辑

   }

}
优点与缺点
  • 优点:灵活扩展功能(无需修改原类)、支持多装饰(多层功能叠加)

  • 缺点:增加类数量(装饰者与被装饰者分离)、调试难度上升(需跟踪装饰链)

3. 代理模式(Proxy)

定义

为其他对象提供一种代理以控制对该对象的访问(代理类与被代理类实现同一接口)。

安卓核心场景
  • Retrofit 动态代理(代理Service接口,生成网络请求实现)

  • 图片加载代理(如 Glide 的RequestManager,代理图片加载逻辑)

  • 权限代理(如动态权限申请,代理原功能的权限校验)

代码示例:Retrofit 动态代理

Retrofit 通过Proxy.newProxyInstance生成Service接口的代理对象,拦截方法调用并生成网络请求:

java 复制代码
// 1. 被代理接口:ApiService

public interface ApiService {

   @GET("user")

   Call<User> getUser(@Query("id") String userId);

}

// 2. 动态代理生成代理对象(Retrofit内部逻辑简化)

public <T> T create(Class<T> service) {

   return (T) Proxy.newProxyInstance(

           service.getClassLoader(),

           new Class<?>[]{service},

           new InvocationHandler() {

               @Override

               public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                   // 1. 拦截方法调用,解析注解(如@GET、@Query)

                   GET getAnnotation = method.getAnnotation(GET.class);

                   String path = getAnnotation.value(); // 解析路径:"user"


                   // 2. 解析参数(如userId)

                   Query queryAnnotation = method.getParameterAnnotations()[0][0];

                   String paramName = queryAnnotation.value(); // 解析参数名:"id"

                   String paramValue = (String) args[0]; // 解析参数值:"123"



                   // 3. 生成Request(网络请求对象)

                   Request request = new Request.Builder()

                           .url("https://api.example.com/" + path + "?" + paramName + "=" + paramValue)

                           .build();


                   // 4. 返回Call对象(供调用方发起请求)

                  return new OkHttpCall(request);

               }

           }

   );

}

// 3. 使用代理对象(调用方无需关心代理逻辑)

ApiService apiService = retrofit.create(ApiService.class);

apiService.getUser("123").enqueue(callback);
优点与缺点
  • 优点:控制访问(如权限校验、缓存)、隐藏实现细节(如 Retrofit 代理网络请求逻辑)

  • 缺点 :增加代理层,可能影响性能;动态代理实现复杂(需理解InvocationHandler

4. 外观模式(Facade)

定义

为子系统中的一组接口提供一个统一的高层接口,使子系统更易于使用(简化复杂系统的调用)。

安卓核心场景
  • 第三方 SDK 封装(如支付 SDK、推送 SDK,封装复杂接口为简单调用)

  • 业务层封装(如 "用户登录" 功能,封装网络请求、数据存储、状态更新)

代码示例:支付 SDK 外观封装

假设支付 SDK 有多个复杂接口(如订单创建、支付签名、结果回调),通过外观类简化调用:

java 复制代码
// 1. 子系统复杂接口(支付SDK内部接口)

class OrderService {

   public String createOrder(String goodsId, float amount) {

       // 复杂逻辑:创建订单,返回订单号

       return "ORDER123456";

   }

}

class PayService {

   public String sign(String orderId, String userId) {

       // 复杂逻辑:生成支付签名

       return "SIGN_XXXXXX";

   }

   public void pay(String orderId, String sign, PayCallback callback) {

       // 复杂逻辑:发起支付请求

       callback.onPaySuccess(orderId);

   }

}

class CallbackService {

   public void registerCallback(PayCallback callback) {

       // 复杂逻辑:注册支付结果回调

   }

}

// 2. 外观类(统一接口,简化调用)

public class PayFacade {

   private OrderService orderService;

   private PayService payService;

   private CallbackService callbackService;

   // 初始化子系统

   public PayFacade() {

       orderService = new OrderService();

       payService = new PayService();

       callbackService = new CallbackService();

   }

   // 统一支付接口(封装所有子系统逻辑)

   public void pay(String goodsId, float amount, String userId, PayCallback callback) {

       // 1. 创建订单

       String orderId = orderService.createOrder(goodsId, amount);

       // 2. 生成签名

       String sign = payService.sign(orderId, userId);

       // 3. 注册回调

       callbackService.registerCallback(callback);

       // 4. 发起支付

       payService.pay(orderId, sign, callback);

   }

   // 支付回调接口

   public interface PayCallback {

       void onPaySuccess(String orderId);

       void onPayFailure(String orderId, String reason);

   }

}

// 3. 使用外观类(无需关心子系统细节)

PayFacade payFacade = new PayFacade();

payFacade.pay(

       "GOODS001", 99.9f, "USER123",

       new PayFacade.PayCallback() {

           @Override

           public void onPaySuccess(String orderId) {

               Toast.makeText(MainActivity.this, "支付成功:" + orderId, Toast.LENGTH_SHORT).show();

          }

           @Override

           public void onPayFailure(String orderId, String reason) {

               Toast.makeText(MainActivity.this, "支付失败:" + reason, Toast.LENGTH\_SHORT).show();

           }

       }

);
优点与缺点
  • 优点:简化调用(隐藏子系统复杂度)、降低耦合(调用方与子系统解耦)

  • 缺点:外观类可能成为 "上帝类"(职责过多);子系统扩展时可能需要修改外观类

四、行为型设计模式(4 种)

1. 观察者模式(Observer)

定义

定义对象间的一对多依赖关系,当一个对象(被观察者)状态改变时,所有依赖它的对象(观察者)都会收到通知并自动更新。

安卓核心场景
  • LiveData(观察数据变化,自动更新 UI,感知生命周期)

  • EventBus/RxJava(事件订阅 - 发布,解耦组件通信)

  • BroadcastReceiver(系统 / 应用事件通知)

  • DataBinding(数据变化自动更新 UI)

代码示例:LiveData 的观察者模式
java 复制代码
// 1. 被观察者:LiveData(系统实现,感知生命周期)

private MutableLiveData\<User> mUserLiveData = new MutableLiveData<>();

// 2. 观察者:Activity/Fragment(实现Observer接口)

@Override

protected void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

   // 观察LiveData(this为LifecycleOwner,自动绑定生命周期)

   mUserLiveData.observe(this, new Observer<User>() {

       @Override

       public void onChanged(User user) {

           // 数据变化时更新UI(自动在主线程执行)

           tvName.setText(user.getName());

           tvAge.setText(String.valueOf(user.getAge()));

       }

   });

}

// 3. 被观察者状态变化(如网络请求成功后)

private void fetchUserSuccess(User user) {

   // .postValue():在子线程更新数据;.setValue():在主线程更新数据

   mUserLiveData.postValue(user);

}
优点与缺点
  • 优点:解耦观察者与被观察者、支持广播通知(一对多)、LiveData 等实现可避免内存泄漏

  • 缺点:观察者过多时通知效率低;循环依赖可能导致问题(如 A 观察 B,B 观察 A)

2. 策略模式(Strategy)

定义

定义一系列算法,将它们封装起来并使它们可互换,使得算法可独立于使用它的客户端而变化。

安卓核心场景
  • 动画插值器(TimeInterpolator,如线性、加速、减速策略)

  • RecyclerView布局管理器(LinearLayoutManagerGridLayoutManagerStaggeredGridLayoutManager

  • 网络请求策略(如 WiFi 下用 OkHttp,移动网络下用 Retrofit 缓存策略)

代码示例:动画插值器(策略模式)

Android 的Animation通过setInterpolator设置不同的插值策略(算法),实现不同的动画效果:

java 复制代码
// 1. 策略接口:TimeInterpolator(定义算法接口)

public interface TimeInterpolator {

   // 输入:动画进度(0\~1);输出:插值后的进度(控制动画速度)

   float getInterpolation(float input);

}

// 2. 具体策略1:LinearInterpolator(线性插值,匀速动画)

public class LinearInterpolator implements TimeInterpolator {

   @Override

   public float getInterpolation(float input) {

       return input; // 输入=输出,匀速

   }

}

// 3. 具体策略2:AccelerateDecelerateInterpolator(加速减速插值)

public class AccelerateDecelerateInterpolator implements TimeInterpolator {

   @Override

   public float getInterpolation(float input) {

       // 公式:(cos((input + 1) \* π) / 2) + 0.5 → 先加速后减速

       return (float)(Math.cos((input + 1) \* Math.PI) / 2.0f) + 0.5f;

   }

}

// 4. 上下文:Animation(使用策略的客户端)

Animation animation = new TranslateAnimation(0, 500, 0, 0);

animation.setDuration(1000); // 动画时长1秒

// 设置不同策略(动态切换算法,无需修改Animation)

// 策略1:匀速动画

animation.setInterpolator(new LinearInterpolator());

// 策略2:先加速后减速动画

// animation.setInterpolator(new AccelerateDecelerateInterpolator());

// 执行动画

view.startAnimation(animation);
优点与缺点
  • 优点 :算法可互换、扩展灵活(新增策略无需修改客户端)、避免大量if-else(如不用策略模式需判断用哪种插值器)

  • 缺点:策略类数量增加(每个算法对应一个类);客户端需了解所有策略(才能选择合适的策略)

3. 命令模式(Command)

定义

将请求封装成对象,使得可以用不同的请求对客户进行参数化,支持请求的排队、记录、撤销和重做

安卓核心场景
  • HandlerMessage(将 "任务" 封装成Message,放入消息队列,Looper执行)

  • 撤销 / 重做操作(如文本编辑、绘图应用)

  • 事件分发(如ViewTouchEvent封装成命令,传递给不同的View处理)

代码示例:Handler 的 Message(命令模式)

Message封装了 "任务"(如更新 UI、延迟执行逻辑),Handler负责发送命令,Looper负责执行命令:

java 复制代码
// 1. 命令对象:Message(封装任务信息)

Message message = Message.obtain();

message.what = 1; // 命令标识(区分不同任务)

message.obj = "更新UI的参数"; // 命令参数

// 2. 命令发送者:Handler(发送命令到消息队列)

private Handler mHandler = new Handler(Looper.getMainLooper()) {

   // 3. 命令执行者:handleMessage(执行命令)

   @Override

   public void handleMessage(@NonNull Message msg) {

       super.handleMessage(msg);

       switch (msg.what) {

           case 1:

               // 执行命令:更新UI

               String param = (String) msg.obj;

               tvContent.setText(param);

               break;

           case 2:

               // 执行其他命令

               break;

       }

   }

};

// 发送命令(立即执行)

mHandler.sendMessage(message);

// 发送延迟命令(3秒后执行)

mHandler.sendEmptyMessageDelayed(2, 3000);
优点与缺点
  • 优点:解耦发送者与执行者、支持命令排队 / 撤销 / 重做、便于日志记录(如记录所有命令)

  • 缺点:命令类数量增加(每个任务对应一个命令);简单场景下略显复杂

4. 迭代器模式(Iterator)

定义

提供一种方法顺序访问一个聚合对象中的各个元素,而无需暴露该对象的内部表示

安卓核心场景
  • 集合遍历(如ArrayListHashMapiterator()方法)

  • RecyclerViewLayoutManager(迭代子View进行布局)

  • 数据库查询结果遍历(如Cursor迭代查询结果)

代码示例:ArrayList 迭代器
java 复制代码
// 1. 聚合对象:ArrayList(实现Iterable接口,提供迭代器)

List<String> list = new ArrayList<>();

list.add("A");

list.add("B");

list.add("C");

// 2. 迭代器:Iterator(定义遍历接口)

Iterator<String> iterator = list.iterator();

// 3. 遍历元素(无需关心ArrayList内部结构)

while (iterator.hasNext()) {

   String item = iterator.next();

   Log.d("Iterator", "item: " + item);

   // 支持删除元素(安全删除,避免ConcurrentModificationException)

   if (item.equals("B")) {

       iterator.remove();

   }

}

// 增强for循环(本质也是迭代器)

for (String item : list) {

   Log.d("ForEach", "item: " + item); // 输出A、C

}
优点与缺点
  • 优点:统一遍历接口(不同聚合对象用相同方式遍历)、隐藏内部结构(如 ArrayList 的数组、LinkedList 的链表)

  • 缺点:简单聚合对象(如数组)使用迭代器略显冗余;新增聚合类型需实现迭代器

五、安卓设计模式高频面试题

1. 单例模式有哪些实现方式?安卓中使用单例需要注意什么?

解答:
  • 实现方式:饿汉式、懒汉式(双重检查锁)、静态内部类、枚举(详见上文)。

  • 安卓注意事项

  1. 内存泄漏 :单例持有Activity/FragmentContext会导致内存泄漏,需使用Application Context(如getApplicationContext())。

  2. 多进程问题 :多进程会创建多个虚拟机,单例实例不共享(如需共享需用ContentProviderSPAIDL)。

  3. 序列化问题 :普通单例序列化后会生成新实例,需重写readResolve()方法返回原实例,或用枚举单例(天然防序列化)。

  4. 反射破坏:通过反射调用私有构造器可创建新实例,枚举单例可避免此问题(JVM 禁止反射调用枚举构造器)。

2. RecyclerView.Adapter 体现了哪种设计模式?请解释其原理。

解答:
  • 设计模式:适配器模式(Adapter Pattern)。

  • 原理

  1. 目标接口RecyclerView.Adapter(系统定义的接口,要求实现onCreateViewHolderonBindViewHoldergetItemCount等方法)。

  2. 适配者 :业务数据(如User列表、商品列表等,格式与RecyclerView所需的ViewHolder不兼容)。

  3. 适配器 :自定义Adapter(如UserAdapter),将业务数据转换为RecyclerView可识别的ViewHolder

  • onCreateViewHolder:创建ViewHolder(视图容器),加载 Item 布局。

  • onBindViewHolder:将业务数据绑定到ViewHolder的控件上(如设置文本、图片)。

  • getItemCount:返回数据数量,供RecyclerView计算布局。

  1. 作用 :解耦业务数据与RecyclerView的展示逻辑,使同一RecyclerView可展示不同类型的数据(只需更换Adapter)。

3. 安卓中哪些组件或框架使用了观察者模式?请举例说明。

解答:

安卓中观察者模式应用广泛,典型场景包括:

  1. LiveData
  • 被观察者:LiveData(持有数据,状态变化时通知观察者)。

  • 观察者:Activity/Fragment(实现Observer接口,接收数据变化并更新 UI)。

  • 优势:自动感知LifecycleOwner(如 Activity)的生命周期,避免内存泄漏(Activity 销毁后自动移除观察者)。

  1. EventBus/RxJava
  • 被观察者:EventBusEvent、RxJava 的Observable

  • 观察者:EventBus@Subscribe方法、RxJava 的Observer

  • 优势:解耦组件通信(如 Activity 与 Fragment、Service 与 Activity),支持线程切换。

  1. BroadcastReceiver
  • 被观察者:系统 / 应用广播(如ACTION_PACKAGE_ADDED、自定义广播)。

  • 观察者:BroadcastReceiver(通过onReceive接收广播并处理)。

  • 优势:实现跨应用、跨组件的事件通知。

  1. DataBinding
  • 被观察者:ObservableFieldBaseObservable子类(持有数据)。

  • 观察者:XML 布局中的控件(如TextViewandroid:text="@{user.name}")。

  • 优势:数据变化时自动更新 UI,无需手动调用findViewByIdsetText

4. 建造者模式和工厂模式的区别是什么?分别适用于什么场景?

解答:
对比维度 建造者模式(Builder) 工厂模式(Factory)
核心目标 构建复杂对象(多属性、多步骤) 创建简单 / 中等复杂度对象
构建过程 分步构建(链式调用设置属性,最后build 一步创建(调用工厂方法直接返回对象)
参数支持 支持大量可选参数(如AlertDialog的标题、内容、按钮) 多为必选参数(如 Retrofit 创建 Service)
灵活性 可定制对象的每个属性(如User的年龄、电话、邮箱) 固定对象结构(工厂返回的对象属性相对固定)
适用场景 1. 复杂对象创建(如AlertDialogOkHttp Request)2. 多可选参数的对象(如用户信息、订单信息)3. 第三方库(Glide、Retrofit Builder) 1. 简单对象创建(如 Retrofit Service、自定义 View)2. 产品类型固定(如仅创建几种类型的对象)3. 客户端无需关心创建细节(如仅需调用工厂方法)

示例

  • 建造者模式:用AlertDialog.Builder创建带标题、内容、确定 / 取消按钮的对话框(多步骤、多可选参数)。

  • 工厂模式:用Retrofit.create()创建ApiService实例(一步创建,参数固定为 Service 接口)。

5. Retrofit 中用到了哪些设计模式?请详细说明。

解答:

Retrofit 是安卓网络请求的核心框架,集成了多种设计模式:

  1. 工厂模式
  • 场景:Retrofit.Builder创建Retrofit实例、create()方法创建Service接口实例。

  • 原理:Retrofit.Builder通过链式调用设置baseUrlConverterFactory等参数,最后build()返回Retrofit实例;create()方法通过工厂逻辑生成Service接口的动态代理对象。

  1. 代理模式(动态代理)
  • 场景:Retrofit.create(Class<T> service)生成Service接口实例。

  • 原理:通过Proxy.newProxyInstance生成动态代理对象,拦截Service接口的方法调用,解析方法上的注解(如@GET@POST@Query),生成Request对象,最终通过 OkHttp 发起网络请求。

  1. 适配器模式
  • 场景:ConverterFactory(如GsonConverterFactoryJacksonConverterFactory)。

  • 原理:ConverterFactory将网络响应的ResponseBody(原始数据)适配为业务所需的 Java 对象(如UserList<Goods>),解耦数据解析与网络请求逻辑。

4 策略模式

  • 场景:CallAdapter.Factory(如RxJavaCallAdapterFactoryCoroutineCallAdapterFactory)。

  • 原理:CallAdapter定义网络请求结果的转换策略,不同的CallAdapterCall对象转换为不同类型(如ObservableFlowDeferred),客户端可根据需求选择不同策略。

6. 为什么说 Application 是单例模式的应用?它的生命周期有什么特点?

解答:
  • Application 是单例的原因
  1. 系统保证唯一实例 :安卓系统在 APP 启动时会创建且仅创建一个Application实例,整个 APP 进程中只有一个Application对象。

  2. 全局访问入口 :通过getApplication()getApplicationContext()可在任意ActivityServiceBroadcastReceiver中获取Application实例,符合单例模式的 "全局唯一访问" 特征。

  3. 私有构造(隐含)Application的构造器是 public 的,但系统禁止开发者手动new Application(手动创建的实例无法被系统管理,且与系统创建的实例冲突),本质上仅有系统能创建实例,符合单例模式的 "唯一实例" 特征。

  • Application 生命周期特点
  1. 生命周期与 APP 进程一致Application在 APP 进程创建时初始化(onCreate),在 APP 进程销毁时销毁(无明确的onDestroy方法,进程销毁时资源自动释放)。

  2. 初始化时机早Application.onCreate()在所有ActivityServiceReceiver创建前执行,适合初始化全局资源(如网络请求客户端、数据库、全局配置)。

  3. 注意事项

  • 避免在onCreate中执行耗时操作(如网络请求、大量 IO),会导致 APP 启动慢(ANR 风险)。

  • 避免存储大量数据(如大列表),会占用内存,可能导致 OOM。

  • 多进程场景下,每个进程会创建独立的Application实例(需在onCreate中判断进程名,避免重复初始化)。

六、总结

设计模式是安卓开发的 "内功",其核心不是死记硬背 23 种模式,而是理解 "如何用标准化方案解决特定问题"。在实际开发中:

  • 创建型模式:解决 "对象如何创建" 的问题(如单例确保唯一实例,建造者简化复杂对象创建)。

  • 结构型模式:解决 "类 / 对象如何组合" 的问题(如适配器解耦接口,装饰者扩展功能)。

  • 行为型模式:解决 "对象如何通信" 的问题(如观察者实现通知,策略模式切换算法)。

相关推荐
诺诺Okami2 小时前
Android Framework-WMS-层级结构树
android
alexhilton13 小时前
面向开发者的系统设计:像建筑师一样思考
android·kotlin·android jetpack
CYRUS_STUDIO1 天前
用 Frida 控制 Android 线程:kill 命令、挂起与恢复全解析
android·linux·逆向
CYRUS_STUDIO1 天前
Frida 实战:Android JNI 数组 (jobjectArray) 操作全流程解析
android·逆向
用户091 天前
Gradle Cache Entries 深度探索
android·java·kotlin
循环不息优化不止1 天前
安卓 View 绘制机制深度解析
android
叽哥1 天前
Kotlin学习第 9 课:Kotlin 实战应用:从案例到项目
android·java·kotlin
雨白2 天前
Java 线程通信基础:interrupt、wait 和 notifyAll 详解
android·java
诺诺Okami2 天前
Android Framework-Launcher-UI和组件
android