在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下,可以动态地扩展其功能。所有这些都可以釆用装饰模式来实现。
装饰器模式(Decorator Pattern)
,又叫作包装器模式(Wrapper Pattern):
指在不改变原有对象结构的基础情况下,动态地给该对象增加一些额外功能的职责。装饰器模式相比生成子类更加灵活。它属于对象结构型模式。
装饰模式和代理模式的功能是雷同的,两者区别是:
通常情况下,扩展一个类的功能会使用继承方式来实现。但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。
如果使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰模式的目标。
下面来分析其基本结构和实现方法。
(1)模式的结构
装饰模式主要包含四个角色。
装饰器模式j角色分配符合设计模式的里氏替换原则、依赖倒置原则,从而使得其具备很强的扩展性,最终满足开闭原则。
主要优点:
主要缺点:
在框架源码中使用也很广泛,比如:
代码如下:
public class DecoratorPattern {
public static void main(String[] args) {
Component p = new ConcreteComponent();
p.operation();
System.out.println("---------------装饰之后------------------");
Component d = new ConcreteDecorator(p);
d.operation();
}
}
//抽象构件
interface Component {
public void operation();
}
//具体构件
class ConcreteComponent implements Component {
public ConcreteComponent() {
System.out.println("创建具体构件角色");
}
// 相应的功能处理
@Override
public void operation() {
System.out.println("调用具体构件角色的方法operation()");
}
}
//抽象装饰器
class Decorator implements Component {
// 持有的组件对象
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
// 处理前后可以加一些附加功能
component.operation();
}
}
//具体装饰器
class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
@Override
public void operation() {
// 在处理父类的方法时,可以在处理前后可以加一些附加功能
// 如果不调用父类的方法,表示完全改写方法,实现新功能
super.operation();
addedFunction();
}
public void addedFunction() {
System.out.println("为具体构件角色增加额外的功能addedFunction()");
}
}
用一个卖煎饼果子的例子来说明。
1、抽象构件(Component)
public abstract class Battercake {
protected abstract String getMessage();
protected abstract int getPrice();
}
2、具体构件(ConcreteComponent)
public class BaseBattercake extends Battercake{
@Override
protected String getMessage() {
return "煎饼果子";
}
@Override
protected int getPrice() {
return 5;
}
}
3、抽象装饰器(Decorator)
public abstract class BattercakeDecorator extends Battercake{
// 静态代理,委托
private Battercake battercake;
public BattercakeDecorator(Battercake battercake) {
this.battercake = battercake;
}
@Override
protected String getMessage() {
return this.battercake.getMessage();
}
@Override
protected int getPrice() {
return this.battercake.getPrice();
}
// 可以加额外功能方法
protected abstract void addedFunction();
}
4、具体装饰器(ConcreteDecorator)
这里给定三种辅料可供选择
public class EggDecorator extends BattercakeDecorator {
public EggDecorator(Battercake battercake) {
super(battercake);
}
@Override
protected String getMessage() {
return super.getMessage() + " + 1个鸡蛋";
}
@Override
protected int getPrice() {
return super.getPrice() + 2;
}
@Override
protected void addedFunction() {
}
// 可以加其特有的功能方法
}
public class SausageDecorator extends BattercakeDecorator{
public SausageDecorator(Battercake battercake) {
super(battercake);
}
@Override
protected String getMessage() {
return super.getMessage() + " + 一个香肠";
}
@Override
protected int getPrice() {
return super.getPrice() + 4;
}
@Override
protected void addedFunction() {
}
// 可以加其特有的功能方法
}
public class OtherDecorator extends BattercakeDecorator{
public OtherDecorator(Battercake battercake) {
super(battercake);
}
@Override
protected String getMessage() {
return message();
}
@Override
protected int getPrice() {
return price();
}
@Override
protected void addedFunction() {
}
// 可以加其特有的功能方法
private String message(){
return "老板,啥也不要,来根大葱";
}
private int price(){
return 5;
}
}
5、测试
在public class Test {
public static void main(String[] args) {
System.out.println("===来一个基础版煎饼果子===");
Battercake battercake = new BaseBattercake();
System.out.println(battercake.getMessage() + ",总价格:" + battercake.getPrice() + "元。");
System.out.println("===来一个套餐A煎饼果子===");
battercake = new EggDecorator(battercake);
System.out.println(battercake.getMessage() + ",总价格:" + battercake.getPrice() + "元。");
System.out.println("===来一个套餐A+B煎饼果子===");
battercake = new SausageDecorator(battercake);
System.out.println(battercake.getMessage() + ",总价格:" + battercake.getPrice() + "元。");
System.out.println("===屌丝买煎饼果子===");
Battercake battercake2 = new BaseBattercake();
battercake2 = new OtherDecorator(battercake2);
System.out.println(battercake2.getMessage() + ",总价格:" + battercake2.getPrice() + "元。");
}
}
装饰模式所包含的 4 个角色不是任何时候都要存在的,在有些应用环境下模式是可以简化的,有时候抽象装饰器是可有可无的,如以下两种情况。(图来自网络)
1、只有一个具体装饰器,这样就不需要抽象装饰器,其结构图如下:
2、只有一个具体构件,这样就不需要抽象构件,抽象装饰者可以直接继承具体构件,其结构图如下:
3、只有一个具体构件和一个具体装饰者,这样抽象角色都不需要了,具体装饰者直接继承集体构件就可以了
参考文章:
—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。