天堂国产午夜亚洲专区-少妇人妻综合久久蜜臀-国产成人户外露出视频在线-国产91传媒一区二区三区

設計模式解析之代理模式

發(fā)布時間:2017-01-11 15:12

  本文關鍵詞:設計模式解析,由筆耕文化傳播整理發(fā)布。


設計模式解析之代理模式

設計模式-代理模式代理模式的概念  代理模式(proxy pattern)是一種結構型的設計模式,代理模式在程序開發(fā)中的運用非常廣泛。簡單地描述代理模式就是:為其他對象(被代理對象)提供一種代理以控制對原有對象的操作。實際的行為是由被代理對象完成的。

  代理模式可以分為兩部分,靜態(tài)代理 和 動態(tài)代理,它們的區(qū)別將在下面詳細介紹。

角色介紹:  Suject: 抽象主題類

  該類的主要職責是申明真是主題與代理的共同接口方法,該類既可以是個抽象類也可以是個接口(具有抽象方法)。

  RealSubject: 真實主題類

  該類也稱為委托類或者被代理類,改類定義了代理所表示的真是對象(也就是實現(xiàn)了抽象方法),由其執(zhí)行具體的業(yè)務邏輯。

  ProxySubject:代理類

  這個類的對象持有一個對真實主題的引用,在這個類所實現(xiàn)的接口方法中調(diào)用真實主題類中相應的方法執(zhí)行,這樣就實現(xiàn)了代理的目的。

  Client:客戶類

  也就是使用代理類的類型,客戶類通過代理類間接地調(diào)用了真實主題類中定義的方法。

代理模式的實現(xiàn)簡單的例子針對,上方的角色介紹,舉一個簡單的例子:在現(xiàn)實的世界中,打公司一般有,原告 和原告的代理律師這樣兩個角色,他們要做的事情是 辯護。于是,我們可以實現(xiàn)以下幾個類。

抽象主題類:interface IDefender,這個接口中有個 抽象方法 abstract public void defend(); 表示辯護這個行為。

[code]public interface IDefender { abstract public void defend();//辯護行為 }

真實主題類: class Accuser,實現(xiàn)IDefender這個接口,具有具體的邏輯行為

[code] public class Accuser implements IDefender { @Override public void defend() { System.out.println("被告嚴重侵犯了公民的人身自由權...嗶哩嗶哩"); } }

代理類:AccuserProxy 類,原告請了個代理律師幫助它打官司,也就是AccuserProxy,由代理律師控制原告的表現(xiàn)

[code]public class AccuserProxy implements IDefender { //持有被代理類的引用 private IDefender iDefend; public AccuserProxy(IDefender iDefend) { this.iDefend = iDefend; } @Override public void defend() { beforeDefend(); // 被代理類的行為 iDefend.defend(); afterDefend(); } //修飾的方法 private void beforeDefend(){ System.out.print("我是原告律師,以下是我方辯詞"); } //修飾的方法 private void afterDefend(){ System.out.print("辯護完畢"); } }

客戶端:Client類,使用代理類的角色

[code]public class Client { public static void main(String[] args) { Accuser accuser = new Accuser(); accuser.defend();//此時輸出 被告嚴重侵犯了公民的人身自由權...嗶哩嗶哩 AccuserProxy accuserProxy = new AccuserProxy(accuser); accuserProxy.defend(); // 輸出:我是原告律師,以下是我方辯詞,被告嚴重侵犯了公民的人身自由權...嗶哩嗶哩,辯護完畢 ///////////////////////////////////////////////////// // 因為,我們的代理類和被代理類 實現(xiàn)的是同一接口,如果將引用類型 寫成IDfender, // 那么在調(diào)用 defend(),方法的使用 客戶完全感覺不到被代理類的存在,當然因為我們這里的 // 被代理類是通過構造函數(shù)傳進去的,軟件開發(fā)中,有時候直接在被代理類中實例化代理類,這樣使用起來就更完美了。 IDefender accuser2 = new Accuser(); IDefender accuser2Proxy = new AccuserProxy(accuser2); accuser2.defend(); } }

  代理模式的運用符合開閉原則的定義,軟件中的對象(類、模塊、函數(shù))應該對于拓展是開發(fā)的,對于修改是封閉的。我們不需要修改被代理類 (Accuser),使用代理模式就可以實現(xiàn)對原有功能的加強。以上代碼只是一個簡答的運用場景,現(xiàn)實開發(fā)中代理模式的運用非常廣泛,它可以解決多方面的問題。

Androd 開發(fā)中的運用例子  Android API的版本迭代很快,在每次的版本更新中 通常會加強一些原有的功能,對原有的類會增加新的接口,而每個版本能夠調(diào)用的API 可能會都不同,比如 狀態(tài)欄 Notification 。

Notfification可以分為4類,一類是正常視圖,也就是我們通常在狀態(tài)欄看到的 高度為 64dp 的長條狀通知視圖;一類是在 API16 中引入的以 Style 方式展示的 MediaStyle、InboxStyle、BigTextStyle 和 BigPictureStyle 四種Notification 風格樣式;一類也是在 API16 中引入的可以將通知視圖顯示為256dp 高度大視圖的 bingContentView;最后一類是在 L 中引入的 headsUpContentVIew

  現(xiàn)在,我們的 App需要根據(jù)不同的版本實例化不同 Notification 顯示不同的視圖,在高版本顯示的視圖當然就更豐富,低版本更單調(diào)。如果你直接在 Activity 中判斷版本,加上一坨的 switch 或者 if else 語句當然也是可以的。但是,我們現(xiàn)在來看一下 運用設計模式的思想,如何將代碼抽離,對于客戶端來說(Activity or Fragment),不應該關心這些細節(jié)。

以下的代碼來自《Android源碼設計模式解析與實戰(zhàn)》一書。

抽象主題類: Notify類, Notify抽象類 聲明了 NotificationManager 和NotificatoinCompat.Builder 2個成員變量來處理和通知的一些邏輯。在構造函數(shù)中初始化所有子類都會調(diào)用的邏輯方法。

[code]public abstract class Notify { protected Context context; protected NotificationManager nm; protected NotificationCompat.Builder builder; public Notify(Context context){ this.context = context; nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); builder = new NotificationCompat.Builder(context); builder.setSmallIcon(R.mipmap.ic_launcher) .setContentIntent(PendingIntent.getActivities( context, 0, new Intent[]{new Intent(context, NotifyActivity.class)}, PendingIntent.FLAG_UPDATE_CURRENT)); } /** * 發(fā)送一條通知 */ public abstract void send(); /** * 取消一條通知 */ public abstract void cancel(); }

真實主題類:NotifyNormal ,繼承抽象主題類,簡單重寫抽象方法

[code]public class NotifyNormal extends Notify{ public NotifyNormal(Context context) { super(context); } @Override public void send() { Notification n = builder.build(); n.contentView = new RemoteViews(context.getPackageName(), R.layout.remote_notify_proxy_normal); nm.notify(0,n); } @Override public void cancel() { nm.cancel(0); } }

真實主題類 : 與NormalNotify的不同在于 還實現(xiàn)了bigContentView 的初始化,,這是在 API 16以上才能調(diào)用的

[code]public class NotifyBig extends Notify{ public NotifyBig(Context context) { super(context); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void send() { Notification n = builder.build(); n.contentView = new RemoteViews(context.getPackageName(), R.layout.remote_notify_proxy_normal); n.bigContentView = new RemoteViews(context.getPackageName(),R.layout.remote_notify_proxy_big); nm.notify(0,n); } @Override public void cancel() { nm.cancel(0); } }

  源碼中還有個 NotifyHeadUp 類,它的唯一區(qū)別就是 在bigContentVie 的基礎上還能實現(xiàn) Notification 的 headsUpContentView ,這個 View 是在 API 20以上 才能使用的,當我們的 App 以全屏的方式展開的時候如果收到了通知,這個 View 就會浮動展示于屏幕頂部。

  代理類: NotifyProxy ,持有被代理類對象,在這個示例中,我們根據(jù)不同的運行時環(huán)境 API 實例化不同的 被代理類對象。

[code]public class NotifyProxy extends Notify{ //代理類持有被代理類的引用 private Notify notify; public NotifyProxy(Context context) { super(context); //根據(jù)版本實例化不同的被代理對象 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ notify = new NotifyHeadUp(context); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){ notify = new NotifyBig(context); } else { notify = new NotifyNormal(context); } } @Override public void send() { notify.send(); } @Override public void cancel() { notify.cancel(); } }

  客戶端類:也就是我們的Activity,在 Activity 中,我們直接將 Context 傳入,代理類會幫我們實例化合適的被代理對象。

[code]new NotifyProxy(NotifyActivity.this).send();

  在這個實例中,我們通過代理模式 ,使用一個代理類來針對不同的運行時系統(tǒng)版本,實例化不同的 Notificaition 的子類,而在客戶端中 簡單地調(diào)用代理類的send方法就可以。

靜態(tài)代理模式總結  代理模式通過代理類對外部提供統(tǒng)一的接口,在代理類中實現(xiàn)對被代理類的附加操作,從而可以在不影響外部調(diào)用的情況下實現(xiàn)系統(tǒng)的拓展,我覺得代理模式可能在一個程序項目的開發(fā)初期運用不到,而在項目成型而又有了新的變化、升級等,可以考慮用代理模式來實現(xiàn),這樣可以不需要修改原有的代碼。

動態(tài)代理模式  其實上文所講述的內(nèi)容只是代理模式的一部分,代理模式還有更為強大的動態(tài)代理模式。以下是這 2 個的區(qū)別:

靜態(tài)代理模式:在我們的代碼運行前,代理類的class編譯文件就已經(jīng)存在了

動態(tài)代理模式:在 code 階段并不存在被代理類,而且并不知道要代理哪個對象,利用 Java 的反射機制在運行期動態(tài)地生成代理者的對象,代理誰將會在代碼執(zhí)行階段決定。

動態(tài)代理模式的實現(xiàn)  Java 已經(jīng)為我們提供了一個便捷的動態(tài)代理接口 InvocationHandler ,我們重寫其調(diào)用方法 invoke。以前面 我們的代理律師的例子為例,看看具體的操作是怎么樣的

[code]public class DynamicProxy implements InvocationHandler{ private Object object;// 被代理類的類引用 public DynamicProxy(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beforeDefend(); //調(diào)用被代理類對象的方法 Object result = method.invoke(object, args); afterDefend(); return result; } private void beforeDefend(){ System.out.print("我是原告律師,以下是我方辯詞"); } private void afterDefend(){ System.out.print("辯護完畢"); } }

  解釋一下這個 invoke 方法,我們通過 invoke 方法來調(diào)用具體的被代理方法,也就是真實的方法,如果對反射機制了解的話, method.invoke(object,args) 這句代碼應該很好理解,object 是被代理類,method 是被代理類的方法,args 是方法的參數(shù)。

  我們僅僅是實現(xiàn)了 InvocationHandler 的接口,那么接下來該做什么呢?怎么實現(xiàn)動態(tài)生成代理者對象呢?Java 的 java.lang.reflect 包下 還有一個 Proxy 類,它有個靜態(tài)方法 newProxyInstance(),我們使用這個方法生成。以前面 我們的代理律師的例子為例,

[code]public class Client { public static void main(String[] args) { //被代理類 IDefender accuser = new Accuser(); accuser.defend(); DynamicProxy proxy = new DynamicProxy(accuser); ClassLoader loader = accuser.getClass().getClassLoader(); IDefender proxyIDefender = (IDefender) Proxy.newProxyInstance(loader, new Class[]{IDefender.class}, proxy); proxyIDefender.defend(); } }

  這個客戶端的輸出結果,和之前是一樣的,可以發(fā)現(xiàn),我們將之前代理類的工作,轉(zhuǎn)換到 InvocationHandler 的 invoke() 方法去執(zhí)行,不再需要關心到底需要代理誰。

動態(tài)代理在 Retrofit 框架中的運用  Retrofit 是 Android 上流行的 Http Client請求庫先看以下一段代碼

[code]interface GitHubService { @GET("/repos/{owner}/{repo}/contributors") List<Contributor> repoContributors( @Path("owner") String owner, @Path("repo") String repo); }

[code]Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com") .build(); //代理模式的運用 GitHubService service = retrofit.create(GitHubService.class);

[code]Call

  本文關鍵詞:設計模式解析,由筆耕文化傳播整理發(fā)布。



本文編號:236203

資料下載
論文發(fā)表

本文鏈接:http://sikaile.net/wenshubaike/mishujinen/236203.html


Copyright(c)文論論文網(wǎng)All Rights Reserved | 網(wǎng)站地圖 |

版權申明:資料由用戶6dd0d***提供,本站僅收錄摘要或目錄,作者需要刪除請E-mail郵箱bigeng88@qq.com
中文字幕日韩精品人一妻| 亚洲欧美日韩精品永久| 国内胖女人做爰视频有没有| 久久夜色精品国产高清不卡| 欧美日韩国产综合在线| 国产免费无遮挡精品视频| 欧美色欧美亚洲日在线| 加勒比日本欧美在线观看| 最新午夜福利视频偷拍| 欧美日本精品视频在线观看| 国产成人精品综合久久久看| 国产精品福利精品福利| 少妇人妻无一区二区三区| 国产精品欧美激情在线观看| 妻子的新妈妈中文字幕| 丰满人妻一二三区av| 中文字幕91在线观看| 日本亚洲欧美男人的天堂| 在线免费国产一区二区三区| 国产精品福利一级久久| 偷拍美女洗澡免费视频| 国产在线日韩精品欧美| 欧美一区二区三区播放| 手机在线不卡国产视频| 国产午夜福利在线免费观看| 高清欧美大片免费在线观看| 国产精品久久男人的天堂| 日本不卡一区视频欧美| 国产一区二区三区丝袜不卡| 欧美尤物在线观看西比尔| 日韩国产亚洲一区二区三区| 日韩欧美国产精品自拍| 亚洲一区二区三区四区性色av| 高潮少妇高潮久久精品99| 高清一区二区三区大伊香蕉| 日韩欧美91在线视频| 爱在午夜降临前在线观看| 亚洲精品偷拍一区二区三区| 亚洲欧美国产中文色妇| 欧美加勒比一区二区三区| 不卡视频免费一区二区三区|