代理模式

代理模式

以下是个人知识储备有限,理解有限,大牛勿喷。
代理模式就我们生活中的代理服务,火车票代售处一样,能够提供原本服务器或火车站原本的功能,同时提供一些额外的服务。

下面举出一个场景,虽然场景不是很好,用 车和售票处这些会比较好理解。
但是学习其中的本质就好了。脱离场景学习本质,能够不用根据场景去思考代码的存在意义,而不是机械的照搬,这才是学会了。同时一个设计模式的来源又是生活场景。相辅相成。
1. 唱歌动作
2. 一个明星
3. 一个化妆师
4. 一个经纪人

静态代理模式

继承模式

继承方式简单来讲就是对父类的方法的重写,加入代理类特由于逻辑代码,这种方式比较简单粗暴,在一些对象数量变化不大且比较少的情况下比较实用。
唱歌

package com.yangs.proxy.staticproxy1;

/**
 * Created by Ytadpole on 2018/2/17.
 */
public interface SingAble {
    void sing();
}

一个明星

package com.yangs.proxy.staticproxy1;

/**
 * Created by Ytadpole on 2018/2/17.
 */
public class StarMan implements SingAble{
    @Override
    public void sing() {
        System.out.println("a star-man is singing");
    }
}

化妆师

package com.yangs.proxy.staticproxy1;
/**
 * Created by Ytadpole on 2018/2/17.
 * 化妆师
 */
public class MakeupWoman extends StarMan{
    @Override
    public void sing() {
        System.out.println("化妆姐姐在演唱会开始前化妆准备");
        super.sing();
        System.out.println("化妆姐姐在演唱会结束后卸妆准备");
    }
}

测试类

package com.yangs.proxy.staticproxy1;

/**
 * Created by Ytadpole on 2018/2/17.
 */
public class Test {
    public static void main(String[] args){
        //只是化妆安排
        SingAble singAble = new MakeupWoman();
        singAble.sing();

        //行程安排,化妆安排
       // SingAble singAble = new AgentMan();
        //singAble.sing();
    }
}

结果查看
这里写图片描述

明星需要唱歌,需要化妆师对他的妆容做好准备,需要过了化妆师代理那关。
但是如果我们需要对明星的行程也进行安排好,就需要添加一个经纪人,负责明星演唱的行程。代码很简单,

package com.yangs.proxy.staticproxy1;

/**
 * Created by Ytadpole on 2018/2/17.
 * 经济人
 */
public class AgentMan extends MakeupWoman{
    @Override
    public void sing() {
        System.out.println("经纪人在演唱会开始前行程准备");
        super.sing();
        System.out.println("经纪人在演唱会结束后行程准备");
    }
}

如果我们需要先 化妆师化妆经纪人安排行程 就需要修改AgentMan和MakeupWoman之间的继承关系,或者新建一个其他类对具体的顺序进行设计。这里就暴露了 继承方式代理的不方便。


聚合模式

聚合模式的话,通过代理类都实现于 一个 接口,通过接口的方法调起一连串 代理类各自的 接口方法 ,修改具体的代码顺序来控制代理类相关顺序。

SingAble 接口和明星 StartMan 不变化,看下面两个代理类(MakeupWomanProxyAgentManProxy )的改动

package com.yangs.proxy.staticproxy2;

/**
 * Created by Ytadpole on 2018/2/17.
 */
public class MakeupWomanProxy implements SingAble{
    private SingAble starMan;

    public MakeupWomanProxy(SingAble starMan) {
        this.starMan = starMan;
    }

    @Override
    public void sing() {
        System.out.println("化妆姐姐在演唱会开始前化妆准备");
        this.starMan.sing();
        System.out.println("化妆姐姐在演唱会结束后卸妆准备");
    }
}
package com.yangs.proxy.staticproxy2;

/**
 * Created by Ytadpole on 2018/2/17.
 * 经纪人
 */
public class AgentManProxy implements SingAble{
    //经纪人的明星
    private SingAble starMan;

    public AgentManProxy(SingAble starMan) {
        this.starMan = starMan;
    }

    @Override
    public void sing() {
        System.out.println("经济人准备演唱行程");
        this.starMan.sing();
        System.out.println("演唱会完毕,经纪人打理会场");
    }
}

测试类1, 先AgentMan代理 再 MakeupWoman代理

package com.yangs.proxy.staticproxy2;

/**
 * Created by Ytadpole on 2018/2/17.
 *
 */
public class Test {
    public static void main(String[] args){
        StarMan starMan = new StarMan();
        MakeupWomanProxy makeupWomanProxy = new MakeupWomanProxy(starMan);
        AgentManProxy agentManProxy = new AgentManProxy(makeupWomanProxy);
        agentManProxy.sing();
    }
}

聚合代理测试1结果
聚合代理测试1结果

测试类2, 先MakeupWoman代理 再 AgentMan代理

package com.yangs.proxy.staticproxy2;

/**
 * Created by Ytadpole on 2018/2/17.
 *
 */
public class Test {
    public static void main(String[] args){
        StarMan starMan = new StarMan();
        AgentManProxy agentManProxy = new AgentManProxy(starMan);
        MakeupWomanProxy makeupWomanProxy = new MakeupWomanProxy(agentManProxy);
        makeupWomanProxy.sing();
    }
}

聚合代理测试2结果
聚合代理测试2结果

仅仅通过修改对应的代理顺序即可完成 代理顺序的控制,比继承方式的静态代理又方便了一点,但是代码稍微比继承方式的复杂点。


动态代理

package com.yangs.proxy.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * Created by Ytadpole on 2018/2/17.
 */
public class MakeupHandler implements InvocationHandler {
    //被代理对象
    private Object target;

    public MakeupHandler(Object target) {
        this.target = target;
    }

    /**
     *
     * @param proxy 被代理对象
     * @param method 被代理对象方法
     * @param args  被代理对象方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("化妆师姐姐化妆开始");
        method.invoke(target, args);
        System.out.println("化妆师姐姐卸妆完毕");
        return null;
    }
}

测试类

package com.yangs.proxy.dynamicproxy;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * Created by Ytadpole on 2018/2/17.
 */
public class Test {
    public static void main(String[] args){
        StarMan starMan = new StarMan();
        InvocationHandler invocationHandler = new MakeupHandler(starMan);

        Class<?> clazz = starMan.getClass();
        SingAble singAble = (SingAble) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), invocationHandler);
        singAble.sing();
    }
}

结果
动态代理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值