Java使用設(shè)計(jì)模式中的代理模式構(gòu)建項(xiàng)目的實(shí)例展示
概念
代理模式(Proxy):代理模式其實(shí)就是多一個(gè)代理類出來(lái),替原對(duì)象進(jìn)行一些操作。比如咱有的時(shí)候打官司需要請(qǐng)律師,因?yàn)槁蓭熢诜煞矫嬗袑iL(zhǎng),可以替咱進(jìn)行操作表達(dá)咱的想法,這就是代理的意思。代理模式分為兩類:1、靜態(tài)代理(不使用jdk里面的方法);2、動(dòng)態(tài)代理(使用jdk里面的InvocationHandler和Proxy)。
靜態(tài)代理由程序員創(chuàng)建或工具生成代理類的源碼,再編譯代理類。所謂靜態(tài)也就是在程序運(yùn)行前就已經(jīng)存在代理類的字節(jié)碼文件,代理類和委托類的關(guān)系在運(yùn)行前就確定了。
動(dòng)態(tài)代理類的源碼是在程序運(yùn)行期間由JVM根據(jù)反射等機(jī)制動(dòng)態(tài)的生成,所以不存在代理類的字節(jié)碼文件。代理類和委托類的關(guān)系是在程序運(yùn)行時(shí)確定。
示例
這里我們舉一個(gè)靜態(tài)代理的例子:
類圖:
/** * 游戲者接口 * */ public interface IGamePlayer { // 登錄游戲 public void login(String user, String password); // 殺怪,網(wǎng)絡(luò)游戲的主要特色 public void killBoss(); // 升級(jí) public void upgrade(); }
/** * 游戲者 * */ public class GamePlayer implements IGamePlayer { private String name = ""; // 通過(guò)構(gòu)造函數(shù)傳遞名稱 public GamePlayer(String _name) { this.name = _name; } // 打怪,最期望的就是殺老怪 public void killBoss() { System.out.println(this.name + " 在打怪!"); } // 進(jìn)游戲之前你肯定要登錄吧,這是一個(gè)必要條件 public void login(String user, String password) { System.out.println("登錄名為" + user + " 的角色 " + this.name + "登錄成功!"); } // 升級(jí),升級(jí)有很多方法,花錢買是一種,做任務(wù)也是一種 public void upgrade() { System.out.println(this.name + " 又升了一級(jí)!"); } }
/** * 客戶端 對(duì)被代理對(duì)象不可見 */ public class GamePlayerProxy implements IGamePlayer { private IGamePlayer gamePlayer = null;//被代理對(duì)象 // 通過(guò)構(gòu)造函數(shù)傳遞要對(duì)誰(shuí)進(jìn)行代練 public GamePlayerProxy(String username) { this.gamePlayer = new GamePlayer(username); } // 代練殺怪 public void killBoss() { this.gamePlayer.killBoss(); } // 代練登錄 public void login(String user, String password) { this.gamePlayer.login(user, password); } // 代練升級(jí) public void upgrade() { this.gamePlayer.upgrade(); } }
/* * 客戶端 對(duì)被代理對(duì)象不可見 */ public class GamePlayerProxy2 implements IGamePlayer { private IGamePlayer gamePlayer = null;//被代理對(duì)象 // 通過(guò)構(gòu)造函數(shù)傳遞要對(duì)誰(shuí)進(jìn)行代練 public GamePlayerProxy2(String username) { this.gamePlayer = new GamePlayer(username); } // 代練殺怪 public void killBoss() { this.gamePlayer.killBoss(); } // 代練登錄 public void login(String user, String password) { System.out.println("登錄時(shí)間是:" + new Date().toLocaleString()); this.gamePlayer.login(user, password); } // 代練升級(jí) public void upgrade() { this.gamePlayer.upgrade(); System.out.println("升級(jí)時(shí)間是:" + new Date().toLocaleString()); } }
/* * 客戶端 對(duì)被代理對(duì)象不可見 */ public class GamePlayerProxy3 { private IGamePlayer gamePlayer; // 通過(guò)構(gòu)造函數(shù)傳遞 被代練(代理)對(duì)象 public GamePlayerProxy3(IGamePlayer gamePlayer) { this.gamePlayer = gamePlayer; System.out.println("我是一名代練,我玩的角色是別人的,可以動(dòng)態(tài)傳遞進(jìn)來(lái)"); } public IGamePlayer getProxy() { return (IGamePlayer) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{IGamePlayer.class}, new MyInvocationHandler()); } private class MyInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("login")) { System.out.println("登錄時(shí)間是:" + new Date().toLocaleString()); } if (method.getName().equals("upgrade")) { System.out.println("升級(jí)時(shí)間是:" + new Date().toLocaleString()); } method.invoke(gamePlayer, args); return null; } } }
public class Test { public static void main(String[] args) { /* * 普通的靜態(tài)代理: 客戶端不知道被代理對(duì)象,由代理對(duì)象完成其功能的調(diào)用 */ IGamePlayer proxy = new GamePlayerProxy("X"); System.out.println("開始時(shí)間是:" + new Date().toLocaleString()); proxy.login("zhangSan", "abcd"); proxy.killBoss(); proxy.upgrade(); System.out.println("結(jié)束時(shí)間是:" + new Date().toLocaleString()); System.out.println(); /* * 代理對(duì)象 增強(qiáng)了 被代理對(duì)象的功能 */ IGamePlayer proxy2 = new GamePlayerProxy2("M"); proxy2.login("lisi", "efg"); proxy2.killBoss(); proxy2.upgrade(); System.out.println(); /* * 動(dòng)態(tài)代理:使用jdk提供的InvocationHandler,反射調(diào)用被代理對(duì)象的方法 * 結(jié)合java.reflect.Proxy 產(chǎn)生代理對(duì)象 * 動(dòng)態(tài)傳入被代理對(duì)象構(gòu)造InvocationHandler,在handler中的invoke時(shí)可以增強(qiáng)被代理對(duì)象的方法的功能 * 或者說(shuō):(面向切面:)在什么地方(連接點(diǎn)), 執(zhí)行什么行為(通知) * GamePlayerProxy3中是方法名為login時(shí)通知開始時(shí)間,upgrade時(shí)通知結(jié)束時(shí)間 */ GamePlayerProxy3 dynamic = new GamePlayerProxy3(new GamePlayer("Y")); IGamePlayer dynamicPlayer = dynamic.getProxy(); dynamicPlayer.login("wangwu", "1234"); dynamicPlayer.killBoss(); dynamicPlayer.upgrade(); /* * 面向切面: 一些相似的業(yè)務(wù)邏輯需要加在眾多的地方,那們就可以把它提取到切面中, 切面也就是事務(wù)切面:如日志切面、權(quán)限切面、業(yè)務(wù)切面 */ } }
打?。?br />
開始時(shí)間是:2014-10-8 17:19:05 登錄名為zhangSan 的角色 X登錄成功! X 在打怪! X 又升了一級(jí)! 結(jié)束時(shí)間是:2014-10-8 17:19:05 登錄時(shí)間是:2014-10-8 17:19:05 登錄名為lisi 的角色 M登錄成功! M 在打怪! M 又升了一級(jí)! 升級(jí)時(shí)間是:2014-10-8 17:19:05 我是一名代練,我玩的角色是別人的,可以動(dòng)態(tài)傳遞進(jìn)來(lái) 登錄時(shí)間是:2014-10-8 17:19:05 登錄名為wangwu 的角色 Y登錄成功! Y 在打怪! 升級(jí)時(shí)間是:2014-10-8 17:19:05 Y 又升了一級(jí)!
優(yōu)點(diǎn)
(1)職責(zé)清晰
真實(shí)的角色就是實(shí)現(xiàn)實(shí)際的業(yè)務(wù)邏輯,不用關(guān)心其他非本職責(zé)的事務(wù),通過(guò)后期的代理完成一件完成事務(wù),附帶的結(jié)果就是編程簡(jiǎn)潔清晰。
(2)代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之間起到中介的作用,這樣起到了的作用和保護(hù)了目標(biāo)對(duì)象的作用。
(3)高擴(kuò)展性
- 詳解JAVA設(shè)計(jì)模式之代理模式
- Java設(shè)計(jì)模式之動(dòng)態(tài)代理模式實(shí)例分析
- Java設(shè)計(jì)模式之靜態(tài)代理模式實(shí)例分析
- 23種設(shè)計(jì)模式(7) java代理模式
- java設(shè)計(jì)模式筆記之代理模式
- java設(shè)計(jì)模式學(xué)習(xí)之代理模式
- java設(shè)計(jì)模式-代理模式(實(shí)例講解)
- Java設(shè)計(jì)模式之代理模式與裝飾模式實(shí)例詳解
- Java設(shè)計(jì)模式之代理模式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- java設(shè)計(jì)模式之代理模式(Porxy)詳解
- java設(shè)計(jì)模式—靜態(tài)代理模式(聚合與繼承方式對(duì)比)
- 詳解設(shè)計(jì)模式中的proxy代理模式及在Java程序中的實(shí)現(xiàn)
- 實(shí)例講解Java設(shè)計(jì)模式編程中如何運(yùn)用代理模式
- Java設(shè)計(jì)模式之代理模式(Proxy模式)介紹
- Java通俗易懂系列設(shè)計(jì)模式之代理模式
相關(guān)文章
關(guān)于@Configuration的作用說(shuō)明
這篇文章主要介紹了關(guān)于@Configuration的作用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01解決Spring?AOP攔截抽象類(父類)中方法失效問(wèn)題
這篇文章主要介紹了解決Spring?AOP攔截抽象類(父類)中方法失效問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11SpringBoot圖文并茂講解Lombok庫(kù)的安裝與使用
Lombok想要解決了的是在我們實(shí)體Bean中大量的Getter/Setter方法,以及toString, hashCode等可能不會(huì)用到,但是某些時(shí)候仍然需要復(fù)寫,以期方便使用的方法;在使用Lombok之后,將由其來(lái)自動(dòng)幫你實(shí)現(xiàn)代碼生成2022-06-06Spring Boot項(xiàng)目使用Flyway的詳細(xì)教程
這篇文章主要介紹了Spring Boot項(xiàng)目使用Flyway,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07Java內(nèi)存模型之happens-before概念詳解
happens-before原則非常重要,它是判斷數(shù)據(jù)是否存在競(jìng)爭(zhēng)、線程是否安全的主要依據(jù),依靠這個(gè)原則,我們解決在并發(fā)環(huán)境下兩操作之間是否可能存在沖突的所有問(wèn)題。下面我們就一個(gè)簡(jiǎn)單的例子稍微了解下happens-before知識(shí),感興趣的朋友一起看看吧2021-06-06Springboot集成restTemplate過(guò)程詳解
這篇文章主要介紹了Springboot集成restTemplate過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04