1. 程式人生 > >Java學習筆記之--------代理模式

Java學習筆記之--------代理模式

代理模式

代理模式的定義:為其他物件提供一種代理以控制對這個物件的訪問。在某些情況下,一個物件不適合或者不能直接引用另一個物件,而代理物件可以在客戶端和目標物件之間起到中介的作用。

組成: 抽象角色:通過介面或抽象類宣告真實角色實現的業務方法。 代理角色:實現抽象角色,是真實角色的代理,通過真實角色的業務邏輯方法來實現抽象方法,並可以附加自己的操作。 真實角色:實現抽象角色,定義真實角色所要實現的業務邏輯,供代理角色呼叫。

代理模式的類圖

在這裡插入圖片描述

靜態代理模式的程式碼實現 下面模擬租房來實現一下靜態代理模式。Client代表房客,Proxy代表中介(代理角色),Host代表房東(真實角色)。Rent介面代表抽象角色。

public interface Rent {
    public void  rent();
}
public class Host implements Rent{
    public void rent(){
        System.out.println("房屋出租");
    }
}
public class Proxy implements Rent{
    private Host host;
    public Proxy() {
    }
    public Proxy(Host host) {
        this.host = host;
    }
    public void setHost(Host host) {
        this.host = host;
    }
    //租房
    public void rent(){
        seeHouse();
        host.rent();
        fare();
    }
    //看房
    private void seeHouse(){
        System.out.println("帶房客看房");
    }
    //收中介費
    private void fare(){
        System.out.println("收取中介費");
    }
}
public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host);
        proxy.rent();
    }
}

執行結果如下所示: 在這裡插入圖片描述

由以上程式碼我們可以看出,使用靜態代理後,因為增加了代理類,我們的工作量變大了,開發效率就會降低。由此我們想到了——動態代理。

動態代理模式的程式碼實現 動態代理模式的代理類是動態生成的。動態代理大致分為兩類:基於介面的動態代理和基於類的動態代理。 jdk動態代理——Proxy類和InvocationHandler介面

  • InvocationHandler是代理例項的呼叫處理程式實現的介面。 每個代理例項都具有一個關聯的呼叫處理程式。對代理例項呼叫方法時,將對方法呼叫進行編碼並將其指派到它的呼叫處理程式的invoke方法。 invoke():在代理例項上處理方法呼叫並返回結果。在與方法關聯的代理例項上呼叫方法時,將在呼叫處理程式上呼叫此方法。

  • Proxy提供用於建立動態代理類和例項的靜態方法,它還是由這些方法建立的所有動態代理類的超類。 newProxyInstance():返回一個指定介面的代理類例項,該介面可以將方法呼叫指派到指定的呼叫處理程式。

動態代理的程式碼實現:

public interface UserService {
	public void add();
	public void update();
	public void delete();
	public void search();
}
public class UserServiceImpl implements UserService {
	@Override
	public void add() {
		System.out.println("增加使用者");
	}
	@Override
	public void update() {
		System.out.println("修改使用者資訊");
	}
	@Override
	public void delete() {
		System.out.println("刪除使用者資訊");
	}
	@Override
	public void search() {
		System.out.println("查詢使用者資訊");
	}
}
public class ProxyInovationHandler 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 代理類的呼叫處理程式的方法物件
     */
    @Override
    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 + "方法");
    }
}
public class Client {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        ProxyInovationHandler pih = new ProxyInovationHandler();
        pih.setTarget(userService);
        UserService proxy = (UserService) pih.getProxy();
        proxy.add();
        proxy.delete();
    }
}

執行結果如下圖: 在這裡插入圖片描述 代理模式的優缺點

  • 優點 (1)職責清晰,真實的角色就是實現實際的業務邏輯,不用關心其他非本職責的事務,通過後期的代理完成一件完成事務,附帶的結果就是程式設計簡潔清晰。 (2)代理物件可以在客戶端和目標物件之間起到中介的作用,這樣起到了中介的作用和保護了目標物件的作用。 (3)高擴充套件性,擴充套件公共業務變得更加集中方便。

  • 缺點 (1) 目標類必須實現某個介面,如果某個類沒有實現介面則不能生成代理物件。 (2)由於在客戶端和真實主題之間增加了代理物件,因此有些型別的代理模式可能會造成請求的處理速度變慢,例如保護代理。 (3) 實現代理模式需要額外的工作,而且有些代理模式的實現過程較為複雜,例如遠端代理。

  • 其他 一個動態代理一般代理某一類業務。一個動態代理可以代理多個類。

代理模式的使用場景 1、遠端代理。 2、虛擬代理。 3、Copy-on-Write 代理。 4、保護(Protect or Access)代理。 5、Cache代理。 6、防火牆(Firewall)代理。 7、同步化(Synchronization)代理。 8、智慧引用(Smart Reference)代理。

注意事項: 1、和介面卡模式的區別:介面卡模式主要改變所考慮物件的介面,而代理模式不能改變所代理類的介面。 2、和裝飾器模式的區別:裝飾器模式為了增強功能,而代理模式是為了加以控制。

以上為【2天學會spring框架-鄒波】視訊中部分內容加自己整理的一些內容,侵刪。