代理模式
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
优点: 1、职责清晰。 2、高扩展性。 3、智能化。
缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。
注意事项: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
实例:
1.静态代理
提供一个公共接口,目标对象跟代理对象都必须实现这个接口
public interface IUserDao {
void eat();
}
目标对象
public class UserDao implements IUserDao {
@Override
public void eat() {
Log.e("android","Hello kitty");
}
}
代理对象
public class ProxyDao implements IUserDao {
private UserDao userDao;
public ProxyDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void eat() {
Log.e("android","Hello 代理");
userDao.eat();
Log.e("android","Hello 代理");
}
}
测试
// 目标对象
UserDao userDao = new UserDao();
// 代理对象
ProxyDao proxyDao = new ProxyDao(userDao);
// 执行代理方法
proxyDao.eat();
2.动态代理(jdk代理)
在动态代理中,代理对象不需要实现公共接口,而是利用JDK的API,动态的在内存中构建代理对象
public class ProxyFactory {
//维护一个目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getInstance(){
return Proxy.newProxyInstance(
//指定当前目标对象使用类加载器,获取加载器的方法是固定的
target.getClass().getClassLoader(),
//目标对象实现的接口的类型,使用泛型方式确认类型
target.getClass().getInterfaces(),
//事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.e("android","动态 代理");
//执行目标方法
Object invoke = method.invoke(target, args);
Log.e("android","动态 代理");
return invoke;
}
}
);
}
}
测试
//目标对象
IUserDao userDao = new UserDao();
IUserDao proxyDao = (IUserDao) new ProxyFactory(userDao).getInstance();
//执行代理方法
proxyDao.eat();
其实还有第三种代理cglib,不过因为不能直接在android中使用,所以暂时不讨论