Java设计模式-Proxy代理模式
問(wèn)題分析:
什么是代理模式呢?其實(shí)我們?cè)谏钪胁⒉簧僖?jiàn)。對(duì)于程序員來(lái)說(shuō)最常接觸的莫過(guò)于代理上網(wǎng)了,連接大力服務(wù)器地址,就可以訪問(wèn)網(wǎng)絡(luò)。
還有每天吃飯趕進(jìn)度是常事,叫公司的同事幫忙帶飯也是一種代理;如果你辭職老板不給你發(fā)工資,那么你還得請(qǐng)個(gè)律師幫你打官司,這也是一種代理。總之生活中無(wú)處不在。
代理的定義:
為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。簡(jiǎn)單點(diǎn)就是在不直接操作訪問(wèn)對(duì)象的的情況下,找一個(gè)代理訪問(wèn)該對(duì)象,就是自己不想搞,這個(gè)其他人幫你搞。
基本UML圖:
具體問(wèn)題UML類(lèi)圖:
抽象主題類(lèi)Subject.java
package com.hust.staticProxy1;public abstract class Subject {public abstract void visit();//普通業(yè)務(wù)方法 } 實(shí)現(xiàn)抽象主題的真正主題類(lèi)RealSubject.java
package com.hust.staticProxy1;public class RealSubject extends Subject {public void visit() {System.out.println("Real Subject!");}} 代理類(lèi)ProxySubject.java
package com.hust.staticProxy1; //代理類(lèi) public class ProxySubject extends Subject {private RealSubject mRealSubject;//把被代理對(duì)象作為成員變量public ProxySubject(RealSubject mRealSubject){this.mRealSubject=mRealSubject;}public void visit() {mRealSubject.visit();//調(diào)用被代理對(duì)象的邏輯方法}} Client.java
package com.hust.staticProxy1;public class Client {/*** @param args*/public static void main(String[] args) {//實(shí)例化一個(gè)被代理對(duì)象RealSubject mRealSubject=new RealSubject();//用被代理對(duì)象構(gòu)造一個(gè)代理對(duì)象ProxySubject mProxySubject=new ProxySubject(mRealSubject);//調(diào)用代理對(duì)象的相關(guān)方法mProxySubject.visit();}} 代理模式的簡(jiǎn)單實(shí)現(xiàn):
設(shè)定一個(gè)故事情節(jié),小明上班遇到一個(gè)被老板拖欠工資甚至克扣工資的情況,這種情況下小明還是通過(guò)法律來(lái)解決問(wèn)題,一旦小明選擇走法律途徑解決該糾紛,那么不可避免的需要請(qǐng)個(gè)律師作為自己的訴訟代理人,我們將訴訟流程抽象在一個(gè)接口中。
訴訟接口類(lèi)
package com.hust.staticProxy2;public interface LawSuit {//提交申請(qǐng)void submit();//進(jìn)行舉證void burden();//開(kāi)始辯護(hù)void defend();//訴訟完成void finish(); } 具體訴訟人,就是被代理對(duì)象小明,就是他想做的事
package com.hust.staticProxy2;public class XiaoMing implements LawSuit {//被代理類(lèi),實(shí)現(xiàn)訴訟接口public void submit() {// 老板欠小明工資,小明只好申請(qǐng)仲裁System.out.println("老板欠小明工資,小明只好申請(qǐng)仲裁");}public void burden() {//小明證據(jù)充足,不怕告不贏System.out.println("這是合同書(shū)和過(guò)去一年的銀行卡工資流水");}public void defend() {// 鐵證如山,辯護(hù)也沒(méi)什么好說(shuō)的System.out.println("證據(jù)確鑿!不需要早說(shuō)些什么了!");}public void finish() {// 結(jié)果也肯定的System.out.println("訴訟成功,判決老板即日起七天內(nèi)結(jié)算工資");}} 代理律師類(lèi):就是代理對(duì)象,小明讓這個(gè)代理類(lèi)完成訴訟流程
package com.hust.staticProxy2; //律師代理類(lèi) public class Lawyer implements LawSuit{private LawSuit mLawSuit;public Lawyer(LawSuit mLawSuit){this.mLawSuit=mLawSuit;}public void submit() {// 調(diào)用被代理類(lèi)的方法mLawSuit.submit();}public void burden() {// 調(diào)用被代理類(lèi)的方法mLawSuit.burden();}public void defend() {// 調(diào)用被代理類(lèi)的方法mLawSuit.defend();}public void finish() {// 調(diào)用被代理類(lèi)的方法mLawSuit.finish();}} 客戶(hù)端類(lèi)
package com.hust.staticProxy2;public class ClientTest {/*** @param args*/public static void main(String[] args) {//構(gòu)造被代理對(duì)象小明LawSuit xiaoming=new XiaoMing();//小明委托代理對(duì)象律師Lawyer mLawyer=new Lawyer(xiaoming);//代理對(duì)象律師幫助小明提出訴訟申請(qǐng)mLawyer.submit();//代理對(duì)象律師進(jìn)行舉證mLawyer.burden();//代理對(duì)象律師代替小明進(jìn)行辯護(hù)mLawyer.defend();//代理對(duì)象律師完成訴訟mLawyer.finish();}} 輸出:
老板欠小明工資,小明只好申請(qǐng)仲裁 這是合同書(shū)和過(guò)去一年的銀行卡工資流水 證據(jù)確鑿!不需要早說(shuō)些什么了! 訴訟成功,判決老板即日起七天內(nèi)結(jié)算工資
代理模式的意義:
代理模式到底好處在哪里呢??
那先要說(shuō)一下代理模式中的三種角色了。
抽象角色:聲明真實(shí)對(duì)象和代理對(duì)象的共同接口。
代理角色: 代理對(duì)象角色內(nèi)部含有對(duì)真實(shí)對(duì)象的引用, 從而可以操作 真實(shí)對(duì)象,同時(shí)代理對(duì)象提供與真實(shí)對(duì)象相同的接口以便在任何時(shí)刻都能代替真實(shí)對(duì)象。同時(shí),代理對(duì)象,可以在執(zhí)行真實(shí)對(duì)象操作時(shí),附加其他的操作,相當(dāng)于對(duì)真實(shí)對(duì)象進(jìn)行封裝。
真實(shí)角色:代理角色所代表的真實(shí)對(duì)象,是我們最終要引用的對(duì)象。
代理模式的一個(gè)好處就是對(duì)外部提供統(tǒng)一的接口方法,而代理類(lèi)在接口中實(shí)現(xiàn)對(duì)真實(shí)類(lèi)的附加操作行為,從而可以在不影響外部調(diào)用情況下,進(jìn)行系統(tǒng)擴(kuò)展。也就是說(shuō),我要修改真實(shí)角色的操作的時(shí)候,盡量不要修改他,而是在外部在“包”一層進(jìn)行附加行為,即代理類(lèi)。例如:接口A有一個(gè)接口方法operator(),真實(shí)角色:RealA實(shí)現(xiàn)接口A,則必須實(shí)現(xiàn)接口方法operator()。客戶(hù)端Client調(diào)用接口A的接方法operator()。現(xiàn)在新需求來(lái)了,需要修改RealA中的operator()的操作行為。怎么辦呢?如果修改RealA就會(huì)影響原有系統(tǒng)的穩(wěn)定性,還要重新測(cè)試。這是就需要代理類(lèi)實(shí)現(xiàn)附加行為操作。創(chuàng)建代理ProxyA實(shí)現(xiàn)接口A,并將真實(shí)對(duì)象RealA注入進(jìn)來(lái)。ProxyA實(shí)現(xiàn)接口方法operator(),另外還可以增加附加行為,然后調(diào)用真實(shí)對(duì)象的operator()。從而達(dá)到了“對(duì)修改關(guān)閉,對(duì)擴(kuò)展開(kāi)放”,保證了系統(tǒng)的穩(wěn)定性。我們看客戶(hù)端Client調(diào)用仍是接口A的接口方法operator(),只不過(guò)實(shí)例變?yōu)榱薖roxyA類(lèi)了而已。也就是說(shuō)代理模式實(shí)現(xiàn)了ocp原則。
什么時(shí)候使用代理模式
當(dāng)我們需要使用的對(duì)象很復(fù)雜或者需要很長(zhǎng)時(shí)間去構(gòu)造,這時(shí)就可以使用代理模式(Proxy)。例如:如果構(gòu)建一個(gè)對(duì)象很耗費(fèi)時(shí)間和計(jì)算機(jī)資源,代理模式(Proxy)允許我們控制這種情況,直到我們需要使用實(shí)際的對(duì)象。一個(gè)代理(Proxy)通常包含和將要使用的對(duì)象同樣的方法,一旦開(kāi)始使用這個(gè)對(duì)象,這些方法將通過(guò)代理(Proxy)傳遞給實(shí)際的對(duì)象。 一些可以使用代理模式(Proxy)的情況:
1,一個(gè)對(duì)象,比如一幅很大的圖像,需要載入的時(shí)間很長(zhǎng)。
? ?2,一個(gè)需要很長(zhǎng)時(shí)間才可以完成的計(jì)算結(jié)果,并且需要在它計(jì)算過(guò)程中顯示中間結(jié)果
3,一個(gè)存在于遠(yuǎn)程計(jì)算機(jī)上的對(duì)象,需要通過(guò)網(wǎng)絡(luò)載入這個(gè)遠(yuǎn)程對(duì)象則需要很長(zhǎng)時(shí)間,特別是在網(wǎng)絡(luò)傳輸高峰期。
4,一個(gè)對(duì)象只有有限的訪問(wèn)權(quán)限,代理模式(Proxy)可以驗(yàn)證用戶(hù)的權(quán)限
代理模式(Proxy)也可以被用來(lái)區(qū)別一個(gè)對(duì)象實(shí)例的請(qǐng)求和實(shí)際的訪問(wèn),例如:在程序初始化過(guò)程中可能建立多個(gè)對(duì)象,但并不都是馬上使用,代理模式(Proxy)可以載入需要的真正的對(duì)象。這是一個(gè)需要載入和顯示一幅很大的圖像的程序,當(dāng)程序啟動(dòng)時(shí),就必須確定要顯示的圖像,但是實(shí)際的圖像只能在完全載入后才可以顯示!這時(shí)我們就可以使用代理模式(Proxy)。
總結(jié)
以上是生活随笔為你收集整理的Java设计模式-Proxy代理模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【错误记录】-eclipse 导入类 提
- 下一篇: Java设计模式-命令模式Command