1. 程式人生 > >設計模式(四)---- 代理模式

設計模式(四)---- 代理模式

 

代理模式(Proxy Pattern)

核心作用:通過代理控制物件的訪問;可以詳細訪問某個類或物件的方法,在呼叫這個方法之前做前置處理,呼叫這個方法之後做後置處理;(AOP的微實現)

核心角色:

  (1)抽象角色:定義代理角色和真實角色的公共對外方法;

  (2)真實角色:實現抽象角色,定義真實角色所要實現的業務邏輯,供代理角色呼叫;(關注真正的業務邏輯)

  (3)代理角色:實現抽象角色,是真實角色的代理,通過真實角色的業務邏輯方法來實現抽象方法並附加自己的操作;將統一的流程控制放到代理角色中處理。

應用場景:

  安全代理:遮蔽堆真實角色的直接訪問;

  遠端代理:通過代理類處理遠端方法呼叫(RMI);

  延時載入:先載入輕量級的代理物件,真正需要時在載入真實物件。

         

分類:

  靜態代理(靜態定義代理類)

    動態代理(動態生成代理類)

    JDK自帶的動態代理;

    java assist 位元組碼操作實現;

    CGLIB

    ASM(底層使用指令,可維護性較差)

一、靜態代理模式

抽象角色:

public interface Star
{
    void confer();      //面談
    void signContract();//籤合同
    void bookTicket();  //
訂票 void sing(); //唱歌 void collectMoney();//收錢 }

真實角色:

public class RealStar implements Star
{
    @Override
    public void confer()
    {
        System.out.println("RealStar.confer()");
    }

    @Override
    public void signContract()
    {
        System.out.println("RealStar.signContract()");
    }

    @Override
    
public void bookTicket() { System.out.println("RealStar.bookTicket()"); } @Override public void sing() { System.out.println("RealStar.sing(周杰倫)"); } @Override public void collectMoney() { System.out.println("RealStar.collectMoney()"); } }

代理角色:

public class ProxyStar implements Star
{
    private Star star;

    public ProxyStar(Star star)
    {
        this.star = star;
    }

    @Override
    public void confer()
    {
        System.out.println("ProxyStar.confer()");
    }

    @Override
    public void signContract()
    {
        System.out.println("ProxyStar.signContract()");
    }

    @Override
    public void bookTicket()
    {
        System.out.println("ProxyStar.bookTicket()");
    }

    @Override
    public void sing()
    {
        star.sing();
    }

    @Override
    public void collectMoney()
    {
        System.out.println("ProxyStar.collectMoney()");
    }
}

測試程式碼:

public class Test
{
    public static void main(String[] args)
    {
        RealStar realStar = new RealStar();
       Star star = new ProxyStar(realStar);

        star.confer();
        star.signContract();
        star.bookTicket();
        star.sing();    //
        star.collectMoney();
    }
}

 

二、動態代理(Dynamic Proxy)

動態代理相比於靜態代理的優點:

抽象角色(介面)中宣告的所有方法都被轉移到呼叫處理器一個集中的方法中,這樣我們可以使用更加靈活統一的處理眾多的方法。

1、JDK自帶的類

(1)動態代理需要的處理

  java.lang.reflect.InvocationHandler (處理器介面):可以通過 invoke 方法實現對真實物件的代理訪問;每次通過Proxy生成的代理類物件時都有指定代理器物件。

  java.lang.reflect.Proxy : 生成代理類和物件。

(2)程式碼實現:抽象角色、真實角色同上

代理角色:

public class ProxyStar implements InvocationHandler
{
    private Star star;

    public ProxyStar(Star star)
    {
        this.star = star;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable
    {
        Object object = null;

        System.out.println("籤合同");
        System.out.println("定機票");
        if("sing".equals(method.getName()))  //執行的方法名為sing時, 呼叫真實角色的sing方法
        {
            object = method.invoke(star, args);
        }
        System.out.println("最後的方法執行");
        return object;
    }
}

測試類程式碼:

public class Test
{
    public static void main(String[] args)
    {
        Star realStar = new RealStar();
        InvocationHandler invocationHandler = new ProxyStar(realStar);

        //生成代理物件
        Star proxy = (Star) Proxy.newProxyInstance(
                RealStar.class.getClassLoader(), //ClassLoader.getSystemClassLoader(),
                RealStar.class.getInterfaces(),  //new Class[]{Star.class},
                invocationHandler);

        //只要呼叫了代理物件的任何一個方法都會進入 InvocationHandler 實現類的 invoke() 方法
        proxy.sing();
    }
}