装饰模式(Decorator Pattern),指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
在RxJava中,创建一个Observable有create、from、just等方式,这些动作也称为创建操作符,假设现在要给每个Observable添加转换(map)、合并(merge)以及分组(groupBy)等功能,那么就需要为每个创建操作符创建3个不同子类,总共9个子类。如果再添加别的操作,就会产生等多的子类,造成子类爆炸的局面,这种设计方式是不可行的。
Decorator模式的目的就是把一个一个的附加功能,用Decorator的方式给一层一层地累加到原始数据源上,最终,通过组合获得我们想要的功能。
**
装饰模式的组成部分如下:
| Component(抽象组件) | 定义一个抽象接口以规范准备接收附加责任的对象 |
|---|---|
| Concrete Component(具体组件) | 实现抽象构件,通过装饰角色为其添加一些职责 |
| Decorator(抽象装饰) | 继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能 |
| Concrete Decorator(具体装饰) | 实现抽象装饰的相关方法,并给具体构件对象添加附加的责任 |
装饰模式的优点
- 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
- 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
- 装饰器模式完全遵守开闭原则
装饰模式的缺点
- 会增加许多子类,过度使用会增加程序得复杂性
装饰模式应用场景
- 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类
- 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰器模式却很好实现
- 当对象的功能要求可以动态地添加,也可以再动态地撤销时
装饰模式使用示例
假设我们需要渲染一个HTML的文本,但是文本还可以附加一些效果,比如加粗、变斜体、加下划线等。为了实现动态附加效果,可以采用Decorator模式。
public class DecoratorPattern {// 首先定义顶层接口public interface TextNode {void setText(String text);String getText();}public static class SpanNode implements TextNode {private String text;@Overridepublic void setText(String text) {this.text = text;}@Overridepublic String getText() {return "<span>" + text + "</span>";}}// 定义一个抽象的Decorator类public static abstract class NodeDecorator implements TextNode {// 将附加的功能添加到TextNodeprotected final TextNode target;protected NodeDecorator(TextNode target) {this.target = target;}public void setText(String text) {this.target.setText(text);}}// 给文本实现加粗效果public static class BoldDecorator extends NodeDecorator {public BoldDecorator(TextNode target) {super(target);}public String getText() {return "<b>" + target.getText() + "</b>";}}// 给文本实现斜向效果public static class ItalicDecorator extends NodeDecorator {public ItalicDecorator(TextNode target) {super(target);}public String getText() {return "<i>" + target.getText() + "</i>";}}// 给文本实现下划线效果public static class UnderlineDecorator extends NodeDecorator {public UnderlineDecorator(TextNode target) {super(target);}public String getText() {return "<u>" + target.getText() + "</u>";}}public static void main(String[] args) {// 给文本实现加粗、下划线、斜线的效果SpanNode node = new SpanNode();node.setText("bujian");BoldDecorator hello = new BoldDecorator(new UnderlineDecorator(new ItalicDecorator(node)));System.out.println(hello.getText());}}
程序运行结果:
:::success bujian :::
