转载:https://www.cnblogs.com/jie-y/p/10732347.html
代理模式:
- 代理(proxy)是一种设计模式,提供了间接对目标对象进行访问的方式;即通过代理对象访问目标对象,这样做的好处是:可以在目标对象实现的功能上,增加额外的功能补充,即扩展目标对象的功能。
- 这就符合了设计模式的开闭原则,即在对既有代码不改动的情况下进行功能的扩展。
- ex:明星与经纪人之间就是代理和被代理的的关系,明星演出活动的时候,明星就是一个目标对象,他只要负责活动中的节目,而其它琐碎的事情由经纪人处理
静态代理:
在使用静态代理时,被代理对象与代理对象需要一起实现相同的接口或继承父类,因此要定义一个接口或抽象类
/**
* 被代理对象的实际行为抽象类
*/
public abstract class IStar {
public abstract void sing();
}
/**
* 被代理对象
*/
public class LDHStar extends IStar {
@Override
public void sing() {
System.out.println("开始唱歌");
}
}
/**
* 代理对象(中介)
*/
public class ProxyManager extends IStar {
private IStar iStar;
public ProxyManager(IStar iStar){
this.iStar = iStar;
}
@Override
public void sing() {
iStar.sing();
}
}
public class Test {
public static void main(String[] args) {
// IStar is = new LDHStar();
//
// ProxyManager proxyManager = new ProxyManager(is);
// proxyManager.sing();
BuyHouse bh = new HouseBussiness();
ProxyBussiness bussiness = new ProxyBussiness(bh);
bussiness.buy();
}
}
静态代理总结:
- 优点:可以做到不修改目标对象的功能的前提下,对目标功能扩展
- 缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类。同时,一旦接口增加方法,目标对象和代理对象都要维护
动态代理可以解决静态代理的缺点
动态代理:
动态代理的主要特点就是能够在程序运行时JVM才为被代理对象生成代理对象
常说的动态代理也叫做JDK代理也是一种接口代理,JDK中生成代理对象的代理类就是proxy,所在的包时java.lang.reflect
public interface IDog {
public abstract void run();
}
public class GunDog implements IDog {
@Override
public void run() {
System.out.println("跑");
}
}
public class MyInvocationHandle implements InvocationHandler {
private Object target;
public void setTarget(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
DogUtil.method1();
DogUtil.method2();
method.invoke(target,args);
return null;
}
}
/**
* 生产代理对象的工厂
*/
public class MyProxyFactory {
public static Object getProxy(Object target){
MyInvocationHandle handle = new MyInvocationHandle();
handle.setTarget(target);
Object instance = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handle);
return instance;
}
}
public class ProxyDemo {
public static void main(String[] args) {
IDog dog = new GunDog();
IDog proxy = (IDog)MyProxyFactory.getProxy(dog);
proxy.run();
}
}
总结:
- 代理对象不需要接口实现,但是目标对象一定要实现接口,否则不能动态代理,因此也算这种方式的缺陷。
cglib代理:
- 上面的静态代理和动态代理模式有个相同点就是都要求目标对象是实现一个接口的对象,然而并不是任何对象都会实现一个接口,也存在没有实现任何的接口的对象
- 这时就可以使用继承目标类以及目标对象子类的方式实现代理,这种方法就叫做:cglib代理,也叫做子类代理,他是在内存中构建一个子类对象,从而实现对目标对象功能的扩展。
- 使用JDK动态代理有一个限制就是被代理的对象必须实现一个或多个接口,若想代理没有实现接口的类,就需要使用cglib实现