Java设计模式 - 代理模式

29 阅读2分钟

文章目录

1. 静态代理

  • 缺点:需要为每个被代理的对象创建一个代理类 – 代码太累赘

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gLCoEZ40-1576776415779)(en-resource://database/13840:1)]

// 代理人跟被代理者共同实现的接口
interface Buy {
	
	public void buy();
	
}

// 被代理者
class CarFactory implements Buy{
	
	@Override
	public void buy() {
		System.out.println("工厂汽车");
	}
	
}

// 代理者  --  隐藏了被代理者的方法实现
class CarFactoryProxy implements Buy{
	
	CarFactory cf = new CarFactory();
	
	@Override
	public void buy() {
		System.out.println("从代理人里买到");
		cf.buy();
	}
	
}

public class Test2 {
	
	public static void main(String[] args) {		
		CarFactoryProxy cfp = new CarFactoryProxy();
		cfp.buy();	
	}	
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JLnaNckW-1576776415792)(en-resource://database/13841:1)]

2. JDK内置的动态代理

缺点:被代理类必须有接口 - 动态代理是通过接口进行反射代理的


步骤:

  1. 代理对象:proxy.newProxyInstance( 类加载器ClassLoader, Class[]接口数组,调用处理者InvocationHandler )
  2. 实现InvocationHandler接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-us94oX5G-1576776415799)(en-resource://database/13842:1)]

// 代理者与被代理者的共同实现接口
interface Buy {
	
	public void buy();
	
}

// 被代理者
class CarFactory implements Buy{
	
	@Override
	public void buy() {
		System.out.println("工厂汽车");
	}
	
}

// 代理者的函数处理
class ProxyInvocationHandler implements InvocationHandler {
	
	// 用来保存被代理的对象
	Object surrogateObj;
	
	ProxyInvocationHandler(Object surrogateObj) { this.surrogateObj = surrogateObj; }
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		System.out.print("从代理人里买到");
		if(method.getName() == "buy") {
			((Buy)surrogateObj).buy();
		}
		
		return null;
	}
	
}

// 测试类
public class Test2 {
	
	public static void main(String[] args) {
		
		// 被代理的对象
		CarFactory cf = new CarFactory();
		
		// 生成JDK代理类需要的信息
		ClassLoader loader = Test2.class.getClassLoader();
		Class<?>[] interfaces = CarFactory.class.getInterfaces();
		InvocationHandler handler = new ProxyInvocationHandler(cf);
		Buy buy = (Buy) Proxy.newProxyInstance(loader, interfaces, handler );
		
		// 利用代理类来操纵被代理者的行为
		buy.buy();
		
	}
	
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DgLrk3oR-1576776415808)(en-resource://database/13843:1)]

3. Spring内置的CGLIB动态代理

注意 Enhancer、InvocationHandler都是Spring的类

步骤

  1. 创建Enhancer对象
  2. 设置其类加载器、以及需要代理的接口Class、以及实现Spring的InvocationHandler接口
  3. 通过Enhancer创建代理对象create()

// 需要被代理的汽车工厂类  ----- 注意这里没有接口
class CarFactory {
	public void buy() {
		System.out.println("工厂汽车");
	}
}

// 代理者方法处理类 -- 即被代理者的方法增强
class MyInvocationHandler2 implements InvocationHandler {
	
	Object proxied;
	
	public MyInvocationHandler2(Object proxied) {
		this.proxied = proxied;
	}
	
	@Override
	public Object invoke(Object var1, Method method, Object[] args) throws Throwable {
		
		System.out.print("从代理人里买到");
		Object result = method.invoke(proxied, args);
		
		return result;
	}
	
}


public class CGLIB动态代理2 {
			
	public static void main(String[] args) {
		
		// 1. 生成一个被代理的对象
		CarFactory cf = new CarFactory();
		
		// 2. 创建一个增强器
		Enhancer enhancer = new Enhancer();
		
		// 3. 设置需要被增强的接口、以及增强的方法处理
		enhancer.setClassLoader(CGLIB动态代理2.class.getClassLoader());
		enhancer.setSuperclass(CarFactory.class);
		enhancer.setCallback(new MyInvocationHandler2(cf));
		
		// 4. 创建一个基于CarFactory对象的代理对象
		CarFactory factoryproxier = (CarFactory) enhancer.create(); 
		
		// 5. 我们只能通过代理者来了解对象 - 即隐藏了代理者的具体实现、以及具有解耦作用
		factoryproxier.buy();
		
	}
	
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OkUFFTa1-1576776415811)(en-resource://database/13992:1)]


运行效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oFyNzH95-1576776415814)(en-resource://database/13994:1)]