設計模式--代理模式

Java工程源碼

類圖

這裏寫圖片描述


定義
爲其它對象提供一種代理以控制對這個對象的訪問


優點
- 職責清晰 真實的角色就是實現的業務邏輯,不用關心其他非本指責的事務
- 高擴展性 具體主題角色不管怎麼變化,只要它實現了接口,代理類完全可以在不做任何修改的情況下使用
- 智能化 動態代理是最好的體現,即在運行階段才指定實際代理對象(Struts如何把表單元素映射到對象上?)


使用場景
典型應用如Spring AOP,Android AIDL


擴展
- 普通代理 要求客戶端只能訪問代理角色,而不能訪問真實角色
- 強制代理 要求客戶端必須通過真實角色找到代理角色(演員和經紀人)
- 虛擬代理 指在需要的時候,才初始化主題對象,可以避免被代理對象太多而引起的初始化緩慢問題

靜態代理

抽象主題類

public interface Subject {
    void request();
}

實體主題類

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject->request()");
    }
}

代理類

public class Proxy implements Subject {
    // 要代理哪個實現類
    private Subject subject = null;

    /**
     * 通過構造函數傳遞被代理者
     *
     * @param subject 被代理者
     */
    public Proxy(Subject subject) {
        this.subject = subject;
    }

    /**
     * 實現接口中定義的方法
     */
    @Override
    public void request() {
        this.before();// 預處理
        this.subject.request();
        this.after();// 善後處理
    }

    /**
     * 預處理
     */
    private void before() {
        System.out.println("預處理");
    }

    /**
     * 善後處理
     */
    private void after() {
        System.out.println("善後處理");
    }
}

靜態代理 場景類

public class Client {
    public static void main(String[] args) {
        //新建主題類
        RealSubject realSubject = new RealSubject();
        //代理主題類
        Subject proxySubject = new Proxy(realSubject);
        //執行代理類方法
        proxySubject.request();
    }
}

運行結果

預處理
RealSubject->request()
善後處理

動態代理

玩家接口

public interface IGamePlayer {
    void login(String user, String password);

    void killBoss();

    void upgrade();
}

實體玩家類

public class GamePlayer implements IGamePlayer {
    private String name = "";

    /**
     * 玩家 實現類
     *
     * @param _name 玩家名
     */
    public GamePlayer(String _name) {
        name = _name;
    }

    @Override
    public void killBoss() {
        System.out.println(name + "在打怪");
    }

    @Override
    public void login(String user, String password) {
        System.out.println("登錄名爲" + user + "的用戶  " + name + "登錄成功");
    }

    @Override
    public void upgrade() {
        System.out.println(name + "又升了一級");
    }
}

動態代理類 藉助java自帶的代理方法

public class DynamicProxy implements InvocationHandler {
    /**
     * 被代理者的實例
     */
    private Object obj = null;

    /**
     * 我要代理誰
     *
     * @param _obj 被代理者
     */
    public DynamicProxy(Object _obj) {
        this.obj = _obj;
    }

    /**
     * 執行代理
     *
     * @return 代理類
     */
    public Object proxy() {
        if (obj != null) {
            Class<?> cls = obj.getClass();
            return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this);
        }
        throw new RuntimeException("被代理者爲空");
    }

    /**
     * 調用被代理的方法
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result = method.invoke(this.obj, args);
        if (method.getName().equalsIgnoreCase("login")) {
            System.out.println("有人登錄");
        } else if (method.getName().equalsIgnoreCase("upgrade")) {
            System.out.println("有人升級了");
        }
        return result;
    }
}

場景類

public class Client {
    public static void main(String[] args) {
        // 新建玩家類
        IGamePlayer player = new GamePlayer("BobbyGu");
        // 動態代理一個玩家類
        IGamePlayer proxyPlayer = (IGamePlayer) new DynamicProxy(player).proxy();
        if (proxyPlayer != null) {
            //調用代理類方法
            proxyPlayer.login("BobbyGu", "123123");
            proxyPlayer.killBoss();
            proxyPlayer.upgrade();
        }
    }
}

運行結果

登錄名爲BobbyGu的用戶  BobbyGu登錄成功
有人登錄
BobbyGu在打怪
BobbyGu又升了一級
有人升級了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章