还是先举栗:
张三家有一个女孩待嫁,她的任务很明显,化妆、穿婚纱嫁人。类的实现如下:
public class girl {
public void Marry()
{
System.out.print("make-up and wedding-dress,then marry.");
}
}
使用场景也很简单:
public class client {
public static void main(String[] args) {
girl beautifulGirl = new girl();
beautifulGirl.Marry();
}
}
好了,女孩终于嫁出去了。
这种嫁闺女的情况只会在一个前提下发生:张三傻了。正常的情况下必须先执行一些控制操作才能执行girl的嫁人操作,比如,要实地考察男方是不是未婚、是不是有车、房、正常的工作等等。
这些额外的操作显然不能放到girl类里,因为这些额外的操作有的时候和主体功能(嫁人)一点关系都没有,并且这些额外的操作随时有可能变化,那怎么办?放到应用场景里呗:
public class client {
public static void main(String[] args) {
girl beautifulGirl = new girl();
boolean bHasBike = false,bHasHouse = false;
//some more judge
bHasBike = true;
bHasHouse = true;
if(bHasBike && bHasHouse)
{
beautifulGirl.Marry();
}
}
}
但是这样就加大了应用场景和gril类之间的耦合,根据开放-封闭原则,将变化的地方(各种约束)进行封装,就出来了代理模式,对于上面的例子来说,张三作为父母,就是闺女的代理,父母先做判断,是否可以嫁人,嫁人的时间等。然后再让闺女执行嫁人操作。
代理模式:为一个对象提供一种代理以控制对这个对象的访问。
特征:
一、控制,控制即是目的,这是它与装饰模式的主要区别,根据开闭原则,装饰模式使用场景中,变化点在于N个随着使用场景变化而组合变化的附加功能,所以装饰模式封装的是这些附加功能从而可以动态的为对象附加额外的功能职责,而代理模式使用场景中,变化的点在于N个针对指定对象的可变的约束。所以代理模式封装的是这些约束或条件内容从而可以控制client对这个对象的访问。
实现:
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
我们来看一下上面的例子如何使用代理模式实现
//抽象角色
public abstract class girl{
public abstract void Marry();
}
//真实角色
public class beautifulGirl extends girl {
public void Marry()
{
System.out.print("make-up and wedding-dress,then marry.");
}
}
//代理角色
public class Proxy extends girl {
private girl zhangsangirl = new beautifulGirl();
@Override
public void Marry()
{
if (Condition()) {
zhangsangirl.Marry();
}
}
public boolean Condition()
{
//judge the house/money/work
return true;
}
}
//应用场景
public class client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
girl myGirl = null;
myGirl = new Proxy();
myGirl.Marry();
}
}
这样,一些附加的与真实功能关联不大的判断或约束就单独封装了,根据不同的场景选择是直接使用真实功能,还是选择代理模式使用真实功能。当然代理也可以嵌套,即动态代理,原理是使用java语言的映射功能。可以参考:https://www.cnblogs.com/meet/p/5116464.html
代理模式实现了功能实现和约束的分离,使客户端可以根据不同的场景选择使用不同的约束方式。