生活中的栗子
去过洗脚城的同学都知道按摩的是13号技师,收费的却是黑心老板,为啥不是13号小妹呢?这又是为啥捏?我们的13号技师兢兢业业只为了服务更好、技艺更精湛,并不懂招揽顾客以及谈判价钱。黑心老板的出现可以让13号技师更专注于自己的事业,又可以推出更多附加服务。这便是代理模式。
下面咱们用代码实现
接口类 Message.java
public interface Message {
// 马杀鸡服务
void message();
}
实现类 Worker13.java
public class Worker13 implements Message {
@Override
public void message() {
System.out.println("13号技师为您服务~");
}
}
代理类 WorkManager.java
public class WorkManager implements Message {
private Message worker;
public void setWorker(Message worker) {
this.worker = worker;
}
@Override
public void message() {
// 前置动作:黑心老板可以在此推出各种活动
System.out.println("欢迎光临");
// 被代理类执行:13号技师服务
worker.message();
// 后置动作:黑心老板可以在此收费或其他安排
System.out.println("本次服务收费200块");
}
}
下面是测试类和测试结果:
public static void main(String[] args) {
Worker13 worker13 = new Worker13();
WorkManager workManager = new WorkManager();
workManager.setWorker(worker13);
// 执行马杀鸡服务
workManager.message();
}
欢迎光临
13号技师服务~
本次服务收费200块
BUILD SUCCESSFUL in 961ms
那代理模式有啥好处嘞?
-
中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
-
开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
静态代理虽好但有局限性,请看动态代理
若干年后12号技师重出江湖并学会独门技术wash!这让黑心老板很是尴尬,他只是马杀鸡的代理,不是wash的代理。如果要代理则要更改逻辑,改一个还好,若是再来一个岂不是又要改,怎样才能一劳永逸,黑心老板陷入沉思-----这便是动态代理的初衷!
12号技师的实现类:Worker12.java
public class Worker12 implements Message, Wash {
@Override
public void message() {
System.out.println("12号技师为您服务~");
}
@Override
public void wash(String text) {
System.out.println("12号技师给您表演个绝活:" + text);
}
}
黑心老板的进阶:ManagerProxy.java
public class ManagerProxy implements InvocationHandler {
private Object object;
/**
* 放入被代理类:12号多技能技师
* @param object
*/
public ManagerProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("**************黑心老板:什么技能我都能代理**************");
// result用于接收返回值
Object result = method.invoke(object, objects);
System.out.println("本次服务收费:200块");
return result;
}
}
下面是测试类和测试结果:
public class ProxyMain {
public static void main(String[] args) {
Worker12 worker12 = new Worker12();
// 第一个参数是被代理类的类加载器
Object o = Proxy.newProxyInstance(Worker13.class.getClassLoader(),
// 第二个参数放被代理类的接口
new Class[]{Message.class, Wash.class},
new ManagerProxy(worker12));
Message message = (Message) o;
message.message();
Wash wash = (Wash) o;
wash.wash("胸口碎大石");
}
}
**************黑心老板:什么技能我都能代理**************
12号技师为您服务~
本次服务收费:200块
**************黑心老板:什么技能我都能代理**************
12号技师给您表演个绝活:胸口碎大石
本次服务收费:200块
BUILD SUCCESSFUL in 749ms
本篇文章只介绍用法,下篇文章剖析动态代理