Java使用設(shè)計模式中的代理模式構(gòu)建項目的實例展示
概念
代理模式(Proxy):代理模式其實就是多一個代理類出來,替原對象進行一些操作。比如咱有的時候打官司需要請律師,因為律師在法律方面有專長,可以替咱進行操作表達咱的想法,這就是代理的意思。代理模式分為兩類:1、靜態(tài)代理(不使用jdk里面的方法);2、動態(tài)代理(使用jdk里面的InvocationHandler和Proxy)。
靜態(tài)代理由程序員創(chuàng)建或工具生成代理類的源碼,再編譯代理類。所謂靜態(tài)也就是在程序運行前就已經(jīng)存在代理類的字節(jié)碼文件,代理類和委托類的關(guān)系在運行前就確定了。
動態(tài)代理類的源碼是在程序運行期間由JVM根據(jù)反射等機制動態(tài)的生成,所以不存在代理類的字節(jié)碼文件。代理類和委托類的關(guān)系是在程序運行時確定。
示例
這里我們舉一個靜態(tài)代理的例子:
類圖:

/**
* 游戲者接口
*
*/
public interface IGamePlayer {
// 登錄游戲
public void login(String user, String password);
// 殺怪,網(wǎng)絡(luò)游戲的主要特色
public void killBoss();
// 升級
public void upgrade();
}
/**
* 游戲者
*
*/
public class GamePlayer implements IGamePlayer {
private String name = "";
// 通過構(gòu)造函數(shù)傳遞名稱
public GamePlayer(String _name) {
this.name = _name;
}
// 打怪,最期望的就是殺老怪
public void killBoss() {
System.out.println(this.name + " 在打怪!");
}
// 進游戲之前你肯定要登錄吧,這是一個必要條件
public void login(String user, String password) {
System.out.println("登錄名為" + user + " 的角色 " + this.name + "登錄成功!");
}
// 升級,升級有很多方法,花錢買是一種,做任務也是一種
public void upgrade() {
System.out.println(this.name + " 又升了一級!");
}
}
/**
* 客戶端 對被代理對象不可見
*/
public class GamePlayerProxy implements IGamePlayer {
private IGamePlayer gamePlayer = null;//被代理對象
// 通過構(gòu)造函數(shù)傳遞要對誰進行代練
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);
}
// 代練升級
public void upgrade() {
this.gamePlayer.upgrade();
}
}
/*
* 客戶端 對被代理對象不可見
*/
public class GamePlayerProxy2 implements IGamePlayer {
private IGamePlayer gamePlayer = null;//被代理對象
// 通過構(gòu)造函數(shù)傳遞要對誰進行代練
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("登錄時間是:" + new Date().toLocaleString());
this.gamePlayer.login(user, password);
}
// 代練升級
public void upgrade() {
this.gamePlayer.upgrade();
System.out.println("升級時間是:" + new Date().toLocaleString());
}
}
/*
* 客戶端 對被代理對象不可見
*/
public class GamePlayerProxy3 {
private IGamePlayer gamePlayer;
// 通過構(gòu)造函數(shù)傳遞 被代練(代理)對象
public GamePlayerProxy3(IGamePlayer gamePlayer) {
this.gamePlayer = gamePlayer;
System.out.println("我是一名代練,我玩的角色是別人的,可以動態(tà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("登錄時間是:" + new Date().toLocaleString());
} if (method.getName().equals("upgrade")) {
System.out.println("升級時間是:" + new Date().toLocaleString());
}
method.invoke(gamePlayer, args);
return null;
}
}
}
public class Test {
public static void main(String[] args) {
/*
* 普通的靜態(tài)代理: 客戶端不知道被代理對象,由代理對象完成其功能的調(diào)用
*/
IGamePlayer proxy = new GamePlayerProxy("X");
System.out.println("開始時間是:" + new Date().toLocaleString());
proxy.login("zhangSan", "abcd");
proxy.killBoss();
proxy.upgrade();
System.out.println("結(jié)束時間是:" + new Date().toLocaleString());
System.out.println();
/*
* 代理對象 增強了 被代理對象的功能
*/
IGamePlayer proxy2 = new GamePlayerProxy2("M");
proxy2.login("lisi", "efg");
proxy2.killBoss();
proxy2.upgrade();
System.out.println();
/*
* 動態(tài)代理:使用jdk提供的InvocationHandler,反射調(diào)用被代理對象的方法
* 結(jié)合java.reflect.Proxy 產(chǎn)生代理對象
* 動態(tài)傳入被代理對象構(gòu)造InvocationHandler,在handler中的invoke時可以增強被代理對象的方法的功能
* 或者說:(面向切面:)在什么地方(連接點), 執(zhí)行什么行為(通知)
* GamePlayerProxy3中是方法名為login時通知開始時間,upgrade時通知結(jié)束時間
*/
GamePlayerProxy3 dynamic = new GamePlayerProxy3(new GamePlayer("Y"));
IGamePlayer dynamicPlayer = dynamic.getProxy();
dynamicPlayer.login("wangwu", "1234");
dynamicPlayer.killBoss();
dynamicPlayer.upgrade();
/*
* 面向切面: 一些相似的業(yè)務邏輯需要加在眾多的地方,那們就可以把它提取到切面中, 切面也就是事務切面:如日志切面、權(quán)限切面、業(yè)務切面
*/
}
}
打?。?br />
開始時間是:2014-10-8 17:19:05 登錄名為zhangSan 的角色 X登錄成功! X 在打怪! X 又升了一級! 結(jié)束時間是:2014-10-8 17:19:05 登錄時間是:2014-10-8 17:19:05 登錄名為lisi 的角色 M登錄成功! M 在打怪! M 又升了一級! 升級時間是:2014-10-8 17:19:05 我是一名代練,我玩的角色是別人的,可以動態(tài)傳遞進來 登錄時間是:2014-10-8 17:19:05 登錄名為wangwu 的角色 Y登錄成功! Y 在打怪! 升級時間是:2014-10-8 17:19:05 Y 又升了一級!
優(yōu)點
(1)職責清晰
真實的角色就是實現(xiàn)實際的業(yè)務邏輯,不用關(guān)心其他非本職責的事務,通過后期的代理完成一件完成事務,附帶的結(jié)果就是編程簡潔清晰。
(2)代理對象可以在客戶端和目標對象之間起到中介的作用,這樣起到了的作用和保護了目標對象的作用。
(3)高擴展性
- 詳解JAVA設(shè)計模式之代理模式
- Java設(shè)計模式之動態(tài)代理模式實例分析
- Java設(shè)計模式之靜態(tài)代理模式實例分析
- 23種設(shè)計模式(7) java代理模式
- java設(shè)計模式筆記之代理模式
- java設(shè)計模式學習之代理模式
- java設(shè)計模式-代理模式(實例講解)
- Java設(shè)計模式之代理模式與裝飾模式實例詳解
- Java設(shè)計模式之代理模式_動力節(jié)點Java學院整理
- java設(shè)計模式之代理模式(Porxy)詳解
- java設(shè)計模式—靜態(tài)代理模式(聚合與繼承方式對比)
- 詳解設(shè)計模式中的proxy代理模式及在Java程序中的實現(xiàn)
- 實例講解Java設(shè)計模式編程中如何運用代理模式
- Java設(shè)計模式之代理模式(Proxy模式)介紹
- Java通俗易懂系列設(shè)計模式之代理模式
相關(guān)文章
Java內(nèi)存模型之happens-before概念詳解
happens-before原則非常重要,它是判斷數(shù)據(jù)是否存在競爭、線程是否安全的主要依據(jù),依靠這個原則,我們解決在并發(fā)環(huán)境下兩操作之間是否可能存在沖突的所有問題。下面我們就一個簡單的例子稍微了解下happens-before知識,感興趣的朋友一起看看吧2021-06-06

