代理模式
以下是个人知识储备有限,理解有限,大牛勿喷。
代理模式就我们生活中的代理服务,火车票代售处一样,能够提供原本服务器或火车站原本的功能,同时提供一些额外的服务。
下面举出一个场景,虽然场景不是很好,用 车和售票处这些会比较好理解。
但是学习其中的本质就好了。脱离场景学习本质,能够不用根据场景去思考代码的存在意义,而不是机械的照搬,这才是学会了。同时一个设计模式的来源又是生活场景。相辅相成。
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 不变化,看下面两个代理类(MakeupWomanProxy 和 AgentManProxy )的改动
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结果
测试类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结果
仅仅通过修改对应的代理顺序即可完成 代理顺序的控制,比继承方式的静态代理又方便了一点,但是代码稍微比继承方式的复杂点。
动态代理
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();
}
}
结果