概念
代理模式——就是给某一个对象提供一个代理,并由代理对象控制对原对象的引用。在一些情况下,一个客户不想或者不能直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。例如电脑桌面的快捷方式就是一个代理对象,快捷方式是它所引用的程序的一个代理。
代理模式的结构
- Subject(抽象主题角色):它声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题,客户端通常需要针对抽象主题角色进行编程。
- Proxy(代理主题角色):它包含了对真实主题的引用,从而可以在任何时候操作真实主题对象;在代理主题角色中提供一个与真实主题角色相同的接口,以便在任何时候都可以替代真实主题;代理主题角色还可以控制对真实主题的使用,负责在需要的时候创建和删除真实主题对象,并对真实主题对象的使用加以约束。通常,在代理主题角色中,客户端在调用所引用的真实主题操作之前或之后还需要执行其他操作,而不仅仅是单纯调用真实主题对象中的操作。
- RealSubject(真实主题角色):它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作。
代理模式和装饰模式的异同
- 代理模式和装饰模式的代码实现方式很相同,主要不同点是代理模式关注与被代理对象行为的控制,然而装饰模式关注于在一个对象上动态的添加方法。
- 代理模式可以对客户端隐藏被代理对象的具体实现,代理模式的时候常常是在一个代理类中创建一个对象的实例,当使用装饰模式的时候,将原始对象转为一个参数传递给装饰者的构造器中
- 代理模式强调的是限制,装饰模式强调的是增强
代理模式和委托
代理:是把一些事情交给某人帮忙去完成。
委托:是当某件事情发生的时候,顺便干某件事情。委托就相当于一个触发器罢了。
代理模式的应用场景
代理模式的类型较多,不同类型的代理模式有不同的优缺点,它们应用于不同的场合:
- 当客户端对象需要访问远程主机中的对象时可以使用远程代理。
- 当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时可以使用虚拟代理,例如一个对象需要很长时间才能完成加载时。
- 当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时可以使用缓冲代理。通过使用缓冲代理,系统无须在客户端每一次访问时都重新执行操作,只需直接从临时缓冲区获取操作结果即可。
- 当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时可以使用保护代理。
- 当需要为一个对象的访问(引用)提供一些额外的操作时可以使用智能引用代理。
代理模式的优缺点
优点:
- 能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
- 客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原则,系统具有较好的灵活性和可扩展性。
缺点:
- 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,例如保护代理。
- 实现代理模式需要额外的工作,而且有些代理模式的实现过程较为复杂,例如远程代理。
代理模式的实现
新建一个买车的接口
public interface buy_car {
public void buy_mycar();
}
新建一个people人类,具有买车的行为,所以实现接口buy_car
class people implements buy_car {
private int cash;
private String vip;
private String username;
@Override
public void buy_mycar() {
// TODO Auto-generated method stub
System.out.print(username+"是vip 客户,可以直接购买新车!");
}
public int getCash(){
return cash;
}
public void setCash(int cash){
this.cash = cash;
}
public String getUsername(){
return username;
}
public void setUsername(String username){
this.username = username;
}
public String getVip(){
return vip;
}
public void setVip(String vip){
this.vip = vip;
}
}
people类不能拥有车,必须经过proxy代理类的认证,符合条件之后才可以拥有车辆,新建一个代理,这个代理类来考察当前的people是否有资格进行买车:
class proxyclass implements buy_car {
private people people;
public people getPeople(){
return people;
}
public void setPeople(people people){
this.people = people;
}
@Override
public void buy_mycar() {
// TODO Auto-generated method stub
if (people.getVip() == "vip"){
people.buy_mycar();
return ;
}
if(people.getCash()>=50000){
System.out.println(people.getUsername()+"买了新车,交易结束!");
}
else
{
System.out.println(people.getUsername()+"钱不够,不能买车,继续比赛!");
}
}
}
最后创建一个客户端,用来模拟买车的行为:
public class run_main {
public static void main(String[] args) {
// TODO Auto-generated method stub
people people_1 =new people();
people_1.setCash(60000);
people_1.setUsername("jeck");
people people_2 =new people();
people_2.setCash(40000);
people_2.setUsername("rose");
people people_3 =new people();
people_3.setCash(0);
people_3.setUsername("tom");
people_3.setVip("vip");
proxyclass proxy_buy = new proxyclass();
proxy_buy.setPeople(people_1);
proxy_buy.buy_mycar();
proxy_buy.setPeople(people_2);
proxy_buy.buy_mycar();
proxy_buy.setPeople(people_3);
proxy_buy.buy_mycar();
}
}