学习笔记----设计模式之动态代理+工厂模式的混合使用简单demo

本文介绍了代理模式的应用,特别是不修改原始实现类代码的情况下扩展功能,如添加权限验证。代理分为静态代理和动态代理。静态代理需要为每个被代理类创建单独的代理类,而动态代理则更为灵活。文章提供了静态代理的简单示例,包括接口定义、代理类实现和测试代码。

最近项目有个需求,要用到动态代理调用远程接口,本地不实现接口,然后就学习了一下该设计模式并记录下来。

我自己的理解。

代理:不提供对对象的直接引用,通过代理的方式对目标对象进行调用。我认为,目前最大的用处在于不改变原有实现类的源代码的情况下,扩展类,增加需求。比如,我的需求是这样的,我要增加对某个类的访问权限,而这个访问权限是针对某些类限定的,那么我就不能去直接更改这个目标类的源代码,因为一旦我再目标类里修改了源代码,那就意味着 所有访问此类的都要经过此权限校验,这与需求不符。那么我就可以使用代理,在需要调用此目标类的调用出使用代理类,在代理类中增加我们的权限验证,这样就需要修改原目标类的代码,又实现了功能。这只是我简单列举的其中一个例子,还有很多应用场景,比如 添加日志 等等

代理又分静态代理和动态代理

静态代理:针对每个需要被代理的类写一个代理类。缺点是:代理类和被代理类都要实现同一个接口或抽象类,并且,如果需要代理的类有很多的话,那么就需要写很多的代理类,因此,动态代理应运而生。

一、静态代理简单demo

1.公共接口(抽象类也行)

public interface UserService {

	String getName(int id);
	
	Integer getAge(int id);
}
2.实现类

public class UserServiceImpl implements UserService{

	@Override
	public String getName(int id) {
		System.out.println("------getName-----");
		return "我的name";
	}

	@Override
	public Integer getAge(int id) {
		System.out.println("---------getAge----------");
		return 25;
	}

}
3.代理类

public class UserServiceProxy implements UserService {

	//目标类的引用
	private UserService userService ;
	
	public UserServiceProxy() {
		this.userService = new UserServiceImpl();
	}
	
	public UserServiceProxy(UserService userService){
		this.userService = userService;
	}

	@Override
	public String doSometing(int id) {
		
		//在调用目标类目标方法之前做一些其他操作,比如增加日志,权限什么的
		
		//调用目标类的同一方法
		String result = userService.doSometing(id);
		
		//目标方法调用完成后做一些其他的操作,比如数据过滤,追加日志等
		
		
		return result;
	}
}
4.测试

public static void main(String[] args) {
//      UserService userService = new UserServiceProxy();
	UserService userService = new UserServiceProxy(new UserServiceImpl());
	userService.doSometing(111);
}


5.结果

-------------------dosometing----------------:111
二、动态代理简单demo
动态代理 ,代理类要实现invocationHandler接口,实现invoke方法即可,此方法是调用被代理类实际执行的方法

1.接口

public interface UserService {

	String doSometing(int id);
	
	String doSometing2(String name);
	
}
2.实现类

public class UserServiceImpl implements UserService{

	@Override
	public String doSometing(int id) {
		System.out.println("-------------------dosometing----------------:" + id);
		return String.valueOf(id);
	}

	@Override
	public String doSometing2(String name) {
		System.out.println("------------dosometing2-------------:" + name);
		return name;
	}

}

3.代理类

public class UserServiceHandler implements InvocationHandler {

	//目标类的引用
	private Object target ;
	
	public UserServiceHandler(Object target) {
		this.target = target;
	}
	

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		//调用目标方法前做一些额外操作,比如日志,权限
		
		//由于调用被代理的类的所有方法时都会进入到此方法中,所以,如果由于业务的需要,并不是所有方法都进行某些操作,那么也可以再次做判断
		//比如,根据方法名判断  if(method.getName().equals("doSometing2")){做处理}
		
		//调用被代理类的方法
		Object result = method.invoke(target, args);
		
		//调用完后做其他的处理,比如数据过滤啥的
		return result;
	}
}

4.测试

public static void main(String[] args) {
		UserService userService = new UserServiceImpl();
		InvocationHandler h = new UserServiceHandler(userService);
		UserService userService2 = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), h);
		userService2.doSometing2("haha");
		userService2.doSometing(22);
}

5.结果

------------dosometing2-------------:haha
-------------------dosometing----------------:22
三、需求,不提供本地实现,只提供接口,用动态代理,使用httpclient远程调用

其实还是上面动态代理的升级版,只需要在调用出做一些修改即可。

1.接口

public interface UserService {

	String doSometing(int id);
	
	String doSometing2(String name);
	
}

2.代理类

public class UserServiceHandler implements InvocationHandler {

	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		//调用目标方法前做一些额外操作,比如日志,权限
		//由于没有实现类,所以不能调用metho.invoke方法,可以根据方法名做区分来判断具体执行的内容
		Object result = null;
		
		if(method.getName().equals("目标方法")){
			//自己封装的httpclient的工具类
			result = httpClientUtil.sendHttpPost(args);
		}else{
			//其他的。。。。。。。。。。
		}
		
		//调用完后做其他的处理,比如数据过滤啥的
		return result;
	}
}
3.工厂类 (这是我加了工厂,可用可不用)

public class ProxyBeanFactory {

	@SuppressWarnings("unchecked")
	public <T> T getProxy(Class<T> clazz) {
		InvocationHandler handler = new UserServiceHandler();
		return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, handler);

	}

}

4.测试

	public static void main(String[] args) {
		
		UserService proxy = (UserService) ProxyBeanFactory.getProxy(UserService.class);
		proxy.doSometing2("haha");
	}


基本的实现是这样的。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值