自己做圖片網(wǎng)站競價排名服務
概述
設計模式就是經過我們開發(fā)人員通過長時間的開發(fā)實踐得出的一種開發(fā)模式,目的就是在開發(fā)過程中降低代碼耦合度,提高代碼可復用性/擴展/維護。目前設計模式可以分為創(chuàng)建型模式、行為型模式、結構型模式,一共包括23種設計模式。本文列舉了實際項目中使用到的設計模式,包括單例模式、策略模式、代理模式
創(chuàng)建型模式
單例模式
- 目的就是解決一個類Class在應用程序中只有一個實例存在,并提供對外的全局訪問
- 構造函數(shù)私有化、對外提供獲取實例靜態(tài)方法
- 項目實踐
- 在多線程環(huán)境中緩存文件操作記錄到隊列中,后續(xù)通過定時任務添加到數(shù)據(jù)庫
-
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)模式
- 定義了一組算法,將每一個算法封裝到具有共同接口的獨立的類中,使得它們可以相互替換。常常適用于業(yè)務存在很多復雜分支場景
- 上下文/Context(持有策略對象的引用,通過該引用來調用算法或行為)、策略/Strategy(定義所有支持的算法的公共接口)、具體策略/Concrete Strategy(實現(xiàn)策略接口的具體算法或行為)
- 項目實踐
- 系統(tǒng)需要根據(jù)不同部門來計算報表生成的內容
-
// 1.定義策略接口 public interface GernerateReportStrategy {boolean calculateReport(int departmentId); }// 2.實現(xiàn)具體策略 public class BDGernerateReportStrategy implements GernerateReportStrategy {@Overridepublic boolean calculateReport(int departmentId) {......} } public class SwGernerateReportStrategy implements GernerateReportStrategy {@Overridepublic boolean calculateReport(int departmentId) {......} } // 3.創(chuàng)建上下文 public class DownloadReportContext {private GernerateReportStrategy gernerateReportStrategy;public void setGernerateReportStrategy(GernerateReportStrategy gernerateReportStrategy) {this.gernerateReportStrategy = gernerateReportStrategy;}...... } // 4.接下來就可以使用了,若后續(xù)有新增部門則直接實現(xiàn)具體策略類即可
結構型模式
代理模式
- 核心思想:為其他對象提供一種代理以控制對這個對象的訪問
- 角色:代理角色、真實/原始/目標角色
- 作用:一是保護真實/原始/目標對象,二是增強真實/原始/目標對象
靜態(tài)代理
- 靜態(tài)代理是一種在編譯時就已經確定代理類和目標對象關系的代理模式。它通常通過創(chuàng)建一個接口和兩個實現(xiàn)這個接口的類(一個為目標對象類,另一個為代理類)來實現(xiàn)
- 代碼實踐
-
// 1.定義一個接口,該接口包含一個或多個方法 interface Service {void execute(); } // 2.創(chuàng)建一個目標對象類,它實現(xiàn)這個接口 class RealService implements Service {public void execute() {System.out.println("Executing real service.");} } // 3.創(chuàng)建一個代理類,也實現(xiàn)這個接口,并包含對目標對象的引用。也可以在調用目標對象的方法之前或之后添加額外的操作 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();
-
動態(tài)代理
- 動態(tài)代理是一種在運行時動態(tài)創(chuàng)建代理對象的代理模式。不需要事先編寫代理類代碼,而是在運行時根據(jù)目標對象動態(tài)生成代理類
- JDK動態(tài)代理 VS Cglib動態(tài)代理
- 代理的目標對象要求
- JDK要求目標類必須實現(xiàn)接口,而Cglib提供更大的靈活性,目標類實現(xiàn)接口或者只是普通類都可以(基于此SpringBoot2.x以上默認使用CGLIB代理)
- 代理對象的創(chuàng)建方式
- JDK通過Proxy類和實現(xiàn)InvocationHandler接口來創(chuàng)建代理對象; Cglib通過Enhancer類直接創(chuàng)建代理對象
- 執(zhí)行性能
- JDK動態(tài)通過反射實現(xiàn),Cglib則使用字節(jié)碼生成技術直接操作字節(jié)碼,因此在一些場景下,Cglib更加高效
- 通常情況下,我們開發(fā)人員不需要在配置文件中明確指定AOP使用的代理方式,因為Spring會自動根據(jù)目標對象的類型選擇代理方式
- 代理的目標對象要求
- JDK動態(tài)代理 VS Cglib動態(tài)代理
- 項目實踐
- JDK動態(tài)代理代碼實踐
// 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動態(tài)創(chuàng)建代理類return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),//當前線程的上下文ClassLoaderobject.getClass().getInterfaces(), //代理需要實現(xiàn)的接口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");*/
- Cglib動態(tài)代理代碼實踐
-
// 1. 創(chuàng)建目標對象/接口實現(xiàn)類 class ToReport{public void generateReport() {System.out.println("生成報表---CglibProxy");} } // 2. 創(chuàng)建代理對象 class CglibProxy implements MethodInterceptor {/*** @param o: 代理對象* @param method: 被代理方法* @param params: 方法入?yún)? @param methodProxy: CGLIB方法**/@Overridepublic Object intercept(Object o, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {System.out.println("【Cglib前置方法】代理對象正在執(zhí)行的方法:" + method.getName());Object result = methodProxy.invokeSuper(o, params);System.out.println("【Cglib后置方法】代理對象正在執(zhí)行的方法:" + method.getName());return result;} } // 3. 創(chuàng)建Enhancer(設置要被代理的類和調用方法時觸發(fā)的攔截器) class CglibProxyFactory{public static Object creatCglibProxyObj(Class<?> clazz) {Enhancer enhancer = new Enhancer();// 為加強器指定要代理的業(yè)務類(即為下面生成的代理類指定父類)enhancer.setSuperclass(clazz);// 設置回調:對于代理類上所有方法的調用,都會調用CallBack,而Callback則需要實現(xiàn)intercept()方法enhancer.setCallback(new CglibProxy());return enhancer.create();} } // 4. 客戶端使用 public static void main(String[] args) { ToReport report = (ToReport)CglibProxyFactory.creatCglibProxyObj(ToReport.class);report.generateReport(); }
-