天天看點

【代理模式】靜态代理,動态代理

文章目錄

  • 代理模式
  • 靜态代理模式
  • 1、介紹
  • 2、例子:婚介公司
  • 3、優點
  • 動态代理模式
  • 1、介紹
  • 2、例子:租房中介公司
  • 3、優點

代理模式

靜态代理模式

1、介紹

1、真實角色和代理角色要實作同一個接口

2、代理角色要代理真實角色

3、給代理角色添加set方法(屬性為接口,進而解耦合),将某個真實角色注入到代理角色的屬性中,以便調用

2、例子:婚介公司

public class StaticProxyTest {
    public static void main(String[] args) {
        You you = new You();
        WeddingCompany weddingCompany = new WeddingCompany();
        weddingCompany.setMarry(you);
        /*
        這也是多線程Thread的原理
        new Thread(一個實作Runnable接口的類).start(),而且Thread本身也實作了Runnable接口
         */

        weddingCompany.HappyMarry();
    }
}

interface Marry {
    void HappyMarry();
}

//真實角色,你去結婚
class You implements Marry {
    @Override
    public void HappyMarry() {
        System.out.println("Marry~");
    }
}

//代理角色,幫你結婚
class WeddingCompany implements Marry {

    private Marry target;

    public void setMarry(Marry target) {
        //傳入真實角色
        this.target = target;
    }

    @Override
    public void HappyMarry() {
        before();
        this.target.HappyMarry(); //真實角色
        after();
    }

    private void before() {
        System.out.println("before--arrangement~");
    }

    private void after() {
        System.out.println("after--clear~");
    }
}      
【代理模式】靜态代理,動态代理

3、優點

代理角色可以做真實角色分外的事,進而真實角色專注做自己分内的事

動态代理模式

1、介紹

  • 動态代理的角色和靜态代理的一樣
  • 動态代理的代理類是動态生成的,靜态代理的代理類是我們提前寫好的
  • 動态代理分為兩類 : 一類是基于接口動态代理 , 一類是基于類的動态代理

    (1)基于接口的動态代理----JDK動态代理

    (2)基于類的動态代理----cglib

    (3)現在用的比較多的是 javasist 來生成動态代理 . 百度一下javasist

JDK的動态代理需要了解兩個類:

  • InvocationHandler
  • 【代理模式】靜态代理,動态代理
  • Proxy
  • 【代理模式】靜态代理,動态代理

2、例子:租房中介公司

public class DynamicProxyTest {
    public static void main(String[] args) {
        //真實角色
        Host host = new Host();

        //代理執行個體的調用處理程式
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setRent(host); //将真實角色放置進去!
        Rent proxy = (Rent)pih.getProxy(); //動态生成對應的代理類!
        proxy.rent();
    }
}

//接口
interface Rent {
    public void rent();
}

//真實角色: 房東,房東要出租房子
class Host implements Rent{
    public void rent() {
        System.out.println("房屋出租");
    }
}

//代理角色:中介
class ProxyInvocationHandler implements InvocationHandler {

    private Rent rent;
    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成代理類,重點是第二個參數,擷取要代理的抽象角色!之前都是一個角色,現在可以代理一類角色
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
            rent.getClass().getInterfaces(),this);
    }
    // proxy : 代理類 method : 代理類的調用處理程式的方法對象.
    // 處理代理執行個體上的方法調用并傳回結果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        //核心:本質利用反射實作!
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }
    //看房
    public void seeHouse(){
        System.out.println("帶房客看房");
    }
    //收中介費
    public void fare(){
        System.out.println("收中介費");
    }
}      
【代理模式】靜态代理,動态代理

更有普适性的例子(優化了 ProxyInvocationHandler 類):

public class DynamicProxyTest {
    public static void main(String[] args) {
        //真實角色
        Host host = new Host();

        //代理角色
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setTarget(host); //将真實角色放置進去!
        Rent proxy = (Rent)pih.getProxy(); //動态生成對應的代理類!
        proxy.rent();
    }
}

//接口
interface Rent {
    public void rent();
}

//真實角色: 房東,房東要出租房子
class Host implements Rent{
    public void rent() {
        System.out.println("房屋出租");
    }
}

//代理角色:中介
class ProxyInvocationHandler implements InvocationHandler {

    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }
    //生成代理類
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
        target.getClass().getInterfaces(),this);
    }
    // proxy : 代理類
    // method : 代理類的調用處理程式的方法對象.
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }
    public void log(String methodName){
        System.out.println("執行了"+methodName+"方法");
    }
}      
【代理模式】靜态代理,動态代理

3、優點

  • 可以使得我們的真實角色更加純粹 . 不再去關注一些公共的事情
  • 公共的業務由代理來完成 . 實作了業務的分工
  • 公共業務發生擴充時變得更加集中和友善
  • 一個動态代理 , 一般代理某一類業務
  • 一個動态代理可以代理多個類,代理的是接口