一、定义:
为其他对象提供一种代理以控制对这个对象的访问,在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。一个类代表另一个类的功能,这种类型的设计模式属于结构型模式。
二、结构
三、实现
代理模式分为:静态代理模式、动态代理模式
1、静态代理模式
//创建服务类接口
public interface BuyHouse {
void buyHouse();
}
//实现服务类接口,中介
public class 中介 implements BuyHouse{
private BuyHouse bh;
中介(BuyHouse bh){
this.bh = bh;
}
public void buyHouse() {
System.out.println("你好,我是中介!你要买房吗?");
bh.buyHouse();
System.out.println("购房成功!");
}
}
实现服务类接口,顾客
public class Customer implements BuyHouse{
public void buyHouse() {
System.out.println("我要买房子!");
}
}
测试
public class Test {
public static void main(String[] args) {
BuyHouse cu = new Customer();
中介 zj= new 中介(cu);
zj.buyHouse();
}
}
优缺点
优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展
缺点:我们得为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。
2、动态代理模式
创建服务类接口
//创建买车服务接口
public interface BuyCar {
void buyCar();
}
//创建买房服务接口
public interface BuyHouse {
void buyHouse();
}
编写动态处理器
//代理对象Proxy
public class ProxyDemo implements InvocationHandler {
//实现InvocationHandler接口中的方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("toString".equals(method.getName())){
return proxy.getClass().getName();
}else if("buyHouse".equals(method.getName())){
System.out.println("我是中介,为您提供买房服务!");
return proxy;
}else if("buyCar".equals(method.getName())){
System.out.println("我是中介,为您提供买车服务");
return proxy;
}
return null;
}
public static <M> M getInstance(Class<M> c){
//得到类加载器的对象
ClassLoader loader = ProxyDemo.class.getClassLoader();
Class [] classes = {c};
//得到当前类的对象
ProxyDemo my = new ProxyDemo();
//得到代理对象
Object obj = Proxy.newProxyInstance(loader,classes,my);
return (M)obj;
}
}
顾客类
public class Client {
public static void main(String[] args) {
//顾客选择买房服务
BuyHouse house = ProxyDemo.getInstance(BuyHouse.class);
house.buyHouse();
}
}
虽然相对于静态代理,动态代理大大减少了我们开发任务,同时减少了对业务接口的依赖,降低了耦合度。但还是一点点小遗憾,它始终无法摆脱仅支持interface代理。Java 的继承机制注定了这些动态代理类们无法实现对 class 的动态代 理,原因是多继承在 Java 中本质上就行不通。有很多条理由,人们 可以否定对class代理的必要性,但是同样有一些理由,相信支持class 动态代理会更美好。 接口和类的划分本就不是很明显,只是到了 Java 中才变得如此的细 化。如果只从方法的声明及是否被定义来考量,有一种两者的混合 体,它的名字叫抽象类。实现对抽象类的动态代理,相信也有其内 在的价值。
优缺点:
优点:
(1)职责清晰
(2)高扩展性
(3)智能化
缺点:
(1)由于在客户端和真实主体之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢
(2)实现代理模式需要额外的工作,有些代理模式的实现非常复杂
四、适应场景
1、远程代理
2、虚拟代理
3、Copy-on-Write 代理
4、保护(Protect or Access)代理
5、Cache 代理
6、防火墙(Firewall)代理
7、同步化(Synchronization)代理
8、智能引用(Smart Reference)代理
五、应用
通过代码实现买火车票不一定在火车站买,也可以去代售点购买
//服务类接口
public interface BuyTrainTicket {
void buyTrainTicket();
}
//代理
public class ProxyDemo implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("buyTrainTicket".equals(method.getName())){
System.out.println("你好,这里是火车票代购点!");
System.out.println("你需要去哪里的票?");
return proxy;
}else if("toString".equals(method.getName())){
return proxy.getClass().getName();
}
return null;
}
public static <T> T getInstance(Class<T> c){
//得到类的加载器的对象
ClassLoader loader = ProxyDemo.class.getClassLoader();
Class [] classes = {c};
//得到当前类的对象
ProxyDemo proxyDemo = new ProxyDemo();
//得到代理对象
Object obj = Proxy.newProxyInstance(loader,classes,proxyDemo);
return (T)obj;
}
}
//顾客
public class Client {
public static void main(String[] args) {
BuyTrainTicket buyTrainTicket = ProxyDemo.getInstance(BuyTrainTicket.class);
buyTrainTicket.buyTrainTicket();
}
}