代理模式:
爲其他對象提供一種代理以控制對這個對象的訪問,有時委託類不適合或不能直接引用另一個對象時,代理類就在兩方之間起到一個橋樑的作用。代理設計模式符合開閉原則 ,在不修改原有類的基礎上,增強原有類的功能邏輯。
代理模式優點:
增強真實對象
保護真是對象
降低系統耦合度,擴展性好
代理模式缺點:
代理類使系統設計時的類增多
靜態代理: 一個接口,兩個類:真實業務類,代理類
靜態體現在:代理類和真實類的關係在程序運行前就確定了
在靜態代理的實現中,需要定義一個接口,真實業務類和代理類都要實現這個接口,同時在代理類中,要定義一個真實對象的引用,通過構造方法傳給代理類對象,然後在調用業務方法時,調用真實類的業務實現
//定義了業務的實現規範
interface Buy {
void buyMac();
void buyGivenchy();
}
//真實類(委託類)真實業務的實現
class Real implements Buy{
@Override
public void buyMac() {
System.out.println("buy a mac");
}
@Override
public void buyGivenchy() {
System.out.println("buy a givenchy");
}
}
//代理類 代理Real類蒐集有的功能,並做額外的增強
class ProxyClass implements Buy{
//引用接口對象使得代理類可以訪問實體
private Buy buy;
public ProxyClass(Buy buy){
this.buy = buy;
}
//其實代理類的本質還是用了委託類的具體方法
@Override
public void buyMac() {
System.out.println("買");
this.buy.buyMac();
}
@Override
public void buyGivenchy() {
System.out.println("買");
this.buy.buyGivenchy();
}
}
public class ProxyDemo {
public static void main(String[] args) {
Buy buy = new ProxyClass(new Real());
buy.buyMac();
buy.buyGivenchy();
}
}
靜態代理是效率最高效率的代理模式,但它也存在缺陷
**靜態代理缺陷:**每一個需要被代理的類或接口,都要爲其實現一個代理類,如果需要代理的類或接口很多,就導致要實現的代理類也很多,這時引入動態代理。動態代理是由一個代理類來代理所有需要被代理的類或接口
動態代理:
在程序運行時有JVM創建代理類,此時的這個代理類可以代理任何需要被代理的類或接口,動態體現在這裏
今天來說JDK代理:
JDK代理就是使用JDK內置的方法去實現代理模式,有兩個核心的類Proxy和InvocationHandle
Proxy:調度器
InvocationHandle:增強器
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
有三個參數:
真是對象的類加載器
真是對象實現的接口
真實對象實例
實現動態代理:
interface ISubject{
public void eat(int num,String msg);
}
//真是業務類
class RealImpl implements ISubject{
@Override
public void eat(int num,String msg) {
System.out.println("I want to buy "+ num + msg);
}
}
//實現InvocationHandler的代理類
class ProxySubject implements InvocationHandler{
private Object target;
public ProxySubject(){ }
public Object bind(Object target){
this.target = target;
//通過JDK獲取代理類對象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);//此時的this是真實類的對象
}
public void preHandle(){
System.out.println("before buy");
}
public void afterHandle() {
System.out.println("after buy");
}
//通過invoke方法對真是業務做增強以及調用真實業務
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
this.preHandle();
Object obj = method.invoke(this.target,args);
this.afterHandle();
return obj;
}
}
public class JDKProxyDemo {
public static void main(String[] args) {
ISubject subject = (ISubject) new ProxySubject().bind(new RealImpl());
//此時真實類與代理已經建立聯繫
subject.eat(3,"apples");
}
}