当前位置: 首页 > news >正文

Android开发——设计模式技术总结

一、单例模式

1. 饿汉模式 (Eager Initialization)

实现方式:在类加载时就创建单例实例,而不是等到第一次使用时才创建。

代码示例

public class Singleton {private static Singleton instance = new Singleton();private Singleton(){}public static Singleton getInstance(){return instance;}
}

优点

  • 线程安全:由于实例是在类加载时创建的,所以天然是线程安全的。在任何线程访问 getInstance() 方法之前,实例就已经存在了,不需要进行同步控制。

  • 实现简单:代码简洁,易于理解。

缺点

  • 非懒加载:无论是否使用,实例都会在类加载时被创建。如果单例的创建过程比较耗时,或者单例对象占用大量资源,而程序又一直没有用到它,就会造成资源浪费。

2. 双重检查锁模式 (Double-Checked Locking, DCL)

实现方式:在 getInstance() 方法中使用 synchronized 关键字,并且在同步块内部和外部都进行一次 null 检查。

代码示例

public class Singleton {private static volatile Singleton instance;private Singleton(){}public static Singleton getInstance(){if(instance == null){synchronized (Singleton.class){if(instance == null){instance = new Singleton();}}}return instance;}
}

为什么采用它

双重检查锁模式是解决多线程下懒加载单例问题的首选方案,因为它兼顾了性能和线程安全。

  • 性能提升:与在整个方法上加 synchronized 的懒汉模式相比,它只在第一次创建实例时才进行同步,之后的调用都无需同步,大大提高了访问效率。

  • 线程安全:通过使用 volatile 关键字,确保了 instance 变量的可见性和有序性。这解决了指令重排可能导致的问题,保证了当一个线程看到 instance 不为 null 时,其构造方法已经执行完毕,是一个完整的对象。

  • 懒加载:只有在第一次调用 getInstance() 方法时,才会创建实例,避免了不必要的资源开销。

3. 静态内部类模式 (Static Inner Class)多并发条件下

实现方式:将单例实例的创建放在一个私有的静态内部类中。

代码示例

public class Singleton {private Singleton(){}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance(){return SingletonHolder.INSTANCE;}
}

为什么采用它

静态内部类模式是多线程下最推荐的单例实现方式之一,因为它完美地结合了懒加载和线程安全,并且实现起来比双重检查锁模式更简单。

  • 线程安全:JVM 保证了类加载过程的线程安全。SingletonHolder 类只有在第一次调用 getInstance() 方法时才会被加载,并且只会加载一次,因此 INSTANCE 实例也只会创建一次,天然地避免了多线程问题。

  • 懒加载:实例是在调用 getInstance() 方法时才创建,实现了懒加载。

  • 实现简洁:没有复杂的同步代码,代码更清晰易懂。

主要应用:

        MediaSettingDbManager 使用 @Singleton 注解来确保其数据库实例在整个应用程序生命周期中是唯一的。这种单例模式是管理数据库实例的最佳实践,因为它能有效解决多个数据库连接带来的资源消耗问题,并确保数据的一致性。通过将数据库实例设计成单例,所有的数据读写操作都将通过同一个实例进行,避免了因多个实例同步不及时而导致的数据不一致问题。此外,它还避免了重复创建数据库连接这个耗时的过程,从而显著提升了应用的性能和启动速度。

二、工厂模式

        工厂模式主要包括三种类型:简单工厂模式工厂方法模式抽象工厂模式。它们的核心都是将对象的创建过程封装起来,从而降低客户端与具体产品之间的耦合。简单工厂模式通过一个单一的工厂类来创建所有产品,优点是实现简单,但缺点是当需要新增产品时必须修改工厂类,不符合开闭原则。为了解决这个问题,工厂方法模式应运而生,它为每一种产品都提供一个独立的工厂,这完美遵循了开闭原则,更易于扩展,但会增加类的数量。抽象工厂模式则更进一步,用于创建一系列相互关联的产品族,它确保了产品族内部的一致性,但其结构更为复杂,并且在新增产品种类时,往往需要修改所有工厂。简单来说,简单工厂适用于简单场景,工厂方法适用于需要频繁扩展新产品的场景,而抽象工厂则适用于需要创建完整产品族的复杂场景。

 ViewModel中的工厂方法模式

        当我们在使用 ViewModel 的时候,通常不会直接用 new ViewModel() 来创建实例,而是通过 ViewModelProvider 来获取。ViewModelProvider 就是一个工厂,它内部有一个 Factory 接口,这个接口就是工厂方法模式的抽象工厂。

ViewModel中工厂方法模式的作用和意义:

  • 解耦和职责分离:ViewModel 负责处理业务逻辑和数据,而不关心自己如何被创建。ViewModelProvider.Factory 则专门负责创建 ViewModel 实例。这符合单一职责原则,让 ViewModel 专注于自己的核心任务。

  • 支持带参数的ViewModel:如果你的 ViewModel 构造函数需要参数(比如 Repository、Context、或用户ID等),普通的 new ViewModel() 无法满足。通过自定义一个实现了 ViewModelProvider.Factory 接口的工厂类,你就可以在工厂的 create() 方法中传入这些必要的参数,并正确地创建 ViewModel 实例。

  • 处理生命周期:ViewModel 的生命周期由 ViewModelProvider 管理。ViewModelProvider 会检查是否已经有一个特定类的 ViewModel 实例存在于当前生命周期作用域内。如果存在,它会返回现有实例;如果不存在,它会调用你提供的 Factory 来创建一个新实例。这确保了 ViewModel 实例在屏幕旋转等配置变更时能够存活下来,避免了不必要的重复创建。

示例解析

假设你有一个 UserViewModel 需要一个 UserRepository 作为参数来获取用户数据。

1. 抽象产品(ViewModel)和具体产品(UserViewModel

public class UserViewModel extends ViewModel {private UserRepository userRepository;public UserViewModel(UserRepository userRepository) {this.userRepository = userRepository;}public LiveData<User> getUser(String userId) {return userRepository.getUser(userId);}
}

2. 抽象工厂(ViewModelProvider.Factory)和具体工厂(UserViewModelFactory

这个 UserViewModelFactory 就是工厂方法模式的具体工厂,它实现了 ViewModelProvider.Factory 接口,负责创建 UserViewModel

public class UserViewModelFactory implements ViewModelProvider.Factory {private UserRepository userRepository;public UserViewModelFactory(UserRepository userRepository) {this.userRepository = userRepository;}@NonNull@Overridepublic <T extends ViewModel> T create(@NonNull Class<T> modelClass) {// 在这里创建具体的ViewModel实例,并将UserRepository传入if (modelClass.isAssignableFrom(UserViewModel.class)) {return (T) new UserViewModel(userRepository);}throw new IllegalArgumentException("Unknown ViewModel class");}
}

3. 客户端(Activity/Fragment)

客户端不再直接 new UserViewModel(),而是通过工厂来获取实例。

public class ProfileFragment extends Fragment {private UserViewModel userViewModel;@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 假设已经有了一个UserRepository实例UserRepository userRepository = new UserRepository();// 创建工厂实例UserViewModelFactory factory = new UserViewModelFactory(userRepository);// 通过ViewModelProvider获取ViewModel实例,这里使用了工厂方法模式userViewModel = new ViewModelProvider(this, factory).get(UserViewModel.class);}
}

在这个例子中,ViewModelProvider 扮演了工厂管理者的角色,而 UserViewModelFactory 则是真正的创建者,它决定了如何实例化 UserViewModel。这种模式将 ViewModel 的创建逻辑与它的使用完全解耦,使得代码更易于测试和维护。

线程池中的工厂方法模式

        在 Java 的 Executors 类中,提供了许多静态工厂方法来创建不同类型的线程池,例如 newFixedThreadPool()newCachedThreadPool()newSingleThreadExecutor() 等。这些方法就是工厂方法模式的典型应用。

线程池中工厂方法模式的作用和意义:

  • 简化创建过程:线程池的构造参数非常复杂,包括核心线程数、最大线程数、空闲线程存活时间、阻塞队列、线程工厂等。Executors 类的静态工厂方法将这些复杂的创建细节封装起来,让开发者无需关心具体的实现参数,只需选择适合自己场景的方法即可,如“我需要一个固定大小的线程池”或“我需要一个按需创建的线程池”。

  • 提供标准化的实现Executors 类提供了几种预定义的、经过优化的线程池配置,这些配置已经过大量实践验证,可以满足大部分常见需求。

  • 解耦和灵活性:开发者只需要使用 ExecutorService 接口,而无需与具体的 ThreadPoolExecutor 类耦合。这使得在不改变客户端代码的情况下,可以轻松切换不同类型的线程池实现。

示例解析

我们可以将 Executors 类视为一个抽象工厂,而其中的每个静态方法(如 newFixedThreadPool())则是一个具体工厂,每个方法都会返回一个特定配置的线程池实例(即具体产品)。

1. 抽象产品(ExecutorService)和具体产品(ThreadPoolExecutor

在 Java 中,ExecutorService 是一个接口,代表线程池服务。而 ThreadPoolExecutor 是它的一个具体实现类。

// 抽象产品:线程池接口
public interface ExecutorService extends Executor {// ...
}// 具体产品:线程池实现类
public class ThreadPoolExecutor extends AbstractExecutorService {// 构造函数非常复杂public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {// ...}
}

2. 抽象工厂(Executors 类)和具体工厂方法

Executors 类本身不是一个接口,但它提供了一系列静态工厂方法,充当了工厂方法模式中具体工厂的角色。

// Execuors 类,提供各种工厂方法
public class Executors {// 工厂方法:创建一个固定大小的线程池public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}// 工厂方法:创建一个按需创建新线程的线程池public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());}// 其他工厂方法...
}

3. 客户端使用

开发者只需要调用 Executors 提供的工厂方法,即可获取一个配置好的线程池实例,而无需关心内部的复杂参数。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class MyAndroidApp {// 客户端代码,直接使用工厂方法public void executeTasks() {// 创建一个固定大小为4的线程池ExecutorService executorService = Executors.newFixedThreadPool(4);// 提交任务executorService.submit(() -> {System.out.println("执行后台任务 1");});executorService.submit(() -> {System.out.println("执行后台任务 2");});// 在应用退出时关闭线程池executorService.shutdown();}
}

总结

Executors 类通过提供一系列静态工厂方法,完美地将线程池的创建逻辑使用逻辑分离开来,这正是工厂方法模式的核心思想。它隐藏了 ThreadPoolExecutor 复杂构造函数的细节,使得线程池的创建和使用变得简单、高效,并且易于维护。

三、其他设计模式应用

        建造者模式通过一个独立的“建造者”对象,将复杂对象的构建过程与其表示分离,让你可以用清晰的链式调用来一步步设置对象的属性,最后一次性创建出最终对象,从而解决了构造函数参数过多、可读性差的问题。(OkHttp,Retrofit初始化配置)

        责任链模式则是通过将请求处理者连接成一条链,让请求沿着这条链传递,直到有一个处理者能够处理它为止,这种方式将请求的发送者和处理者解耦,使得系统更加灵活、可扩展,并且每个处理者都职责单一。(OkHttp拦截器)

http://www.dtcms.com/a/487219.html

相关文章:

  • 做网站要搭建本地服务器么网站建设可行性研究
  • 表3-5企业网站建设可行性分析静态网页怎么放到网上
  • 荆州网站建设荆州手工制作书签简单又好看
  • 伪静态就是把网站地址如何自己创建小程序
  • GPT-2 技术报告
  • Tiger生成式推荐
  • 宿州企业网站建设小程序服务器可以做网站吗
  • Vue组件中Prop类型定义与泛型类型安全指南
  • 企业级流程平台权责模块架构升级:技术实现与核心价值
  • vscode如何链接远程服务器里面的docker里面的目录
  • 从B站提取视频或音频、音乐,下复制链接,然后到提取网站进行提取和下载
  • 新的网站怎么推广淘宝客返利网站程序
  • 算法沉淀第三天(统计二进制中1的个数 两个整数二进制位不同个数)
  • 制造业的未来:数字孪生正在重塑一切
  • 网站联系方式模板搜索引擎提交网站
  • 目标识别笔记
  • 考研408《计算机组成原理》复习笔记,第五章(5)——CPU的【微程序控制器】
  • 做网站page庆阳东道设计
  • 从1G到5G:移动通信技术的迭代史诗与未来展望
  • 深入理解 Java 类加载与垃圾回收机制:从原理到实践
  • 手机wap网站模板 带后台台州椒江做网站
  • 苏州网站推广公司东营住建局官网
  • 配置的前世今生:从逻辑中抽离,又与逻辑有限融合
  • 十三、kubernetes 1.29 之 存储 storageClass存储类、补全命令
  • Kotlin中的flow、stateflow、shareflow之间的区别和各自的功能
  • 一般网站建设的流程图wordpress账号和站内网
  • 复习总结最终版:Linux软件编程
  • 索泰显卡,索泰 firestorm 官方下载
  • 网站建设的主要内容包括网页框架结构有哪些
  • 公司做一个网站企业网站制作哪些公司制作