標籤:編輯器 access win 遠程 技術 時間 handler 圖形 ...
Proxy??
Proxy是“代理人”的意思,它指的是代替別人進行工作的人。代理實際上就是使用委託的機制,在代理的過程中你可以做點其他的事情,然後再來執行被代理對象的代碼。
1.什麼時候使用:
GoF書(請參見附錄E[GoF])在講解Proxy模式時,使用了一個可以在文本中嵌入繪圖物件(例片等)的文字編輯器作為例子。為了產生這些繪圖物件,需要讀取圖片檔案,這很耗費時間。因此如果在開啟文檔時就產生有所的繪圖物件,就會導致文檔開啟時間過長。所以,最好是當使用者瀏覽至文本中各個繪圖物件時,再去產生它們的執行個體。這時,Proxy模式就有了用武之地。
2.有那些代理:
- Virtual Proxy(虛擬代理)Virtual Proxy就是本章中學習的Proxy模式。只有當真正需要執行個體時,它才產生和初始化執行個體。
- Remote Proxy(遠程代理)Remote Proxy可以讓我們完全不必在意RealSubject角色是否在遠程網路上,可以如同它在自己身邊一樣(透明性地)調用它的 方法。Java的RMI(RemoteMethodInvocation:遠程方法調用)就相當於Remote Proxy。
Access Proxy Access Proxy 用於在調用RealSubject角色的功能時設定訪問限制。例如,這種代理可以只允許指定的使用者調用方法,而當其他使用者調用方法時則報錯。
靜態代理
1.使用委託機制代理人只代理他能解決的問題。當遇到他不能解決的問題時,還是會“轉交”給本人去解決。
這裡的“轉交”就是在本書中多次提到過的“委託”。從PrinterProxy類的print方法中調用real.print方法正是這種“委託”的體現。
- 為了實現PrinterProxy類可以從printer類中分離出來作為獨立的組件使用,而且只要是實現了Printable介面的類都可以扮演Proxy的角色。需要使用反射執行個體
private synchronized void realize(String classname) { if(real==null){ try { real = ((Printable) Class.forName(classname).newInstance()); }catch (ClassNotFoundException e){ System.out.println("沒有發現"+classname); }catch (Exception e){ e.printStackTrace(); } }}
在java的動態代理機制中,有兩個重要的類或介面,一個是 InvocationHandler(Interface)、另一個則是 Proxy(Class),這一個類和介面是實現我們動態代理所必須用到的。首先我們先來看看java的API協助文檔是怎麼樣對這兩個類進行描述的:
InvocationHandler:
InvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.
每一個動態代理類都必須要實現InvocationHandler這個介面,並且每個代理類的執行個體都關聯到了一個handler,當我們通過代理對象調用一個方法的時候,這個方法的調用就會被轉寄為由InvocationHandler這個介面的 invoke 方法來進行調用。我們來看看
InvocationHandler這個介面的唯一一個方法?invoke?方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
我們看到這個方法一共接受三個參數,那麼這三個參數分別代表什麼呢?
Object invoke(Object proxy, Method method, Object[] args) throws Throwableproxy: 指代我們所代理的那個真實對象method: 指代的是我們所要調用真實對象的某個方法的Method對象args: 指代的是調用真實對象某個方法時接受的參數
理清職責
- 實現一個帶名字的印表機
名字=====》》說明
Printer || 表示帶名字的印表機的類(本人)
Printable || Printer和PrinterProxy的共同介面
PrinterProxy || 表示帶名字的印表機的類(代理人)
Main ||測試程式行為的類
UML
類圖:
時序圖:
Code
public interface Printable { // 設定列印名字 void setPrinterName(String name); // 擷取列印名字 String getPrinterName(); // 顯示文字 void print(String string);}
···
public class Printer implements Printable{
private String name;
public Printer() { heavyjob("正在產生Printer執行個體");}public Printer(String name) { this.name = name; heavyjob("正在產生Printer執行個體("+name+")");}/** * 類比一個高負載任務 * @param string */private void heavyjob(String string) { System.out.println(string); for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } System.out.print("."); }}@Overridepublic void setPrinterName(String name) { this.name=name;}@Overridepublic String getPrinterName() { return name;}@Overridepublic void print(String string) { System.out.println("==="+name+"==="); System.out.println(string);}
}
···
public class PrinterProxy implements Printable{ private String name; private Printer real; /** * 不論 setPrinterName 方法和getPrinterName 方法被調用多少次, * 都不會產生Printer類的執行個體。只有當真正需要本人時, * 才會產生printer類的執行個體(printerProxy類的調用者完全不知道是否產生了本人,也不用在意是否產生了本人)。 * @param name */ public PrinterProxy(String name) { this.name = name; } @Override public synchronized void setPrinterName(String name) { if(real!=null){ real.setPrinterName(name); } this.name=name; } @Override public String getPrinterName() { return name; } @Override public void print(String string) { realize(); real.print(string); } private synchronized void realize() { if(real==null) real=new Printer(name); }}public class MainT { public static void main(String[] args) { Printable p=new PrinterProxy("Tom"); System.out.println("現在是"+p.getPrinterName()); p.setPrinterName("Cat"); System.out.println("現在是"+p.getPrinterName()); p.print("我是 Tomcat"); }}
現在是Tom現在是Cat正在產生Printer執行個體(Cat).....===Cat===我是 Tomcat
動態代理Code
public class Client { public static void main(String[] args) { Printable tom = new Printer("Tom"); DynamicProxy proxy = new DynamicProxy(tom); Printable o = (Printable) Proxy.newProxyInstance(proxy.getClass().getClassLoader(), tom.getClass().getInterfaces(), proxy); System.out.println(o.getClass().getName()); System.out.println("現在是"+o.getPrinterName()); o.print("Tomcat"); }}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 { System.out.println("準備執行"); System.out.println("Method:" + method); Object o = method.invoke(object, args); System.out.println("執行完畢"); return o; }}public interface Printable { // 設定列印名字 void setPrinterName(String name); // 擷取列印名字 String getPrinterName(); // 顯示文字 void print(String string);}public class Printer implements Printable{ private String name; public Printer() { heavyjob("正在產生Printer執行個體"); } public Printer(String name) { this.name = name; heavyjob("正在產生Printer執行個體("+name+")"); } /** * 類比一個高負載任務 * @param string */ private void heavyjob(String string) { System.out.println(string); for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } System.out.print("."); } } @Override public void setPrinterName(String name) { this.name=name; } @Override public String getPrinterName() { return name; } @Override public void print(String string) { System.out.println("==="+name+"==="); System.out.println(string); }}
Proxy模式(代理[延遲]模式)