1. 程式人生 > 資訊 >諾基亞在美國推出 G20 手機:Helio G35 晶片,價格 199 美元

諾基亞在美國推出 G20 手機:Helio G35 晶片,價格 199 美元

代理模式

定義:由於某些原因需要給某物件提供一個代理以控制該物件的訪問

結構:

  • 抽象主題(Subject): 介面宣告要實現的業務方法
  • 真實主題 (Real Subject): 實現抽象主題裡的業務方法
  • 代理類(Proxy):提供了與真實主題相同的介面,它可以擴充套件、控制真實主題的功能。

代理模式的結構很簡單,是通過繼承抽象主題的代理類來包含真實主題,從而來實現對真實主題的訪問。

程式碼示例:

public interface Ticket {

    void buyTicket();
}
public class OfficialTicket implements Ticket {
    @Override
    public void buyTicket() {
        System.out.println("官方途徑購票");
    }
}
public class ProxyTicket implements Ticket {

    private OfficialTicket officialTicket=new OfficialTicket();

    @Override
    public void buyTicket() {
        System.out.println("我把錢給了去哪網,委託購票");
        officialTicket.buyTicket();
    }
}

測試程式碼:

public static void main(String[] args) throws InterruptedException, CloneNotSupportedException {
        ProxyTicket proxyTicket = new ProxyTicket();
        proxyTicket.buyTicket();

以上就是代理模式的實現,也可以說是靜態代理

靜態代理的侷限性:

  1. 如果我們需要再增加一個需要代理的方法,那我們需要修改上面3個類,每個類都要加對應的邏輯。
  2. 如果我們想再代理一個其他的物件,也需要對代理類進行修改。

那麼如果用動態代理實現上面的程式碼會怎麼樣呢?

Ticket類和OfficialTicket不變

public class TicketInvocationHandler implements InvocationHandler {

    private Ticket ticket;

    public TicketInvocationHandler(Ticket ticket) {
        this.ticket = ticket;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我把錢給了去哪網,委託購票");
        method.invoke(ticket,args);
        return null;
    }
}

測試程式碼:

public static void main(String[] args) throws InterruptedException, CloneNotSupportedException {
     
        Ticket ticket = new OfficialTicket();
        //將操作者物件進行注入
        TicketInvocationHandler handler = new TicketInvocationHandler(ticket);
        //生成代理物件
        Ticket operationProxy = (Ticket) Proxy.newProxyInstance(ticket.getClass().getClassLoader(),
                ticket.getClass().getInterfaces(), handler);
       operationProxy.buyTicket();
    }

此時如果我們想增加一個退票方法,如果用動態代理,那麼只需要改動Ticket類和OfficialTicket類。

Cglib實現:

public class TicketMethodInterceptor implements MethodInterceptor {


    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("我把錢給了去哪網,委託購票");
        Object object = proxy.invokeSuper(obj, args);
        return object;
    }
}

測試程式碼:

 public static void main(String[] args) throws InterruptedException, CloneNotSupportedException {
        Enhancer enhancer = new Enhancer();
        // 設定enhancer物件的父類
        enhancer.setSuperclass(OfficialTicket.class);
        // 設定enhancer的回撥物件
        enhancer.setCallback(new TicketMethodInterceptor());
        // 建立代理物件
        Ticket proxy= (Ticket)enhancer.create();
        // 通過代理物件呼叫目標方法
        proxy.buyTicket();
    }

返回目錄