使用反射增加装饰模式的普适性,动态代理实现装饰模式

本文介绍了使用Java动态代理实现装饰模式的方法,通过定义抽象构件、装饰类和装饰动作类,实现了对对象功能的动态扩展,提高了系统的灵活性和扩展性。以卡通片《猫和老鼠》中的角色Jerry为例,演示了如何为其增加飞行和钻地能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

装饰模式(Decorator Pattern)的定义是“动态地给一个对象添加一些额外的职责。就增 加功能来说,装饰模式相比于生成子类更为灵活”,不过,使用Java的动态代理也可以实现 装饰模式的效果,而且其灵活性、适应性都会更强。

我们以卡通片《猫和老鼠》(《Tom and Jerry》)为例,看看如何包装小Jerry让它更强 大。首先定义Jerry的类:老鼠(Rat类),代码如下;

public interface Animal {
  public void doStuff();
}

public class Rat implements Animal {

	@Override
	public void doStuff() {
		// TODO Auto-generated method stub
        System.out.println("Rat...doStuff()....");
	}

}


接下来我们要给Jerry增加一些能力,比如飞行、钻地等能力,当然使用类继承也很容 易实现,但我们这里只是临时地为Rat类增加这些能力,使用装饰模式更符合此处的场景。 首先定义装饰类,代码如下:

//定义某种能力
public interface Feature {
  //加载特性
  public void  load();
}
public class FlyFeature implements Feature {

	@Override
	public void load() {
		// TODO Auto-generated method stub
         System.out.println("增加了一只翅膀。。。。。。");
	}

}
public class DigFeature implements Feature {

	@Override
	public void load() {
		// TODO Auto-generated method stub
      System.out.println("增加了钻地能力。。。。");
	}

}

此处定义了两种能力:一种是飞行,另一种是钻地,我们如果把这两种属性陚予到Jerry身上,那就需要一个包装动作类了,代码如下:

public class DecorateAnimal implements Animal {

	//被包装的动物
	private Animal animal;
	
	//使用哪一个包装器
	private Class<? extends Feature> clz;
	
	public DecorateAnimal(Animal _animal, Class<? extends Feature> _clz){
		this.animal=_animal;
		this.clz=_clz;
	}
	

	@Override
	public void doStuff() {
		// TODO Auto-generated method stub
            InvocationHandler handler=new InvocationHandler() {
				
				@Override
				public Object invoke(Object proxy, Method method, Object[] args)
						throws Throwable {
					// TODO Auto-generated method stub
					Object object=null;
					//设置包装条件
					if(Modifier.isPublic(method.getModifiers())){
						object=method.invoke(clz.newInstance(), args);
					}
					
					animal.doStuff();
					return object;
				}
			};
			
			//当前加载器
			ClassLoader cl=getClass().getClassLoader();
			//动态代理,油Handler决定如何包装
			Feature proxy=(Feature) Proxy.newProxyInstance(cl, clz.getInterfaces(), handler);
	                proxy.load();
	}

}


注意看doStuff方法,一个装饰类型必然是抽象构建(Component)的子类型,它必 须要实现doStuff,此处的doStuff方法委托给了动态代理执行,并且在动态代理的控制器 Handler中还设置了决定装饰方式和行为的条件(即代码中InvocationHandler匿名类中的if 判断语句),当然,此处也可以通过读取持久化数据的方式进行判断,这样就更加灵活了。

抽象构件有了,装饰类也有了,装饰动作类也完成了,那我们就可以编写客户端进行调用了,代码如下:

public class Client {
public static void main(String[] args) {
	//定义Jerry这种家喻户晓的老鼠
	Animal animal =new Rat();
	//为Jerry增加飞行能力
	animal =new DecorateAnimal(animal, FlyFeature.class); //DecorateAnimal@5b202f4d    rat                       fly
	//为Jerry增加挖掘能力
   	animal =new DecorateAnimal(animal, DigFeature.class); //DecorateAnimal@3f68336     DecorateAnimal@5b202f4d   dig
	//Jerry开始耍毛
	 animal.doStuff();
  }
}
DecorateAnimal@3f68336.doStuff() ----->DecorateAnimal@5b202f4d.doStuff() -------> rat.doStuff() 


此类代码是一个比较通用的装饰模式,只需要定义被装饰的类及装饰类即可,装饰行为 由动态代理实现,实现了对装饰类和被装饰类的完全解耦,提供了系统的扩展性。


动态代理可以使代理模式更加灵活




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你是我的天晴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值