一、什麼是Proxy模式
Proxy,代理的意思,它指的是代替别人進行工作的人。當不一定需要本人親自進行工作時,就可以尋找代理人去完成工作。在面向對象程式設計時,“本人”和“代理人”都是對象,要記住的一樣東西,就是代理人可以替代本人去做某些事情,意味着代理人和本人就具有一定程度相同的屬性和方法。
二、Proxy模式的原理
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPR10MJRUT3FFVPpHOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLxITO4UzN1ETM0EjMwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
Subject:定義了使Proxy和RealSubject之間一緻性的接口,上面也提及到,代理人和本人具有一定程度相同的屬性和方法;
Proxy、RealSubject:這兩者都實作了Subject接口,并且都有一定程度相同的屬性;
Client:負責使用Proxy模式。
三、Proxy模式示例
這段示例實作了一個“帶名字的列印機”。
1、Printable接口:
package com.cjs.proxy;
public interface Printable {
public abstract void setPrinterName(String name);//設定名字
public abstract String getPrinterName();//擷取名字
public abstract void print(String string);//顯示名字,列印
}
2、Printer類:
package com.cjs.proxy;
public class Printer implements Printable {
private String name;
private void heavyJob(String msg) {
System.out.println(msg);
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(".");
}
}
public Printer() {
heavyJob("正在列印Printer執行個體");
}
public Printer(String name) {
this.name = name;
heavyJob("正在列印Printer執行個體("+name+")");
}
@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);
}
}
Printer類定義了name屬性,用于設定和擷取”列印機名“,還定義了一個heavyJob,做一些”重活“,這裡是sleep5秒;
3、PrinterProxy類
package com.cjs.proxy;
public class PrinterProxy implements Printable {
private String name;
private Printable real;
private String className;
public PrinterProxy() {
}
public PrinterProxy(String name, String className) {
this.name = name;
this.className = className;
}
@Override
public 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) {
try {
real = (Printable) Class.forName(className).newInstance();
real.setPrinterName(name);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
System.out.println("沒有找到"+className+"類");
}
}
}
}
PrinterProxy類,用于代理Printer完成名字的設定和擷取,即一些簡單的任務,是以PrinterProxy類也具有name屬性,另外,還定義了Printable類型屬性,用于操作實作了Printable接口的類;當需要完成”重活“時,就需要交給”本人“Printer類,即print方法。注意,執行print方法時,會調用realize方法,realize方法裡面首先判斷Printable類型的屬性對象是否為null,不為null時,就建立一個這樣的對象,這是根據類名來擷取對象,能夠有效的将PrinterProxy和Printer解耦,隻要實作了Printable接口的類,就可以被PrinterProxy使用。
4、Main類
package com.cjs.proxy;
public class Main {
public static void main(String[] args) {
String className = "com.cjs.proxy.Printer";//這裡是類的全名
Printable p = new PrinterProxy("Alice", className);
System.out.println("現在的名字是" + p.getPrinterName() + ".");
p.setPrinterName("Bob");
System.out.println("現在的名字是" + p.getPrinterName() + ".");
p.print("hello world");
}
}
輸出結果:
在Main類中,一些簡單的name設定和name擷取,可以由PrinterProxy代理完成,到了print,則由真正的Printer類完成。