
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
装饰模式(Decorator Pattern)的定义是“动态的给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比于生成子类更为灵活”,不过,使用Java的动态代理也可以实现装饰模式的效果,而且其灵活性、适应性都会更强。
昆明达内培训的老师以卡通片《猫和老鼠》(Tom and Jerry)为例,看看如何包装小Jerry让它更强大。首先定义Jerry的类:老鼠(Rat类),代码如下:
interface Animal{
public void doStuff();
}
class Rat implements Animal{
@Override
public void doStuff() {
System.out.println("Jerry will play with Tom ......");
}
}
接下来,昆明达内培训的老师要给Jerry增加一些能力,比如飞行,钻地等能力,当然使用继承也很容易实现,但我们这里只是临时的为Rat类增加这些能力,使用装饰模式更符合此处的场景,首先定义装饰类,代码如下:
//定义某种能力
interface Feature{
//加载特性
public void load();
}
//飞行能力
class FlyFeature implements Feature{
@Override
public void load() {
System.out.println("增加一对翅膀...");
}
}
//钻地能力
class DigFeature implements Feature{
@Override
public void load() {
System.out.println("增加钻地能力...");
}
}
此处定义了两种能力:一种是飞行,另一种是钻地,我们如果把这两种属性赋予到Jerry身上,那就需要一个包装动作类了,代码如下:
class DecorateAnimal implements Animal {
//被包装的动物
private Animal animal;
//使用哪一个包装器
private Class<? extends Feature> clz;
public DecorateAnimal(Animal _animal, Class<? extends Feature> _clz) {
animal = _animal;
clz = _clz;
}
@Override
public void doStuff() {
InvocationHandler handler = new InvocationHandler() {
//具体包装行为
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object obj = null;
if (Modifier.isPublic(method.getModifiers())) {
obj = method.invoke(clz.newInstance(), args);
}
animal.doStuff();
return obj;
}
};
//当前加载器
ClassLoader cl = getClass().getClassLoader();
//动态代理,又handler决定如何包装
Feature proxy = (Feature) Proxy.newProxyInstance(cl, clz.getInterfaces(), handler);
proxy.load();
}
}
注意看doStuff方法,一个装饰类型必然是抽象构建(Component)的子类型,它必须实现doStuff方法,此处的doStuff方法委托给了动态代理执行,并且在动态代理的控制器Handler中还设置了决定装饰方式和行为的条件(即代码中InvocationHandler匿名类中的if判断语句),当然,此处也可以通过读取持久化数据的方式进行判断,这样就更加灵活了。
抽象构建有了,装饰类也有了,装饰动作类也完成了,那我们就可以编写客户端进行调用了,代码如下:
public static void main(String[] args) {
//定义Jerry这只老鼠
Animal jerry = new Rat();
//为Jerry增加飞行能力
jerry = new DecorateAnimal(jerry, FlyFeature.class);
//jerry增加挖掘能力
jerry = new DecorateAnimal(jerry, DigFeature.class);
//Jerry开始戏弄毛了
jerry.doStuff();
}
此类代码只一个比较通用的装饰模式,只需要定义被装饰的类及装饰类即可,装饰行为由动态代理实现,实现了对装饰类和被装饰类的完全解耦,提供了系统的扩展性。
了解详情请登陆昆明达内IT培训官网(km.tedu.cn)!