代理模式(Proxy Pattern)从最初代码到一步步改进
代理模式产生的动机:
在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给会给使用者或者系统节后带来很多麻烦。
如何在不失去透明操作对象的同时来管理/控制这些对象特有的负责性?增加一层间接层是软件开发中常见的解决方式。
## 代理模式的导出:
场景描述:
前提:卓佳怡喜欢娇娇,但是娇娇不认识卓佳怡:
1.卓佳怡给娇娇送花,送巧克力,送洋娃娃
2.卓佳怡也可以找一个人,让这个人把鲜花,巧克力和洋娃娃送给娇娇。
这是两种方式,但是达到的目的是一样的。
代码实现:
1.没有代理的代码
//追求者
class Pursuit
{
SchoolGirl mm;
public Pursuit(SchoolGirl mm)
{
this.mm=mm;
}
public void DiveDolls()
{
System.out.println(mm.Name+"送你洋娃娃");
}
public void GiveFlowers()
{
System.out.println(mm.Name+"送你鲜花");
}
public void GiveChocolate()
{
System.out.println(mm.Name+"送你巧克力");
}
}
//被追求者
class SchooleGirl
{
private String name;
public String getName()
{return name;}
public setName(String value)
{name = value;}
}
//客户端代码
public class Program
{
public static void main(String[] args)
{
SchoolGirl jiaojiao = new SchoolGirl();
jiaojiao.setName("李娇娇");
Pursuit zhuojiayi = new Pursuit(jiaojiao);
//从代码来看,卓佳怡和娇娇是认识的,并且,卓佳怡直接把鲜花巧克力和洋娃娃送给了娇娇。但是娇娇不认识卓佳怡
zhuojiayi.GiveDolls();
zhuojiayi.GiveFlowers();
zhuojiayi.GiveChocolate();
}
}
2.只有代理的代码
class Proxy
{
SchoolGirl mm;
public Proxy(SchoolGirl mm)
{
this.mm = mm;
}
public void GiveDolls()
{
System.out.println(mm.Name+"送你洋娃娃");
}
public void GiveFlowers()
{
System.out.println(mm.Name+"送你鲜花");
}
public void GiveChocolate()
{
System.out.println(mm.Name+"送你巧克力");
}
}
//被追求者
class SchooleGirl
{
private String name;
public String getName()
{return name;}
public setName(String value)
{name = value;}
}
//客户端代码
public class Program
{
public static void main(String[] args)
{
SchoolGirl jiaojiao = new SchoolGirl();
jiaojiao.setName("李娇娇");
Pursuit daili = new Pursuit(jiaojiao);
//把Pursuit(追求者)换成Proxy(代理),把卓佳怡换成戴利。使得这个礼物变成是戴利送的,忽略了Pursuit追求者。
daili.GiveDolls();
daili.GiveFlowers();
daili.GiveChocolate();
}
}
分析:
1.礼物是Pursuit(追求者)买的、Proxy(代理)将Pursuit(追求者)买的礼物送给SchoolGirl(被追求者)。
2.礼物实质上是Pursuit(追求者)送的。
3.Pursuit(追求者)和Proxy(代理)都有送礼物的行为。
综上所述:Pursuit(追求者)和Proxy(代理)应该实现相同的接口。
符合实际的代码结构图:
被追求者:
class SchoolGirl
{
private String name;
public String getName()
{return name;}
public setName(String value)
{name = value;}
}
送礼物接口:
interface IGiveGift
{
void GiveDolls();
void GiveFlowers();
void GiveChocolate();
}
追求者类:
class Pursuit implement IGiveGift//追求者实现送礼物接口
{
SchoolGirl mm;
public Pursuit(SchoolGirl mm)
{
this.mm = mm;
}
public void GiveDolls()
{
System.out.println(mm.Name + "送你洋娃娃");
}
public void GiveFlowers()
{
System.out.println(mm.Name+"送你鲜花");
}
public void GiveChocolate()
{
System.out.println(mm.Name+"送你巧克力");
}
}
代理类:
class Proxy implement IGiveGift//代理实现送礼物接口
{
pursuit gg;
public Proxy(SchoolGirl mm)
{
gg=new Pursuit(mm);
}
public void GiveDolls()
{
gg.GiveDolls();
}
public void GiveFlowers()
{
gg.GiveFlowers();
}
public void GiveChocolate()
{
gg.GiveChocolate();
}
}
客户端:
public class Program
{
public static void main(String[] args)
{
SchoolGirl jiaojiao = new SchoolGirl();
jiaojiao.setName("李娇娇");
Pursuit daili = new Pursuit(jiaojiao);
daili.GiveDolls();
daili.GiveFlowers();
daili.GiveChocolate();
}
}
代理模式:
● 代理模式(Proxy),为其它对象提供一种代理以控制(隔离,使用接口)对这个对象的访问。
代理模式结构图:
//Subject类,定义了RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy。
abstract class Subject
{
public abstract void Request();
}
//RealSubject类,定义Proxy所代表的真是实体
class RealSubject implement Subject
{
public override void Request()
{
System.out.println("真是的请求");
}
}
//Proxy类,保存一个真是实体的引用,使得代理可以访问实体,并提供一个与Subject的接口相同的接口,这样的代理可以用来替代实体。
class Proxy implement subject
{
RealSubject realSubject;//真是实体
public override void Request()
{
if(readSubject == null)
{realSubject = newRealSubject();}
realSubject.Request();
}
}
public class Program//客户端代码
{
public static void main(String[] args){
Proxy proxy = new Proxy();
proxy.Request();
}
}
要点总结:
● “增加一层间接层”是软件系统中对许多复杂问题的一种常见解决方式,在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的Proxy对象时解决这一问题的常用手段。
● 具体Proxy设计模式的实现方法、实现粒度都相差很大,有些可能对某个对象做细粒度的控制,如copy-on-write技术,有些可能对组件模块提供抽象代理层,在架构层次对对象做Proxy。
● Proxy并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时候损失一些透明性是可以接受的。
Proxy模式解说
● 在软件系统中,无时不在跨越障碍:
◇ 当访问网络上一台计算机的资源时,需要跨越网络障碍,
◇当访问服务器上数据库时,需要跨越数据库访问障碍,同时还有网络障碍。 跨越这些障碍有时候是非常复杂的,如果更多地去关注处理这些障碍,可能就会忽略了本来应该关注的业务逻辑问题,Proxy模式有助于去解决这些问题。