源码git地址 https://github.com/dlovetco/designMode
问题提出
请用代码实现小明通过小刚向小红送礼物(注意:不能让小红知道是小明送的礼物)
public class Main {
public static void main(String[] args) {
ZhuiQiuZhe ming = new ZhuiQiuZhe("小明");
BeiZhuiQiuZhe hong = new BeiZhuiQiuZhe("小红");
DianDengPao gang = new DianDengPao(ming, "小刚");
gang.sendGift(hong);
}
}
/**
* 追求者
*/
class ZhuiQiuZhe {
//追求者姓名
public String name;
public ZhuiQiuZhe(String name) {
this.name = name;
}
//送礼物
public void sendGift(BeiZhuiQiuZhe beiZhuiQiuZhe) {
System.out.println(name + "给" + beiZhuiQiuZhe.name + "送礼物");
}
}
/**
* 电灯泡———用于传递礼物
*/
class DianDengPao {
//帮谁送东西
public ZhuiQiuZhe zhuiQiuZhe;
private String name;
public DianDengPao(ZhuiQiuZhe zhuiQiuZhe, String name) {
this.zhuiQiuZhe = zhuiQiuZhe;
this.name = name;
}
//送礼物
public void sendGift(BeiZhuiQiuZhe beiZhuiQiuZhe) {
System.out.print(name + "帮助");
zhuiQiuZhe.sendGift(beiZhuiQiuZhe);
}
}
/**
* 被追求者
*/
class BeiZhuiQiuZhe {
//追求者姓名
public String name;
public BeiZhuiQiuZhe(String name) {
this.name = name;
}
}
输出结果为:小刚帮助小明给小红送礼物。上面代码主要特点是电灯泡类里面保存了一个追求者类的引用,然后在电灯泡类的送礼物方法里面几乎完全使用追求者的送礼物方法。这种方法就叫做代理模式。这样的话追求者类和被追求者类相互之间没有任何关系,实现了安全性。
模式抽象化
抛开上面的实际例子,我们可以用更一般的代码来实现简单的代理模式
public class Main {
public static void main(String[] args) {
new Proxy(new RealSubject()).doSth();
}
}
/**
* 需要被代理的事情
*/
interface Subject {
void doSth();
}
/**
* 事情真正的发起人
*/
class RealSubject implements Subject {
@Override
public void doSth() {
System.out.println("实体类真正在做的事情");
}
}
/**
* 代理类
*/
class Proxy implements Subject {
private RealSubject realSubject;
Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void doSth() {
if (realSubject != null) {
realSubject.doSth();
}
}
}
以上代理模式的plantuml代码如下
@startuml
interface Subject{
doSth()
}
class RealSubject{
doSth()
}
class Proxy{
RealSubject realSubject
doSth()
}
Subject <|.. Proxy
Subject <|.. RealSubject
RealSubject <-- Proxy
@enduml
代理模式的四大用处:
- 远程代理:为一个对象在不同的地址空间提供局部代表,用于隐藏一个对象存在于不同地址空间的事实。(狡兔三窟???)
- 虚拟代理:根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象。一般用于性能优化。比如打开一个网页,里面有很多张大图片。一般的做法都是使用虚拟代理对象在相应的位置占一个坑,然后再通过虚拟对象慢慢实例化出真实对象。
- 安全代理:用来控制真实对象访问时的权限。(就是不让其他人知道有真实对象的存在,因为所有事情都是通过代理对象执行的,加强了安全性,避免恶意反射破坏)
- 智能指引:可以在真实对象方法的基础上增加一些其他的操作。比如计算总共调用了多少次真实对象的方法。此时就可以在代理对象的方法上增加计数器来实现。