代理模式(Proxy)
为其他对象提供一种代理以控制这个对象的访问。
在GoF23种设计模式中,属于结构型模式( Structural patterns)
。
生活中有很多代理,比如说经济人,经销商,房产中间等等。为什么会出现这种职业呢?
明星总不能凡事都亲力亲为,通过经纪人可以减轻自身在商务、关系处理等等方面的事务。
厂家可以通过经销商获取到更广的客源,更容易把自身的产品推销出去。
房产中介作为房东的代理,可以帮房东分担出租、销售上的压力。
代理模式本质与上述情形一样,其实就是作为中间商,为代理对象赋能,增强代理对象能力。同时也会对代理对象进行保护,可以控制代理对象的访问权限。
- 优点
- 保护代理对象
- 降低系统耦合
- 增强代理对象
- 缺点
- 增加了系统的复杂度
- 可能降低了系统响应速度
- 使用场景
- 远程代理(VPN)
- 保护代理(Proxy网络代理)
- 业务上,可以使用静态代理or动态代理从而增加目标功能 (AOP)
实例
角色说明
- Subject
- 代理类与被代理类的统一接口,使得在任何RealSubject处,都可以使用代理类。
- Proxy
- 代理类,增强目标能力
- RealSubject
- 被代理对象
- Client
- 使用者
举例
在java代码里,代理通常有静态代理和动态代理两种形式。
静态代理
角色说明
- Star(Subject)
- 明星接口
- Agent(Proxy)
- 经纪人
- Ordin(RealSubject)
- 大明星
- Client
- 商家
代码详情
- Star.java
public interface Star {
void show();
}
- Ordin.java
public class Ordin implements Star{
@Override
public void show() {
System.out.println("super star ordin's showTime!!! ");
}
}
- Agent.java
public class Agent implements Star{
private Ordin ordin;
public Agent(Ordin ordin) {
this.ordin = ordin;
}
@Override
public void show() {
beforeShow();
ordin.show();
afterShow();
}
private void beforeShow(){
System.out.println("商谈演出计划,粉丝应援...");
}
private void afterShow(){
System.out.println("结账分红...");
}
}
- Client.java
public class Client {
public static void main(String[] args) {
Ordin ordin = new Ordin();
System.out.println("==不使用经纪人==");
ordin.show();
System.out.println("\n==使用经纪人后==");
Agent agent = new Agent(ordin);
agent.show();
}
}
- output
==不使用经纪人==
super star ordin's showTime!!!
==使用经纪人后==
商谈演出计划,粉丝应援...
super star ordin's showTime!!!
结账分红...
使用静态代理我们明显可以看到明星的能力得到了增强。但是这样编码对于系统拓展极不灵活,如果经纪人同时作为另一个明星的代理,这边还需要更改原有对象,违反开闭原则。
如果想要动态的更换代理对象,Java中可以使用jdk动态代理和Cglib动态代理实现。
jdk动态代理和Cglib动态代理比较
- jdk动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。因此使用Cglib时,需要特别注意final类的代理。
- jdk是直接写Class字节码,Cglib使用ASM框架写Class字节码,相比之下jdk生成代理类效率更好一些。
- jdk底层是通过反射机制调用代理方法,而Cglib是通过FastClass机制(生成代理和被代理类,通过index直接调用,避免反射调用)调用方法,Cglib执行效率更高。
动态代理
- Star.java
public interface Star {
void show();
}
- Ordin.java
public class Ordin implements Star{
@Override
public void show() {
System.out.println("super star ordin's showTime!!! ");
}
}
- OrdinT.java
public class OrdinT implements Star {
@Override
public void show() {
System.out.println("super star ordinT's showTime!!! ");
}
}
- Agent.java
public class Agent implements InvocationHandler {
private Star star;
public Agent(Star star) {
this.star = star;
}
public Object getProxy() {
Class cls = star.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this);
}
private void beforeShow() {
System.out.println("商谈演出计划,粉丝应援...");
}
private void afterShow() {
System.out.println("结账分红...");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeShow();
Object object = method.invoke(star, args);
afterShow();
return object;
}
}
- Client.java
public class Client {
public static void main(String[] args) {
System.out.println("==代理Ordin==");
Ordin ordin = new Ordin();
Star ordinProxy = (Star)new Agent(ordin).getProxy();
ordinProxy.show();
System.out.println("\n==动态代理OrdinT==");
OrdinT ordinT = new OrdinT();
Star ordinTProxy = (Star)new Agent(ordinT).getProxy();
ordinTProxy.show();
}
}
- output
==代理Ordin==
商谈演出计划,粉丝应援...
super star ordin's showTime!!!
结账分红...
==动态代理OrdinT==
商谈演出计划,粉丝应援...
super star ordinT's showTime!!!
结账分红...
实例
- AOP实现
总结
代理模式可以增强目标对象和保护目标对象。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名,转载请标明出处
最后编辑时间为: