设计模式 — Facade外观模式

出现的背景:client端需要调用多个子模块实现某个功能,就需要有一个外观类来实现客户端对内部子模块api的解耦,因为其实客户端关注的只是需要实现某个功能,如果没有facasd类,那么相当于客户端需要知道moduleA提供了a零件,moduleB提供了b零件。。然后客户端要了解哪些module是自己这个功能需要的,还要自己组合才能得到想要的功能,而且一旦某几个module方法比如调用顺序发生改变,或者需要新的module方法实现一个新的细节,那么客户端也需要修改。

实现:

facade_1

 

facade_2

 

public class Facade {
	/**
	 * 示意方法,满足客户需要的功能
	 */
	public void test(){
		//在内部实现的时候,可能会调用到内部的多个模块
		AModuleApi a = new AModuleImpl();
		a.testA();
		BModuleApi b = new BModuleImpl();
		b.testB();
		CModuleApi c = new CModuleImpl();
		c.testC();
	}
}

public class Client {
	public static void main(String[] args) {
//		//不用Facade,需要自己跟多个模块交互
//		AModuleApi a = new AModuleImpl();
//		a.testA();
//		BModuleApi b = new BModuleImpl();
//		b.testB();
//		CModuleApi c = new CModuleImpl();
//		c.testC();
//		
//		System.out.println("使用Facade----------------------〉");
		//使用了Facade
		new Facade().test();		
	}
}

这样client只需要调用facade里面的方法就可以得到想要的功能而根本不需要知道具体由哪几个module来共同完成了这个功能

Facade加强版:

facade_3

 

这种模式是facade实现类同时被内部和外部调用,需要被外部调用的方法才封装成接口,这样能够屏蔽内部才调用的方法,使这些方法不会暴露到客户端,为了面向接口,不将内部的facade实现类暴露出去,所以还需要一个工厂来得到引起具体facade实例的facade接口对象。

Facade注意事项:

  • 有Facade类,但是客户端不是必须使用,客户端也可以直接使用具体的模块
  • Facade类只是对不同模块方法的封装,不需要自己去实现新的功能

设计模式 利用CGLib实现Proxy模式

JDK中带来的Proxy类来动态创建Proxy的时候必须要实现接口,否则无法使用,如果业务bean没有实现接口的情况可以用第三方的CGLib来创建Proxy类

public class CGLibProxyFactory implements MethodInterceptor {
	private Object target;
	
	public Object createProxyInstance(Object obj){
		this.target = obj;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(this.target.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
	}

	@Override
	public Object intercept(Object proxy, Method method, Object[] args,
			MethodProxy methodProxy) throws Throwable {
		Users user = new Users();
		if(user.getName() != null && !"".equals(user.getName())){
			return methodProxy.invoke(target, args);
		}else{
			return null;
		}
	}
}

@Test
	public void enhanceTest(){
		PersonServiceImpl personService = new PersonServiceImpl();
		CGLibProxyFactory factory = new CGLibProxyFactory();
		PersonServiceImpl service = (PersonServiceImpl)factory.createProxyInstance(personService);
		service.save();
	}

enhancer.setSuperclass(this.target.getClass()) — 表示enhancer会为原业务bean创建一个子类,当业务bean的方法被调用时,MethodInterceptor的intercept会被调用。

设计模式 利用Proxy模式实现权限过滤思想

public class ProxyFactory implements InvocationHandler {
	private Object target;
	
	public Object createProxyInstance(Object obj){
		this.target = obj;
		return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Users user = new Users();
		if(user.getName() != null && !"".equals(user.getName())){
			return method.invoke(target, args);
		}else{
			return null;
		}
	}
	
}

动态Proxy最关键的就是Proxy和InvocationHandler类,Proxy.newProxyInstance方法动态的创建原target类的代理对象,然后用这个代理对象调用原类的方法时,会触发InvocatioinHandler的invoke方法,然后可以在这个方法里面写入过滤的逻辑,然后通过method的反射api真正的调用原api的方法。
@Test
	public void test() {
		PersonServiceImpl personService = new PersonServiceImpl();
		ProxyFactory factory  = new ProxyFactory();
		IPersonService service = (IPersonService)factory.createProxyInstance(personService);
		service.save();
	}

Proxy代理模式的介绍博客:Proxy原博客