概述
设计模式就是经过我们开发人员通过长时间的开发实践得出的一种开发模式,目的就是在开发过程中降低代码耦合度,提高代码可复用性/扩展/维护。目前主要有23种设计模式,分为创建型模式、行为型模式、结构型模式。本文列举了实际项目中使用到的设计模式,包括单例模式、策略模式、代理模式
创建型模式
单例模式
- 目的就是解决一个类Class在应用程序中只有一个实例存在,并提供对外的全局访问
- 构造函数私有化、对外提供获取实例静态方法
- 项目实践
- 在多线程环境中缓存文件操作记录到队列中,后续通过定时任务添加到数据库
-
public class LazyQueueSingleton {private static int QUEUE_MAX_SIZE = 80000;// LinkedBlockingQueue线程安全的共享队列,并设置队列初始大小避免内存溢出private volatile Queue<HistoryRecords> ShareQueue = new LinkedBlockingQueue<>(QUEUE_MAX_SIZE);private static final Object lockedObj = new Object();//懒汉式队列单例,保证实例全局唯一 private static volatile LazyQueueSingleton INSTANCE;private LazyQueueSingleton() {if(ShareQueue == null) {ShareQueue = new LinkedBlockingQueue<>(QUEUE_MAX_SIZE);}}public static LazyQueueSingleton getInstance() {if(INSTANCE == null) {synchronized (lockedObj) {if(INSTANCE == null) {INSTANCE = new LazyQueueSingleton();}}}return INSTANCE;}public Queue<HistoryRecords> getPendingTodoQueue() {return ShareQueue;} }
行为型模式
策略(Strategy)模式
- 定义了一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。常常适用于业务存在很多复杂分支场景
- 上下文/Context(持有一个策略对象的引用,通过该引用来调用算法或行为)、策略/Strategy(定义所有支持的算法的公共接口)、具体策略/Concrete Strategy(实现策略接口的具体算法或行为)
- 项目实践
- 系统需要根据不同部门来计算报表生成的内容
-
// 1.定义策略接口 public interface GernerateReportStrategy {boolean calculateReport(int departmentId); }// 2.实现具体策略 public class BDGernerateReportStrategy implements GernerateReportStrategy {@Overridepublic boolean calculateReport(int departmentId) {......} } public class SwGernerateReportStrategy implements GernerateReportStrategy {@Overridepublic boolean calculateReport(int departmentId) {......} } // 3.创建上下文 public class DownloadReportContext {private GernerateReportStrategy gernerateReportStrategy;public void setGernerateReportStrategy(GernerateReportStrategy gernerateReportStrategy) {this.gernerateReportStrategy = gernerateReportStrategy;}...... } // 4.接下来就可以使用了,若后续有新增部门则直接实现具体策略类即可
结构型模式
代理模式
- 核心思想:是为其他对象提供一种代理以控制对这个对象的访问
- 角色:代理角色、真实/原始/目标角色
- 作用:一是保护真实/原始/目标对象,二是增强真实/原始/目标对象
静态代理
- 静态代理是一种在编译时就已经确定代理类和目标对象关系的代理模式。它通常通过创建一个接口和两个实现这个接口的类(一个为目标对象类,另一个为代理类)来实现
- 代码实践
-
// 1.定义一个接口,该接口包含一个或多个方法 interface Service {void execute(); } // 2.创建一个目标对象类,它实现这个接口 class RealService implements Service {public void execute() {System.out.println("Executing real service.");} } // 3.创建一个代理类,也实现这个接口,并包含对目标对象的引用。也可以在调用目标对象的方法之前或之后添加额外的操作 class ProxyService implements Service {private RealService realService;public ProxyService(RealService realService) {this.realService = realService;}public void execute() {System.out.println("Before execution.");realService.execute();System.out.println("After execution.");} } // 4.客户端使用 Service service = new ProxyService(new RealService()); service.execute();
-
动态代理
- 动态代理是一种在运行时动态创建代理对象的代理模式。它不需要事先编写代理类的代码,而是在运行时根据目标对象动态生成代理类
- 项目实践
-
// 1. 定义接口 public interface Report {void generateReportByDepartmentId(int departmentId);void generateReportByDepartmentName(String departmentName); } // 2. 定义目标/原始/真实对象 public class generateReport implements Report {@Overridepublic void generateReportByDepartmentId(int departmentId) {System.out.println("按部门ID已生成报表:" + departmentId);}@Overridepublic void generateReportByDepartmentName(String departmentName) {System.out.println("按部门名称已生成报表:" + departmentName);} } // 3. 定义代理对象 public class ReportJDKProxy implements InvocationHandler {//需要被代理的对象private Object object;public ReportJDKProxy(Object object) {this.object = object;}@SuppressWarnings("unchecked")public <T> T getProxy(){// 使用反射API动态创建代理类return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),//当前线程的上下文ClassLoaderobject.getClass().getInterfaces(), //代理需要实现的接口this); // 处理器自身}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = null;//进行方法匹配,调用对应方法名的方法if ("generateReportByDepartmentId".equals(method.getName())) {System.out.println("按部门ID已生成报表------前置增强------");result=method.invoke(object, args);System.out.println("按部门ID已生成报表------后置增强------");}if ("generateReportByDepartmentName".equals(method.getName())) {System.out.println("按部门名称已生成报表------前置增强------");result=method.invoke(object, args);System.out.println("按部门名称已生成报表------后置增强------");}return result;} } // 4. 客户端使用// 调用方式一Report player=new generateReport(); Report proxy=new ReportJDKProxy(player).getProxy(); proxy.generateReportByDepartmentId(666);proxy.generateReportByDepartmentName("SW");/** // 调用方式二 * Report p=new generateReport(); * Report o = (Report)Proxy.newProxyInstance( p.getClass().getClassLoader(),p.getClass().getInterfaces(), new ReportJDKProxy(p) );* o.generateReportByDepartmentId(666); * o.generateReportByDepartmentName("SW");*/
-