代理模式
代理模式:在代理模式中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
再代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
介绍
意图:为其他对象提供一种代理以控制这个对象的访问。
主要解决:在直接访问对象带来的问题,比如说:要访问的对象在远程机器上。在面向对象系统中,有些对象由于某些原因(比如对象的创建开销很大,或者默写操作需要安全控制,或者需要远程的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以访问此对象时加上一个对此对象的访问层。
何时使用:想在访问一个类时做一些控制。
如何解决:增加中间层。
关键代码:实现与代理类组合(下文例子中)。
应用实例: 1、Windows 里面的快捷方式。
2、相比于中介,买家找房子,闲麻烦,找个委托中介找房
3、买火车票不一定在火车站买,也可以去代售点。
4、一张支票或银行存单是账户中资金的代理。支票在市场交易中来代替现金,并提供对签发人账号上资金的控制。
5、Spring Aop(重点)。
优点: 1、职责清晰。
2、高扩展性。
3、智能化。
缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
使用场景:
按职责来划分,通常有以下场景:
1、远程代理。
2、虚拟化代理。
3、Copy-on-Write 代理。
4、保护(Protect or Access)代理。
5、Cache 代理。
6、防火墙(Firewall)代理。
7、同步化(Synchroniztion)代理 。
8、智能引用代理。
注意事项: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
代码实例:代理模式 分为动态代理和静态代理,我们在开发中使用动态代理,因为动态两个字听起来牛逼!
静态代理:类结构
/**
* @author xxx-001.
* @date 2018/9/3.
* @time 8:47.
* @Description 抽象接口
*/
public interface Demo {
/**
* @Author: xxx
* @Date: 8:48
* @Param: No such property: code for class: Script1
* @return:
* @Description:增加
*/
void add();
/**
* @Author: xxx
* @Date: 8:48
* @Param: No such property: code for class: Script1
* @return:
* @Description:删除
*/
void delete();
/**
* @Author: xxx
* @Date: 8:48
* @Param: No such property: code for class: Script1
* @return:
* @Description:修改
*/
void update();
/**
* @Author: xxx
* @Date: 8:49
* @Param: No such property: code for class: Script1
* @return:
* @Description:查询
*/
void select();
}
/**
* @author xxx-001.
* @date 2018/9/3.
* @time 8:44.
* @Description 委托类
*/
public class EntrustDemo implements Demo {
@Override
public void add() {
System.out.println("添加");
}
@Override
public void delete() {
System.out.println("删除");
}
@Override
public void update() {
System.out.println("修改");
}
@Override
public void select() {
System.out.println("查询");
}
}
/**
* @author xxx-001.
* @date 2018/9/3.
* @time 8:46.
* @Description 代理类
*/
public class ProxyDemo implements Demo {
/**
* 委托对象
*/
private EntrustDemo entrustDemo;
/**
* 构造函数
*
* @param entrustDemo
*/
public ProxyDemo(EntrustDemo entrustDemo) {
this.entrustDemo = entrustDemo;
}
/**
* 代理类处理
*/
@Override
public void add() {
System.out.println("代理添加");
}
@Override
public void delete() {
System.out.println("代理删除");
}
/**
* 引用委托处理
*/
@Override
public void update() {
entrustDemo.update();
}
@Override
public void select() {
entrustDemo.select();
}
}
/**
* @author xxx-001.
* @date 2018/9/3.
* @time 8:49.
* @Description 测试类
*/
public class TestDemo {
public static void main(String[] args) {
//委托对象
EntrustDemo entrustDemo = new EntrustDemo();
//使用静态代理对象
ProxyDemo proxyDemo = new ProxyDemo(entrustDemo);
//通过代理对象实现对委托类的调用
proxyDemo.add();
proxyDemo.delete();
proxyDemo.update();
proxyDemo.select();
}
}
动态代理:
Demo类代码和EntrustDemo代码同上
/**
* @author xxx-001.
* @date 2018/9/3.
* @time 8:46.
* @Description 代理类
*/
public class ProxyHandlerDemo implements InvocationHandler {
/**
* 委托对象
*/
private EntrustDemo entrustDemo;
/**
* 构造方法
*
* @param entrustDemo
*/
public ProxyHandlerDemo(EntrustDemo entrustDemo) {
this.entrustDemo = entrustDemo;
}
/**
* invoke的三个参数、第一个参数就是代理者,如果你想对代理者做一些操作可以使用这个参数;第二个就是被执行的方法,第三个是执行该方法所需的参数。
* 当你执行代理者的某个方法的时候,最后跑的都是invoke方法。
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("你好,开始");
if (method.getName().equals("add")) {
method.invoke(entrustDemo, args);
}
if (method.getName().equals("delete")) {
method.invoke(entrustDemo, args);
}
if (method.getName().equals("update")) {
method.invoke(entrustDemo, args);
}
if (method.getName().equals("select")) {
method.invoke(entrustDemo, args);
}
System.out.println("谢谢,再见");
return null;
}
}
/**
* @author xxx-001.
* @date 2018/9/3.
* @time 8:49.
* @Description 测试类
*/
public class TestDemo {
public static void main(String[] args) {
//委托对象
EntrustDemo entrustDemo = new EntrustDemo();
//使用JDK自带的实现代理接口
InvocationHandler handler = new ProxyHandlerDemo(entrustDemo);
//通过Proxy的newProxyInstance方法来创建我们的代理对象
Demo demo = (Demo) Proxy.newProxyInstance(handler.getClass().getClassLoader(), entrustDemo.getClass().getInterfaces(), handler);
//通过代理对象实现对委托类的调用
demo.add();
demo.delete();
demo.select();
demo.update();
}
}