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

資訊專欄INFORMATION COLUMN

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

xuweijian / 3181人閱讀

摘要:下面我們通過(guò)玩英雄聯(lián)盟代練的例子來(lái)說(shuō)明下登錄游戲贏下了一局英雄聯(lián)盟,獲得了金幣測(cè)試結(jié)果登錄游戲贏下了一局英雄聯(lián)盟,獲得了金幣可以這樣理解,自己寫(xiě)代理類的方式就是靜態(tài)代理。

前言

剛上大學(xué)那會(huì),英雄聯(lián)盟火的一塌糊涂,當(dāng)時(shí)每天都想著升到30級(jí)開(kāi)啟排位之旅。可是升到30級(jí)需要大把的時(shí)間不說(shuō),這時(shí)候匹配到的人,水平過(guò)于參差不齊,問(wèn)候你全家的事經(jīng)常發(fā)生,那個(gè)時(shí)候就想要是能有個(gè)代練幫我升到30級(jí)該多好啊.....下面我們就通過(guò)代碼的方式找下代練-..-

什么是代理模式
為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)
uml類圖

代理模式是一個(gè)使用率非常高的模式,像spring的aop,struts2的Form元素映射都采用了代理模式。下面我們來(lái)看下類圖中三種角色的具體定義:

subject:抽象主題,可以是接口也可以是抽象類,用來(lái)進(jìn)行業(yè)務(wù)定義。

realsubject:真實(shí)主題類,用來(lái)實(shí)現(xiàn)真正的業(yè)務(wù)邏輯。

proxy:代理類,也叫委托類。它負(fù)責(zé)控制對(duì)真實(shí)主題類訪問(wèn)的控制,將所有抽象主題定義的方法委托給realsubject類實(shí)現(xiàn),并在這個(gè)過(guò)程加上預(yù)處理和善后工作,已達(dá)到增強(qiáng)功能的目的.

靜態(tài)代理

靜態(tài)代理模式其實(shí)就是在類設(shè)計(jì)階段就將代理類考慮在內(nèi),而不是和動(dòng)態(tài)代理和cglib代理一樣動(dòng)態(tài)生成代理類。下面我們通過(guò)玩英雄聯(lián)盟代練的例子來(lái)說(shuō)明下:

public interface IGame {

    void login();

    void playLOL();

}
public class IGamePlayer implements IGame {

    private String name;

    public IGamePlayer(String name) {
        this.name = name;
    }

    @Override
    public void login() {
        System.out.println(name+"登錄游戲");
    }

    @Override
    public void playLOL() {
        System.out.println(name+"贏下了一局英雄聯(lián)盟,獲得了100金幣");
    }
}
public class IGameProxy implements IGame {

    private IGamePlayer iGamePlayer;

    public IGameProxy(IGamePlayer iGamePlayer) {
        this.iGamePlayer = iGamePlayer;
    }

    @Override
    public void login() {
        iGamePlayer.login();
    }

    @Override
    public void playLOL() {
        iGamePlayer.playLOL();
    }
}
public class Client {

    public static void main(String[] args) {
        IGameProxy iGameProxy = new IGameProxy(new IGamePlayer("bin"));
        iGameProxy.login();
        iGameProxy.playLOL();
    }
}
測(cè)試結(jié)果:
bin登錄游戲
bin贏下了一局英雄聯(lián)盟,獲得了100金幣

可以這樣理解,自己寫(xiě)代理類的方式就是靜態(tài)代理。創(chuàng)建代理類和真實(shí)主題類,用代理類控制主題類的訪問(wèn)。游戲代練登錄賬號(hào),打游戲升級(jí),從而節(jié)省我的時(shí)間。

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

動(dòng)態(tài)代理就是在設(shè)計(jì)和實(shí)現(xiàn)階段不需要關(guān)心代理誰(shuí),而是在運(yùn)行時(shí)期才去指定代理哪個(gè)對(duì)象。spring的核心之一就是aop,俗稱面向切面編程,其核心就是采用了動(dòng)態(tài)代理機(jī)制。

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

保持IGAME接口和業(yè)務(wù)邏輯類不變。

//通知(這個(gè)例子用來(lái)統(tǒng)計(jì)登錄接口的耗時(shí))
 interface IAdvice {
     void execute();
}
//前置通知
public class BeforeAdvice implements IAdvice {

    @Override
    public void execute() {
        System.out.println("執(zhí)行前時(shí)間:"+System.currentTimeMillis());
    }
}
//后置通知
public class AfterAdvice implements IAdvice {

    @Override
    public void execute() {
        System.out.println("執(zhí)行后時(shí)間:"+System.currentTimeMillis());
    }
}
public class DynamicProxy{

    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    public Object getInstance(ClassLoader classLoader, Class[] interfaces){
        return Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //連接點(diǎn)
                if (method.getName().startsWith("login")){
                    new BeforeAdvice().execute();
                }
                Object objec=method.invoke(target,args);
                if (method.getName().startsWith("login")){
                    new AfterAdvice().execute();
                }
                return objec;
            }
        });
    }
}
public class Client {

    public static void main(String[] args) {
        IGamePlayer gamePlayer =  new IGamePlayer("bin");
        DynamicProxy dynamicProxy = new DynamicProxy(gamePlayer);
        IGame proxy= (IGame) dynamicProxy.getInstance(gamePlayer.getClass().getClassLoader(),gamePlayer.getClass().getInterfaces());
        proxy.login();
        proxy.playLOL();
    }
}
測(cè)試結(jié)果:
執(zhí)行前時(shí)間:1513498759281
bin登錄游戲
執(zhí)行后時(shí)間:1513498759282
bin贏下了一局英雄聯(lián)盟,獲得了100金幣

在上面的例子中,我引用了一些aop的術(shù)語(yǔ),例如連接點(diǎn),通知。實(shí)現(xiàn)了一個(gè)非常簡(jiǎn)單的面向切面編程,由項(xiàng)目經(jīng)驗(yàn)的可以看下springaop關(guān)于事務(wù)的配置,就會(huì)明白這樣配置的含義了。
jdk動(dòng)態(tài)代理是面向接口的,也就是說(shuō)代理對(duì)象是根據(jù)目標(biāo)對(duì)象的所有接口決定的。到底是怎么實(shí)現(xiàn)的呢,我們來(lái)看下這一段代碼:

public Object getInstance(ClassLoader classLoader, Class[] interfaces){
        return Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //連接點(diǎn)
                if (method.getName().startsWith("login")){
                    new BeforeAdvice().execute();
                }
                Object objec=method.invoke(target,args);
                if (method.getName().startsWith("login")){
                    new AfterAdvice().execute();
                }
                return objec;
            }
        });
    }

Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler()):這個(gè)方法是重新生成了一個(gè)對(duì)象,通過(guò)類加載器和該類所有的接口生成。當(dāng)前生成的方法都是空的,具體邏輯都會(huì)由InvocationHandler來(lái)實(shí)現(xiàn)。InvocationHandler我采用了內(nèi)部類的方式來(lái)實(shí)現(xiàn),具體邏輯都是通過(guò)invoke來(lái)訪問(wèn)目標(biāo)對(duì)象。其調(diào)用流程就是:client-->DynamicProxy-->InvocationHandler-->IGamePlayer .

cglib代理

jdk提供的動(dòng)態(tài)代理是通過(guò)接口實(shí)現(xiàn)的,那么cglib就是通過(guò)生成目標(biāo)類的子類實(shí)現(xiàn)的。假如你的目標(biāo)類沒(méi)有實(shí)現(xiàn)接口,又想使用動(dòng)態(tài)代理,那么cglib是你的不二選擇。

Cglib是一個(gè)強(qiáng)大的高性能的代碼生成包,它可以在運(yùn)行期擴(kuò)展java類與實(shí)現(xiàn)java接口.它廣泛的被許多AOP的框架使用,例如Spring AOP和synaop,為他們提供方法的interception(攔截)。Cglib包的底層是通過(guò)使用一個(gè)小而快的字節(jié)碼處理框架ASM來(lái)轉(zhuǎn)換字節(jié)碼并生成新的類.不鼓勵(lì)直接使用ASM,因?yàn)樗竽惚仨殞?duì)JVM內(nèi)部結(jié)構(gòu)包括class文件的格式和指令集都很熟悉.但是有一點(diǎn)需要額外注意,若目標(biāo)類是final或者目標(biāo)方法是static和final的,則不會(huì)被cglib方法攔截。

使用cglib需要引入cglib包或者spring-core(spring核心功能已經(jīng)集成cglib)

public class IGamePlayer{

    private String name;

    public IGamePlayer(String name) {
        this.name = name;
    }

    public IGamePlayer() {
    }

    public void login() {
        System.out.println(name+"登錄游戲");
    }

    public void playLOL() {
        System.out.println(name+"贏下了一局英雄聯(lián)盟,獲得了100金幣");
    }
}
public class DynamicProxy implements MethodInterceptor {

    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    public Object getProxyInstance(){

        Enhancer enhancer = new Enhancer();

        enhancer.setSuperclass(target.getClass());

        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //模擬事務(wù)
        System.out.println("事務(wù)開(kāi)始了");
        method.invoke(target,objects);
        System.out.println("事務(wù)結(jié)束了");
        return null;
    }
}
public class Client {

    public static void main(String[] args) {
        IGamePlayer iGamePlayer = new IGamePlayer("bin");
        DynamicProxy dynamicProxy = new DynamicProxy(iGamePlayer);
        IGamePlayer proxy = (IGamePlayer) dynamicProxy.getProxyInstance();
        proxy.login();
        proxy.playLOL();
    }
}
測(cè)試結(jié)果:
事務(wù)開(kāi)始了
bin登錄游戲
事務(wù)結(jié)束了
事務(wù)開(kāi)始了
bin贏下了一局英雄聯(lián)盟,獲得了100金幣
事務(wù)結(jié)束了

如例子,我們定義了一個(gè)目標(biāo)對(duì)象類,沒(méi)有實(shí)現(xiàn)接口,通過(guò)cglib的Enhancer工具類指定父類和回調(diào),創(chuàng)建代理類。實(shí)現(xiàn)MethodInterceptor,重寫(xiě)intercept,相當(dāng)于jdk動(dòng)態(tài)代理的invoke。

總結(jié)

代理模式分為靜態(tài)代理和動(dòng)態(tài)代理。最大的區(qū)別就是靜態(tài)代理是自己寫(xiě)代理,而動(dòng)態(tài)代理是通過(guò)運(yùn)行時(shí)動(dòng)態(tài)的生成代理類。動(dòng)態(tài)代理是springaop的核心,又分為jdk代理和cglib代理,前者通過(guò)接口生成代理后者通過(guò)定義父類的子類來(lái)生成代理(類不能為final,方法不能為static和final)。
代理模式或許是大家接觸的最多的模式,有了springaop和aspectj這樣優(yōu)秀的工具,我們拿來(lái)定義即可。在學(xué)習(xí)aop框架的時(shí)候,要先弄清一些專業(yè)名詞,切面、切入點(diǎn)、通知、織入,理解這些名詞,知道代理模式的原理,學(xué)起aop框架就會(huì)游刃有余了。

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

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

相關(guān)文章

  • PHP設(shè)計(jì)模式代理模式

    摘要:虛擬代理如果需要?jiǎng)?chuàng)建一個(gè)資源消耗較大的對(duì)象,先創(chuàng)建一個(gè)消耗相對(duì)較小的對(duì)象來(lái)表示,真實(shí)對(duì)象只在需要時(shí)才會(huì)被真正創(chuàng)建。虛擬代理通過(guò)使用一個(gè)小對(duì)象來(lái)代表一個(gè)大對(duì)象,可以減少系統(tǒng)資源的消耗,對(duì)系統(tǒng)進(jìn)行優(yōu)化并提高運(yùn)行速度。 概念 代理模式(Proxy Pattern) :一種對(duì)象結(jié)構(gòu)型模式。給某一個(gè)對(duì)象提供一個(gè)代理,并由代理對(duì)象控制對(duì)原對(duì)象的引用。 UML showImg(https://seg...

    zhisheng 評(píng)論0 收藏0
  • 設(shè)計(jì)模式代理模式

    摘要:代理模式的定義來(lái)源于百度百科為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。二來(lái)源大話設(shè)計(jì)模式三例子實(shí)現(xiàn)現(xiàn)在根據(jù)上面購(gòu)票代理的場(chǎng)景來(lái)實(shí)現(xiàn)例子接口,定義真實(shí)火車站,還有代理提供的服務(wù)。一、定義? ? ? ?在網(wǎng)絡(luò)不發(fā)達(dá)之前,我們買(mǎi)火車票,通常都需要跑到火車站去買(mǎi)。這對(duì)于我們來(lái)說(shuō)可能有些麻煩,偶然有一天,你發(fā)現(xiàn)你樓下有一家便利店居然能買(mǎi)火車票,這就方便很多。其實(shí)啊,便利店并不提供火車服務(wù),也沒(méi)有權(quán)...

    enda 評(píng)論0 收藏0
  • Spring框架我見(jiàn)(二)——代理模式

    摘要:聊完了工廠模式,下面我們來(lái)說(shuō)框架中的另一個(gè)核心設(shè)計(jì)模式代理模式。這里的外賣(mài)小哥就相當(dāng)于是我們的代理。主要分為代理和代理。 聊完了工廠模式,下面我們來(lái)說(shuō)Spring框架中的另一個(gè)核心設(shè)計(jì)模式——代理模式(Proxy Pattern)。 代理模式 大家可以先不用看概念,先舉個(gè)吃飯的例子:比如說(shuō)我們想吃飯,我們可以選擇自己做飯吃、去飯店吃、叫外賣(mài)吃。如果我們選擇自己做著吃,我們就需要去買(mǎi)菜、...

    oneasp 評(píng)論0 收藏0
  • 設(shè)計(jì)模式代理模式

    摘要:虛擬代理虛擬代理把一些開(kāi)銷很大的對(duì)象,延遲到真正需要它的時(shí)候才去創(chuàng)建。主要參考設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐 設(shè)計(jì)模式 在面向?qū)ο筌浖O(shè)計(jì)過(guò)程中針對(duì)特定問(wèn)題的簡(jiǎn)潔而優(yōu)雅的解決方案。 這是在《設(shè)計(jì)模式》一書(shū)中對(duì)設(shè)計(jì)模式的定義。在軟件開(kāi)發(fā)過(guò)程中,我們可能會(huì)遇到過(guò)這樣的情況,我們現(xiàn)在發(fā)現(xiàn)一個(gè)問(wèn)題,和以前的某個(gè)問(wèn)題很相似,幾乎可以用統(tǒng)一套解決方案,而且我們還發(fā)現(xiàn),在某個(gè)條件下,這個(gè)解決方案幾乎就是通用的,...

    Gilbertat 評(píng)論0 收藏0
  • Javascript設(shè)計(jì)模式——代理模式

    摘要:最近在讀設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐,在這里把文中的各種設(shè)計(jì)模式寫(xiě)出來(lái),以便加深記憶,也可以分享給初學(xué)者。經(jīng)紀(jì)人可以全權(quán)代表明星和客戶談判,最后把談判結(jié)果給明星,明星決定簽約與否。這也違反了面向?qū)ο笤O(shè)計(jì)原則中的單一職責(zé)原則。 最近在讀《javascript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》,在這里把文中的各種設(shè)計(jì)模式寫(xiě)出來(lái),以便加深記憶,也可以分享給初學(xué)者。如果你不了解設(shè)計(jì)模式,那么強(qiáng)烈推薦你閱讀一下這本書(shū),...

    cuieney 評(píng)論0 收藏0
  • JS設(shè)計(jì)模式代理模式

    摘要:什么是代理模式代理模式,類似于明星的經(jīng)紀(jì)人,想要拜訪明星,需要先通過(guò)經(jīng)紀(jì)人的溝通。不同于裝飾器,那種動(dòng)態(tài)加載一個(gè)對(duì)象,可以說(shuō)在代理模式當(dāng)中,代理是早已既定的。又稱單一功能原則,面向?qū)ο笪鍌€(gè)基本原則之一。 什么是代理模式 代理模式,類似于明星的經(jīng)紀(jì)人,想要拜訪明星,需要先通過(guò)經(jīng)紀(jì)人的溝通。而在JS當(dāng)中,如果想訪問(wèn)一個(gè)類,需要通過(guò)另一個(gè)類來(lái)間接訪問(wèn) 。不同于裝飾器,那種動(dòng)態(tài)加載一個(gè)對(duì)象,可...

    widuu 評(píng)論0 收藏0

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

0條評(píng)論

xuweijian

|高級(jí)講師

TA的文章

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