代理模式

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能,这种类型属于结构性模式。
在代理模式中,创建现有对象的对象,以便向外界提供功能接口。

意图:

为其他对象提供一种以控制这个对象的访问。

主要解决:

在直接访问对象时带来的问题,比如说:要访问的对象在远程机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

如何使用:

想在访问一个类时做一些控制

如何解决:

增加中间层

关键代码:

实现与代理类的组合

应用实例:

1.windows快捷方式2.spring aop

优点:

1.职责清晰2.高扩展性3.智能化

缺点:

1.由于在客户端和真实性主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢2.实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

使用场景:

按职责来划分,通常有以下使用场景:
1.远程代理,2.虚拟代理3.Copy-on-Write代理4.保护(Protect or Access)代理5.Cache代理6.防火墙代理7.同步化代理8.只能引用代理

注意事项:

1.和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口2.和装饰器模式的区别:装饰器模式是为了增强功能,而代理模式是为了加以控制。
jdk动态代理,直接上代码
定义一个被代理类的接口,代理对象和被代理对象时兄弟关系

package com.jdkproxy.$interface;

public interface Subject {
	
    int sellBooks();
	
	String speak(); 

}

package com.jdkproxy.$interface.impl;

import com.jdkproxy.$interface.Subject;

public class RealSubject implements Subject{

	@Override
	public int sellBooks() {
		System.out.println("sell books");
		return 1;
	}

	@Override
	public String speak() {
		System.out.println("speak");
		return "zhangsan";
	}
	
	

}

package com.jdkproxy.handler;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import com.jdkproxy.$interface.Subject;

public class InvocationHandlerDemo implements InvocationHandler{
	
	//因为需要处理真是角色,需要传进来
	private Subject realSubject;

	public InvocationHandlerDemo(Subject realSubject) {
		this.realSubject = realSubject;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("proxy class");
		if(method.getName().equals("sellBooks")){
			int param = (int) method.invoke(realSubject,args);
			System.out.println("sell books");
			return param;
		}else if(method.getName().equals("speak")){
			String param2 = (String) method.invoke(realSubject,args);
			return param2;
		}
		return null;
	}
	
	

}

package com.jdkproxy.test;

import java.lang.reflect.Proxy;

import org.junit.Test;

import com.jdkproxy.$interface.Subject;
import com.jdkproxy.$interface.impl.RealSubject;
import com.jdkproxy.handler.InvocationHandlerDemo;

public class TestDemo {
	
	@Test
	public void test(){
		Subject subject = new RealSubject();
		InvocationHandlerDemo invocation = new InvocationHandlerDemo(subject);
		Subject proxy = (Subject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
				new Class[]{Subject.class},invocation);
			
		proxy.sellBooks();
		proxy.speak();
		
	}

}

Cglib 动态代理是针对代理的类, 动态生成一个子类, 然后子类覆盖代理类中的方法, 如果是private或是final类修饰的方法,则不会被重写。

CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。

CGLIB作为一个开源项目,其代码托管在github,地址为:https://github.com/cglib/cglib


public class Engineer {
	
	public void eat(){
		System.out.println("engineer is eatting");
	}
	
	public final void work(){
		System.out.println("engineer is working");
	}
	
	private void play(){
		System.out.println("enginner is playing");
	}

}

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{
	
	private Object obj;
	
	public CglibProxy(Object obj) {
		this.obj = obj;
	}

	@Override
	public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
		System.out.println("before invocation");
		Object result = arg1.invoke(obj,arg2);
		System.out.println("after invocation");
		return result;
	}
	
	public static Object getProxy(Object obj){
		Enhancer e = new Enhancer();
		e.setSuperclass(obj.getClass());
		e.setCallback(new CglibProxy(obj));
		return e.create();
	}
	
	

}

import org.junit.Test;

public class TestDemo1 {
	
	@Test
	public void test(){
		Engineer engineer = (Engineer) CglibProxy.getProxy(new Engineer());
		engineer.eat();
		engineer.work();
	}

}

before invocation
engineer is eatting
after invocation
engineer is working

你可能感兴趣的:(设计模式)