千淘万漉虽辛苦,吹尽黄沙始到金
一,定义
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
装饰模式也叫包装模式,结构型设计模式之一,其使用一种对客户端透明的方式来动态地扩展对象的功能,同时它也是继承关系的一种替代方案之一。
二,使用场景
需要透明且动态的扩展类的功能时。
装饰模式在代码中的应用非常广泛,我们在不经意间就会使用到类似的概念。比如:
public abstract class EtnApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
setRxJavaErrorHandler();
initApplication();
}
private void initApplication(){}
private void setRxJavaErrorHandler(){}
}
这里的setRxJavaErrorHandler 和initApplication 就是对onCreate方法的包装
三,角色介绍
1,Component:抽象组件
可以是一个接口或者抽象类,其充当的就是被装饰的原始对象
2,ConcreteComponent:组件具体实现类
该类是Component类的基本实现,也是我们装饰的具体对象
3,Decorator:抽象装饰者
其承担的职责就是为了装饰我们的组件对象,其内部一定要有一个指向组件对象的引用。在大多数情况下,该类为抽象类,需要根据不同的装饰逻辑实现不同的具体子类。当然,如果装饰逻辑单一,只有一个的情况下我们可以省略该类直接作为具体的装饰者
4,ConcreteDecorator:装饰者具体实现类
只是对抽象装饰者作出具体的实现
四,使用案例
在和平精英吃鸡手游这个游戏的玩家群体里,大部分人玩游戏都是自己一个人玩,有一部分人为了上分会花钱请一些技术陪玩一起玩,还有一部分人玩游戏不是为了上分,而是为了开心,他们会花钱请一些娱乐陪玩一起玩。
在这里,我们就可以将玩家定义为一个抽象类,将玩家玩游戏的行为定义为一个具体的方法,这就是上面提到的抽象组件:
public abstract class Player {
/**
* 玩游戏
* */
public abstract void playGame();
}
然后具体实现类就是具体到某个人,继承抽象组件:
public class YuanZhen extends Player{
@Override
public void playGame() {
System.out.println("玩吃鸡游戏");
}
}
然后创建一个抽象的装饰者类:
public abstract class PlayerAbsDecorator extends Player{
protected Player player;
public PlayerAbsDecorator(Player player) {
this.player = player;
}
@Override
public void playGame() {
player.playGame();
}
}
这个类是该模式的核心类,它持有了Player的引用,可以方便的调用具体被装饰对象中的方法,这也是为什么我们可以在不破坏原类层次结构的情况下为类增加一些功能,我们只需在被装饰对象的相应方法的前或后增加相应的功能逻辑即可。
最后创建我们的具体装饰者类,继承抽象装饰者类,实现技术陪玩和娱乐陪玩相关方法
public class TechnicalPlayer extends PlayerAbsDecorator{
public TechnicalPlayer(Player player) {
super(player);
}
public void eatChicken(){
System.out.println("吃鸡了");
}
@Override
public void playGame() {
super.playGame();
eatChicken();
}
}
public class EntertainmentPlayer extends PlayerAbsDecorator{
public EntertainmentPlayer(Player player) {
super(player);
}
private void happy(){
System.out.println("玩的开心");
}
@Override
public void playGame() {
super.playGame();
happy();
}
}
使用:
YuanZhen yuanzhen=new YuanZhen();
EntertainmentPlayer entertainmentPlayer =new EntertainmentPlayer(yuanzhen);
entertainmentPlayer.playGame();
TechnicalPlayer technicalPlayer =new TechnicalPlayer(yuanzhen);
technicalPlayer.playGame();
输出:
这样就实现了一个简单的装饰者模式。
五,总结
装饰者模式和代理模式Java 代理模式之静态代理与动态代理_java静态代理模式_袁震的博客-CSDN博客有点类似,有时容易混淆。
注意:装饰模式是以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,而代理模式则是给一个对象提供一个代理对象,并有代理对象来控制原有对象的引用。装饰模式应该为所装饰的对象增强功能,代理模式对代理的对象施加控制,但不对对象本身的功能进行增强。