代理模式
代理模式屬于結(jié)構(gòu)型模式.分為靜態(tài)代理與動(dòng)態(tài)代理.
比如說 用戶現(xiàn)在要買車,只要一輛車直接去車商買,肯定不會(huì)賣給你啊.這個(gè)時(shí)候用戶就會(huì)找到4S店
讓4S店幫忙購買,在從4S那兒買到車子.
在整個(gè)交易過程中4S的存在就是一個(gè)代理商,用戶作為委托者,代理商幫委托者完成委托者的述求.
應(yīng)用場景
- 為一個(gè)對象的引用提供額外操作
- 控制一個(gè)對象的訪問,為不同的用戶提供不同的權(quán)限級別
- 被訪問對象不想暴露所有細(xì)節(jié)方法,可代理不想暴露的方法
- 一個(gè)對象不想直接被另一個(gè)對象訪問
代碼示例(靜態(tài)代理)
(一)抽象購車代理接口
public interface Car {
void buyCar();
}
(二)用戶實(shí)現(xiàn)購車接口
public class UserBuyCar implements Car {
private String name;
@Override
public void buyCar() {
System.out.print("\n"+"用戶買了"+getName());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
(三)代理商4S店
public class CarStoreProxy implements Car {
private UserBuyCar car;
public CarStoreProxy(UserBuyCar car) {
this.car = car;
}
@Override
public void buyCar() {
if (car.getName().equals(ProxyTest.AUDI) ||
car.getName().equals(ProxyTest.BMW) ||
car.getName().equals(ProxyTest.BENZ)) {
car.buyCar();
} else {
System.out.print("\n" + "用戶什么也沒買");
}
}
}
(四)調(diào)用方式
//靜態(tài)代理 買奧迪
UserBuyCar userBuyCar=new UserBuyCar();
userBuyCar.setName(AUDI);
CarStoreProxy audiCarStoreProxy=new CarStoreProxy(userBuyCar);
audiCarStoreProxy.buyCar();
//靜態(tài)代理 什么也不買
UserBuyCar userBuyCar1=new UserBuyCar();
userBuyCar1.setName(NONE);
CarStoreProxy carStoreProxy=new CarStoreProxy(userBuyCar1);
carStoreProxy.buyCar();
顯示結(jié)果
用戶買了audi
用戶什么也沒買
以上為用戶買車過程中,4S作為代理商,用戶委托買車的流程案例.實(shí)現(xiàn)類和代理類保證統(tǒng)一性必須都實(shí)現(xiàn)同一個(gè)接口方法.含有具體的代理類.
接口也只能作用于當(dāng)前這個(gè)用戶,如果新添加了方法(租車),所有的實(shí)現(xiàn)類和代理類都需要實(shí)現(xiàn)新方法.
-
靜態(tài)代理優(yōu)點(diǎn)
- 使用者只需要關(guān)注用戶業(yè)務(wù)自身的邏輯
-
靜態(tài)代理缺點(diǎn)
- 一個(gè)接口只能作用于一個(gè)對象
- 接口新方法后,所有實(shí)現(xiàn)類 代理類都需要新增方法
代碼示例(動(dòng)態(tài)代理)
在代理模式中的動(dòng)態(tài)代理,不同于靜態(tài)代理含有具體代理類.
動(dòng)態(tài)代理中只要通過反射機(jī)制動(dòng)態(tài)生成代理類,具體代理對象在運(yùn)行時(shí)生成.
Java動(dòng)態(tài)代理Proxy
/獲取指定代理對象所關(guān)聯(lián)的調(diào)用處理器
static InvocationHandler getInvocationHandler(Object proxy )
獲取關(guān)聯(lián)于指定類裝載器和一組接口的動(dòng)態(tài)代理類的類對象
static Class getProxyClass(ClassLoader loader,Class[] interfaces)
判斷指定類對象是否是一個(gè)動(dòng)態(tài)代理類
static boolean isProxyClass(Class cl )
為指定類裝載器君账、一組接口及調(diào)用處理器生成動(dòng)態(tài)代理類實(shí)例
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h )
在newProxyInstance第三個(gè)參數(shù)中的InvocationHandler含有一個(gè)invoke方法,實(shí)現(xiàn)對委托者代理訪問,在每次動(dòng)態(tài)代理都需要通過它指定的調(diào)用器對象.
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(object,args);
return result;
}
實(shí)現(xiàn)InvocationHandler定義動(dòng)態(tài)代理類
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 {
Object result = method.invoke(object,args);
return result;
}
}
調(diào)用方式
//動(dòng)態(tài)代理 買奔馳
UserBuyCar userBuyCar2=new UserBuyCar();
userBuyCar2.setName(BENZ);
DynamicProxy dynamicProxy=new DynamicProxy(userBuyCar2);
Car car=(Car) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Car.class}, dynamicProxy);
car.buyCar();
顯示結(jié)果
用戶買了benz
結(jié)果與靜態(tài)代理效果一致,調(diào)用只需要傳入具體的委托者即可動(dòng)態(tài)生成代理類.相比于靜態(tài)代理更為靈活方便