成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java設(shè)計(jì)模式之(五)——代理模式

李文鵬 / 482人閱讀

摘要:什么是代理模式什么是代理模式為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。另外一種方式是動(dòng)態(tài)代理。代理模式應(yīng)用場(chǎng)景代理模式應(yīng)用場(chǎng)景業(yè)務(wù)系統(tǒng)的非功能性需求開發(fā)這是最常用的一個(gè)場(chǎng)景。

1、什么是代理模式

Provide a surrogate or placeholder for another object to control access to it.

Proxy Pattern:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。

說人話:在不改變?cè)碱悾ɑ蚪斜淮眍悾┐a的情況下,通過引入代理類來給原始類附加功能,比如Spring AOP。

2、代理模式定義

①、Subject

抽象主題角色,可以是抽象類,可以是接口,是一個(gè)最普通的業(yè)務(wù)類定義,無特殊要求。

②、RealSubject

真實(shí)主題角色,也叫被代理角色,是業(yè)務(wù)邏輯的具體執(zhí)行者。

③、Proxy

代理主題角色,也叫代理類,它負(fù)責(zé)對(duì)真實(shí)角色的應(yīng)用,把所有抽象主題類定義的方法限制委托給真實(shí)主題角色實(shí)現(xiàn),并在真實(shí)主題角色處理前后做一些預(yù)處理或善后工作。

通用代碼如下:

/** * 抽象主題類 */public interface Subject {    void doSomething();}
/** * 真實(shí)主題角色 */public class RealSubject implements Subject{    @Override    public void doSomething() {        //TODO 具體執(zhí)行的事    }}
/** * 代理主題角色 */public class Proxy implements Subject{    //要代理的具體實(shí)現(xiàn)類    private Subject realSubject;    public Proxy(Subject realSubject){        this.realSubject = realSubject;    }    @Override    public void doSomething() {        this.before();        realSubject.doSomething();        this.after();    }    // 預(yù)處理    private void before(){        // TODO    }    // 善后處理    private void after(){        // TODO    }}

3、代理模式的兩種實(shí)現(xiàn)

比如用代理模式實(shí)現(xiàn)統(tǒng)計(jì)某個(gè)接口的耗時(shí)。

3.1 靜態(tài)代理

①、基于接口編程

抽象主題類:

public interface IUserController {    // 登錄    String login(String username,String password);    // 注冊(cè)    String register(String username,String password);}

具體主題類:

public class UserController implements IUserController{    @Override    public String login(String username, String password) {        // TODO 登錄邏輯        return null;    }    @Override    public String register(String username, String password) {        // TODO 注冊(cè)邏輯        return null;    }}

代理主題類:

public class UserControllerProxy implements IUserController{    private IUserController userController;    public UserControllerProxy(IUserController userController){        this.userController = userController;    }    @Override    public String login(String username, String password) {        long startTime = System.currentTimeMillis();        // 登錄邏輯        userController.login("username","password");        long endTime = System.currentTimeMillis();        long responseTime = endTime - startTime;        System.out.println("接口響應(yīng)時(shí)間:"+responseTime);        return null;    }    @Override    public String register(String username, String password) {        long startTime = System.currentTimeMillis();        // 注冊(cè)邏輯        userController.register("username","password");        long endTime = System.currentTimeMillis();        long responseTime = endTime - startTime;        System.out.println("接口響應(yīng)時(shí)間:"+responseTime);        return null;    }}

測(cè)試:

因?yàn)樵碱?UserController 和代理類 UserControllerProxy 實(shí)現(xiàn)相同的接口,是基于接口而非實(shí)現(xiàn)編程,將UserController類對(duì)象替換為UserControllerProxy類對(duì)象,不需要改動(dòng)太多代碼

public class StaticProxyTest {    public static void main(String[] args) {        IUserController userController = new UserControllerProxy(new UserController());        userController.login("username","password");        userController.register("username","password");    }}

在上面的代碼中,代理類和具體主題類需要實(shí)現(xiàn)相同的接口,假如具體主題類沒有實(shí)現(xiàn)接口,并且不是我們開發(fā)維護(hù)的(比如來自第三方接口),我們要統(tǒng)計(jì)這個(gè)第三方接口的耗時(shí),那應(yīng)該如何實(shí)現(xiàn)代理模式呢?

②、基于繼承

繼承具體主題類,然后擴(kuò)展其方法即可,直接看代碼。

public class UserControllerProxy extends UserController {    @Override    public String login(String username, String password) {        long startTime = System.currentTimeMillis();        // 登錄邏輯        super.login("username","password");        long endTime = System.currentTimeMillis();        long responseTime = endTime - startTime;        System.out.println("接口響應(yīng)時(shí)間:"+responseTime);        return null;    }    @Override    public String register(String username, String password) {        long startTime = System.currentTimeMillis();        // 注冊(cè)邏輯        super.register("username","password");        long endTime = System.currentTimeMillis();        long responseTime = endTime - startTime;        System.out.println("接口響應(yīng)時(shí)間:"+responseTime);        return null;    }}

3.2 動(dòng)態(tài)代理

在上面的例子中,有兩個(gè)問題:

①、我們需要在代理類中,將具體主題類中的所有的方法,都重新實(shí)現(xiàn)一遍,并且為每個(gè)方法都附加相似的代碼邏輯,如果方法很多,重復(fù)代碼也會(huì)很多。

②、如果要添加的附加功能的類有不止一個(gè),我們需要針對(duì)每個(gè)類都創(chuàng)建一個(gè)代理類。

那該如何解決上面的問題呢?答案就是動(dòng)態(tài)代理(Dynamic Proxy)。

動(dòng)態(tài)代理:不事先為每個(gè)原始類編寫代理類,而是在運(yùn)行的時(shí)候,動(dòng)態(tài)地創(chuàng)建原始類對(duì)應(yīng)的代理類,然后在系統(tǒng)中用代理類替換掉原始類。

JDK動(dòng)態(tài)代理:

public class DynamicProxyHandler implements InvocationHandler {    private Object target;    public DynamicProxyHandler(Object target){        this.target = target;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        long startTime = System.currentTimeMillis();        Object result = method.invoke(this.target, args);        long endTime = System.currentTimeMillis();        long responseTime = endTime - startTime;        System.out.println("接口響應(yīng)時(shí)間:"+responseTime);        return result;    }}

測(cè)試:

public class DynamicProxyTest {    public static void main(String[] args) {        // 1、創(chuàng)建具體主題類        IUserController userController = new UserController();        // 2、創(chuàng)建 Handler        DynamicProxyHandler proxyHandler = new DynamicProxyHandler(userController);        // 3、動(dòng)態(tài)產(chǎn)生代理類        IUserController o = (IUserController)Proxy.newProxyInstance(userController.getClass().getClassLoader(),                userController.getClass().getInterfaces(),                proxyHandler);        o.login("username","password");        o.register("username","password");    }}

這是 JDK 動(dòng)態(tài)代理,利用反射機(jī)制生成一個(gè)實(shí)現(xiàn)代理接口的匿名類,在調(diào)用具體方法前調(diào)用InvokeHandler來處理,代理對(duì)象是在程序運(yùn)行時(shí)產(chǎn)生的,而不是編譯期,要求是具體主題類必須實(shí)現(xiàn)接口。

另外一種方式是 Cglib 動(dòng)態(tài)代理。CGLIB(Code Generation Library)是一個(gè)基于ASM的字節(jié)碼生成庫(kù),它允許我們?cè)谶\(yùn)行時(shí)對(duì)字節(jié)碼進(jìn)行修改和動(dòng)態(tài)生成,也就是通過修改字節(jié)碼生成子類來處理。

Cglib 動(dòng)態(tài)代理:

public class UserController{    public String login(String username, String password) {        // TODO 登錄邏輯        System.out.println("登錄");        return null;    }    public String register(String username, String password) {        // TODO 注冊(cè)邏輯        System.out.println("注冊(cè)");        return null;    }}

注意:真實(shí)主題類是沒有實(shí)現(xiàn)接口的。

public class CglibDynamicProxy implements MethodInterceptor {    private Object target;    public CglibDynamicProxy(Object target){        this.target = target;    }    // 給目標(biāo)創(chuàng)建代理對(duì)象    public Object newProxyInstance(){        // 1.工具類        Enhancer enhancer = new Enhancer();        // 2.設(shè)置父類        enhancer.setSuperclass(target.getClass());        // 3.設(shè)置回調(diào)函數(shù)        enhancer.setCallback(this);        // 4.創(chuàng)建子類(代理對(duì)象)        return enhancer.create();    }    @Override    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {        long startTime = System.currentTimeMillis();        Object result = method.invoke(this.target, args);        long endTime = System.currentTimeMillis();        long responseTime = endTime - startTime;        System.out.println("接口響應(yīng)時(shí)間:"+responseTime);        return result;    }}

測(cè)試:

public class CglibDynamicProxyTest {    public static void main(String[] args) {        UserController userController = new UserController();        CglibDynamicProxy cglibDynamicProxy = new CglibDynamicProxy(userController);        UserController o = (UserController)cglibDynamicProxy.newProxyInstance();        o.login("username","password");        o.register("username","password");    }}

4、代理模式優(yōu)點(diǎn)

①、職責(zé)清晰

真實(shí)的角色就是實(shí)現(xiàn)實(shí)際的業(yè)務(wù)邏輯, 不用關(guān)心其他非本職責(zé)的事務(wù), 通過后期的代理完成一件事務(wù), 附帶的結(jié)果就是編程簡(jiǎn)潔清晰。

②、高擴(kuò)展性

具體主題角色是隨時(shí)都會(huì)發(fā)生變化的, 只要它實(shí)現(xiàn)了接口, 甭管它如何變化,代理類完全都可以在不做任何修改的情況下使用。

5、代理模式應(yīng)用場(chǎng)景

①、業(yè)務(wù)系統(tǒng)的非功能性需求開發(fā)

這是最常用的一個(gè)場(chǎng)景。比如:監(jiān)控、統(tǒng)計(jì)、鑒權(quán)、限流、事務(wù)、冪等、日志。我們將這些附加功能與業(yè)務(wù)功能解耦,放到代理類中統(tǒng)一處理,讓程序員只需要關(guān)注業(yè)務(wù)方面的開發(fā)。

典型例子就是 SpringAOP。

②、RPC

RPC(遠(yuǎn)程代理) 框架也可以看作一種代理模式,通過遠(yuǎn)程代理,將網(wǎng)絡(luò)通信、數(shù)據(jù)編解碼等細(xì)節(jié)隱藏起來。客戶端在使用 RPC 服務(wù)的時(shí)候,就像使用本地函數(shù)一樣,無需了解跟服務(wù)器交互的細(xì)節(jié)。除此之外,RPC 服務(wù)的開發(fā)者也只需要開發(fā)業(yè)務(wù)邏輯,就像開發(fā)本地使用的函數(shù)一樣,不需要關(guān)注跟客戶端的交互細(xì)節(jié)。

作者:IT可樂
出處:http://www.cnblogs.com/ysocean/

資源:微信搜【IT可樂】關(guān)注我,回復(fù) 【電子書】有我特別篩選的免費(fèi)電子書。
本文版權(quán)歸作者所有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意不能轉(zhuǎn)載,否則保留追究法律責(zé)任的權(quán)利。
?

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/124128.html

相關(guān)文章

  • java設(shè)計(jì)模式動(dòng)態(tài)代理

    摘要:場(chǎng)景描述病從口入這句成語(yǔ)告訴我們注意飲食健康,小六同學(xué)想吃蘋果,在吃蘋果之前需要清洗一下蘋果和洗一下手,吃完蘋果后,需要洗一下手保持個(gè)人衛(wèi)生十分鐘后。。。動(dòng)態(tài)代理小六委托管家來代理洗食物和洗手,小六屬于委托對(duì)象,管家屬于代理對(duì)象。 前言 為了更好的理解代理模式,首先根據(jù)生活中實(shí)際場(chǎng)景進(jìn)行模擬,讓我們?cè)谏钪腥ンw驗(yàn)設(shè)計(jì)思想的美妙。 場(chǎng)景描述 病從口入這句成語(yǔ)告訴我們注意飲食健康,小六同學(xué)...

    piglei 評(píng)論0 收藏0
  • php設(shè)計(jì)模式

    摘要:我們今天也來做一個(gè)萬能遙控器設(shè)計(jì)模式適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。今天要介紹的仍然是創(chuàng)建型設(shè)計(jì)模式的一種建造者模式。設(shè)計(jì)模式的理論知識(shí)固然重要,但 計(jì)算機(jī)程序的思維邏輯 (54) - 剖析 Collections - 設(shè)計(jì)模式 上節(jié)我們提到,類 Collections 中大概有兩類功能,第一類是對(duì)容器接口對(duì)象進(jìn)行操作,第二類是返回一個(gè)容器接口對(duì)象,上節(jié)我們介紹了...

    Dionysus_go 評(píng)論0 收藏0
  • php設(shè)計(jì)模式

    摘要:我們今天也來做一個(gè)萬能遙控器設(shè)計(jì)模式適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。今天要介紹的仍然是創(chuàng)建型設(shè)計(jì)模式的一種建造者模式。設(shè)計(jì)模式的理論知識(shí)固然重要,但 計(jì)算機(jī)程序的思維邏輯 (54) - 剖析 Collections - 設(shè)計(jì)模式 上節(jié)我們提到,類 Collections 中大概有兩類功能,第一類是對(duì)容器接口對(duì)象進(jìn)行操作,第二類是返回一個(gè)容器接口對(duì)象,上節(jié)我們介紹了...

    vspiders 評(píng)論0 收藏0
  • 當(dāng)Kotlin邂逅設(shè)計(jì)模式代理模式(二)

    摘要:簡(jiǎn)述從這篇文章起,我們將繼續(xù)邂逅設(shè)計(jì)模式系列篇中的第二篇代理模式。代理模式可以說很多初級(jí)中級(jí)開發(fā)者迷惑的設(shè)計(jì)模式。首先我們需要使用類圖直觀地表示出代理模式思想。所以基于代理模式很輕松就實(shí)現(xiàn)。簡(jiǎn)述: 從這篇文章起,我們將繼續(xù)Kotlin邂逅設(shè)計(jì)模式系列篇中的第二篇代理模式。代理模式可以說很多初級(jí)中級(jí)開發(fā)者迷惑的設(shè)計(jì)模式。但是它確實(shí)應(yīng)用很廣,不用多說大家非常熟悉的Retrofit框架,內(nèi)部使用了...

    番茄西紅柿 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<