摘要:下面總結了它倆的異同相同點都需要實現同一個接口或者繼承同一個抽象類,并且代理角色和裝飾角色都持有被代理角色和構件角色的引用。
寫完上一篇之后有小伙伴問我有沒有寫過代理模式,想看看我的理解。原本我的設計模式系列是按照創建型-行為型-結構型的順序寫下去的,既然小伙伴誠心誠意了,我就大發慈悲的穿插一篇代理模式。開玩笑,題外話。
說起代理模式,就不由得想起經紀人,說起經紀人,就想起了...對,沒錯就是“許三多”。這就有點邪惡了~甭八卦了,入正題。
經紀人的角色就相當于一個代理,要找到明星就先經過經紀人,經紀人負責給明星接拍電影把關、活動撈金,這就是為什么要用到代理的原因,拋開其他繁瑣的事務,專注被代理人的業務邏輯,減輕被代理人的負擔。so,帶著一點點罪惡感來看看什么是代理模式。
一、代理模式 定義??為其它對象提供一個代理對象,并由代理對象控制這個對象的訪問。
特點1)很直接的,實現同一個接口或者繼承同一個抽象類。
2)代理對象控制對被代理對象的訪問。
UML這是代理模式的通用UML,涉及到的角色如下所示:
??- 抽象主題角色:定義了被代理角色和代理角色的共同接口或者抽象類。
??- 被代理角色:實現或者繼承抽象主題角色,定義實現具體業務邏輯的實現。
??- 代理角色:實現或者繼承抽象主題角色,持有被代理角色的引用,控制和限制被代理角色的實現,并且擁有自己的處理方法(預處理和善后)
二、代理模式實戰首先是抽象主題角色:
public interface Subject { public void movie(); }
很簡單,單純定義了movie方法,下面看被代理角色的實現:
public class Star implements Subject { @Override public void movie() { System.out.println(getClass().getSimpleName() + ":經紀人接了一部電影,我負責拍就好"); } }
被代理角色實現抽象主題角色,專注實現被代理角色的業務邏輯。繼續看代理角色:
public class Agent implements Subject { private Subject star; public Agent(Subject star) { this.star = star; } @Override public void movie() { System.out.println(getClass().getSimpleName() + ":劇本很好,這部電影接下了"); star.movie(); } }
代理角色持有被代理角色的引用,要訪問被代理角色必須通過代理,負責被代理角色本職之外的職能,并且具有準入和過濾的功能。最后來看客戶端的實現:
public class Client { public static void main(String[] args) { Subject star = new Star(); Subject proxy = new Agent(star); proxy.movie(); } }
表面上是調用了代理的方法,實際的執行者其實是被代理角色Star,看看結果就知道:
Agent:劇本很好,這部電影接下了
Star:經紀人接了一部電影,我負責拍就好
上面是代理模式其中的一種實現方式,主要在代理角色Agent中指定了被代理角色Star,意思是經紀人大喊一聲“嘿~兄弟,你是我的了!”。
下面看代理模式的另一種實現方式,先看抽象主題角色代碼:
public interface Subject { public void movie(); // 指定代理 public Subject getAgent(); }
增加了指定代理的方法getAgent,再來看被代理角色和代理角色代碼:
// 被代理角色 public class Star implements Subject { @Override public void movie() { System.out.println(getClass().getSimpleName() + ":經紀人接了一部電影,我負責拍就好"); } @Override public Subject getAgent() { return new Agent(this); } } // 代理角色 public class Agent implements Subject { private Subject star; public Agent(Subject star) { this.star = star; } @Override public void movie() { System.out.println(getClass().getSimpleName() + ":劇本題材很好,這部電影接下了"); star.movie(); } @Override public Subject getAgent() { return this; } }
重點看被代理角色getAgent方法,方法里面指定了Agent為代理,而Agent的getAgent并沒有指定代理。下面看客戶端代碼實現:
public class Client { public static void main(String[] args) { Subject star = new Star(); Subject proxy = star.getAgent(); proxy.movie(); } }
在客戶端通過getAgent得到指定代理角色,由代理來控制star對象。
運行的結果的跟上一種方式是一樣的。注意,這種方式是客戶端直接訪問被代理角色,代理由被代理角色指定。前面的一種方式則是客戶端不能訪問直接訪問被代理角色,只能訪問代理。但是,無論是哪一種方式,代理模式的實現都是必須經過代理才能訪問被代理模式。就比如明星拍電影,不會跳過經紀人直接找到明星,而是經過經紀人再到明星,要不然經紀人這個職位豈不是浪費了。
三、代理模式擴展 代理模式VS裝飾者模式代理模式在講解了,接下來看裝飾者模式,先搞一張裝飾者模式的UML圖
別坑我讀的書少,這明明就是代理模式的UML。沒錯,裝飾者模式和代理模式就是這么相似,包括UML和代碼實現,甚至可以是一模一樣。不信?來看裝飾者模式的代碼,這里我只給出簡單代碼:
// 抽象構件 public interface Component { public void movie(); } // 具體構件,實現Component,要被裝飾的 public class Star implements Component { @Override public void movie() { System.out.println(getClass().getSimpleName() + ":化了妝迷倒一片妹紙,拍起來電影特別帶勁"); } } // 裝飾者,裝飾具體構件 public class ConcreteDecorator implements Component { private Component star; public ConcreteDecorator(Component concreteComponent) { this.star = concreteComponent; } @Override public void movie() { System.out.println(getClass().getSimpleName() + ":拍電影各種道具加身,還得化妝"); star.movie(); } } public class Client { public static void main(String[] args) { Subject star = new Star(); Subject proxy = new Agent(star); proxy.movie(); } }
運行客戶端代碼,結果如下:
ConcreteDecorator:拍電影各種道具加身,還得化妝
Star:化了妝迷倒一片妹紙,拍起來電影特別帶勁
哈哈哈哈,傻傻的分不清是裝飾者還是代理模式了吧!UML一樣,就算代碼的實現也可以一樣,就把結果改了改。下面總結了它倆的異同:
都需要實現同一個接口或者繼承同一個抽象類,并且代理角色和裝飾角色都持有被代理角色和構件角色的引用。
兩種模式都可以在被代理角色和具體構件角色的業務方法前后添加自己的方法。額...說了等于沒說。
代理模式重點在于控制對象的行為,而裝飾模式側重于增加對象的職能(當然也可以削弱)。看完這句話立馬暈菜,到底是怎么才叫控制行為和增加職能?設計模式離不開面對對象思想,用面向對象的思想思考這個問題。代理模式是對整個對象的行為控制和限制,而非針對功能,跟裝飾模式不一樣,裝飾模式針對的是對象職能上的加強,也就是屬性或者方法。
通俗的講,它們倆根本的區別是目的性不一樣,也就是使用場景。比如公司老板,為了更好的管理公司會請做行政、財務的人回來幫忙處理公司事務,把事情整理好了,有必要的事情才到達老板那,這就是代理。如果是裝飾呢,就是往老板身上加職能,不僅提供財力,還要懂行政管理,財務會計,甚至要會敲代碼,可以這么做,但并不符合實際使用場景。
四、代理模式的優缺點 優點1)良好的擴展性。修改被代理角色并不影響調用者使用代理,對于調用者,被代理角色是透明的。
2)隔離,降低耦合度。代理角色協調調用者和被代理角色,被代理角色只需實現本身關心的業務,非自己本職的業務通過代理處理和隔離。
缺點1)增加了代理類,實現需要經過代理,因此請求速度會變慢。
總結代理模式有靜態和動態兩種方式,這篇文章的代理模式都是使用靜態代理,動態代理在往后設計模式的擴展會補上。這里不講解動態代理首先是因為重點在于把代理模式核心闡述清楚,再者是動態代理用到的篇幅會較長,所以放到之后靜態代理和動態代理的對比擴展一起講解比較合適。另外,注意代理模式和裝飾者模式的區別,從網上看到了一堆相關的資料,有的說是構造方法不同,有的就直接拋出一句控制行為和增加職能虛無縹緲的闡述,都沒有說清兩者的區別,看完后還是一臉的懵。這篇文章我給出了自己的它倆見解,有不同看法的小伙伴也可以給我意見。下一篇模板方法模式,您的點贊和關注是我的動力哦,see you!
更多精彩干貨關注“AndroidJet的開發之路”公眾號
設計模式Java源碼GitHub下載:https://github.com/jetLee92/DesignPattern
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71150.html
摘要:受知乎文章和設計模式之禪的啟發,我也來搞一篇腦洞小開的文章由標題可知,這篇文章是寫給我女朋友看的。于是這就讓經紀人對粉絲說只有萬,我才會寫代碼。 前言 只有光頭才能變強 回顧前面: ThreadLocal就是這么簡單 多線程三分鐘就可以入個門了! 多線程基礎必要知識點!看了學習多線程事半功倍 Java鎖機制了解一下 AQS簡簡單單過一遍 Lock鎖子類了解一下 線程池你真不來了解一下...
摘要:這種語法,在中被稱為動態代理。在動態代理機制中,這個角色只能是接口。動態代理就是實現的技術之一。 所謂動態代理,指的是語言提供的一種語法,能夠將對對象中不同方法的調用重定向到一個統一的處理函數中來。python重寫__getattr__函數能夠做到這一點,就連世界上最好的語言也提供稱為魔術方法的__call。這種語法除了能更好的實現動態代理外,還是RPC框架實現原理的一部分。 動態代理...
摘要:代理模式在我們日常中很常見,生活處處有代理看張學友的演唱會很難搶票,可以找黃牛排隊買嫌出去吃飯麻煩,可以叫外賣無論是黃牛外賣騎手都得幫我們干活。靜態代理我還是以找黃牛幫我排隊買張學友的演唱會門票的例子,寫個說明。 微信公眾號:一個優秀的廢人。如有問題,請后臺留言,反正我也不會聽。 最近在復習 Java 相關,回顧了下代理模式。代理模式在 Java 領域很多地方都有應用,它分為靜態代理和...
摘要:面向對象設計里的設計模式之代理模式,相信很多朋友已經很熟悉了。代表當前執行方法的實例,即方法調用者。代表具體的方法名稱。現在我們再次調用,傳入構造器返回的代理對象打印輸出,代理邏輯生效了和的一樣優雅地實現了代理設計模式。 showImg(https://segmentfault.com/img/remote/1460000016760603);面向對象設計里的設計模式之Proxy(代理...
閱讀 2311·2021-11-25 09:43
閱讀 3453·2021-10-25 09:48
閱讀 1328·2021-09-13 10:24
閱讀 2738·2019-08-29 15:07
閱讀 1274·2019-08-29 13:14
閱讀 3271·2019-08-29 12:22
閱讀 1359·2019-08-29 11:32
閱讀 3242·2019-08-29 11:23