设计模式——装饰模式(Decorator)

230 阅读2分钟

一、概述

        动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。

二、使用场景

1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 

2.处理那些可以撤消的职责。 

3.当不能采用生成子类的方法进行扩充时。

三、参与者

1.Component 定义一个对象接口,可以给这些对象动态地添加职责。 

2.ConcreteComponent 定义一个对象,可以给这个对象添加一些职责。

3.Decorator 维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。 

4.ConcreteDecorator 就是具体的装饰对象,起到该Component添加职责的功能。

四、类图

五、Java代码示例

1.Component接口:

/**
 * 定义Component接口Person
 * @author zhipeng_Tong
 */
public interface Person {
    void speak();
}

2.ConcreteComponent:

/**
 * ConcreteComponent类,即Person的实现类
 * @author zhipeng_Tong
 */
public class Speaker implements Person {
    @Override
    public void speak() {
        System.out.println("时光的荏苒");
    }
}

3.Decorator抽象类:

/**
 * Decorator抽象类,实现了(Component接口的)Person
 * @author zhipeng_Tong
 */
public abstract class Decorator implements Person {
    protected Person person;

    public void setPerson(Person person) {
        this.person = person;
    }

    @Override
    public void speak() {
        if (person != null)
            person.speak();
    }
}

4.ConcreteDecorator装饰类:

public class ConcreteDecoratorA extends Decorator {
    @Override
    public void speak() {
        super.speak();
        seconedSpeak();
        System.out.println("ConcreteDecoratorA...Over");
    }

    private void seconedSpeak() {
        System.out.println("它蹉跎了所有");
    }
}

public class ConcreteDecoratorB extends Decorator {
    @Override
    public void speak() {
        super.speak();
        seconedSpeak();
        System.out.println("ConcreteDecoratorB...Over");
    }

    private void seconedSpeak() {
        System.out.println("他向我...");
    }
}

5.测试代码

public class Client {
    public static void main(String[] args) {
        Speaker speaker = new Speaker();
        ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA();
        ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB();

        concreteDecoratorA.setPerson(speaker);
        concreteDecoratorB.setPerson(concreteDecoratorA);
        concreteDecoratorB.speak();
    }
}

运行结果:

时光的荏苒
它蹉跎了所有
ConcreteDecoratorA...Over
他向我...
ConcreteDecoratorB...Over

六、GO代码示例

package main

import "fmt"

type Person interface {
   Show() // 展示自己
}

// Tramp 被装饰者
// 流浪汉
type Tramp struct{}

func (t *Tramp) Show() {
   fmt.Println("装扮:仅有一块遮羞布")
}

// ClothingDecorator 衣服装饰器
type ClothingDecorator struct {
   P Person
}

func (*ClothingDecorator) Show() {
}

// Jacket 夹克,具体装饰
type Jacket struct {
   ClothingDecorator
}

func (j *Jacket) Show() {
   j.P.Show()

   fmt.Println("装扮:+穿上夹克")
}

// Hat 帽子,具体装饰
type Hat struct {
   ClothingDecorator
}

func (h *Hat) Show() {
   h.P.Show()

   fmt.Println("装扮:+带上帽子")
}

func main() {
   tramp := new(Tramp)

   jacket := new(Jacket)
   jacket.P = tramp
   hat := new(Hat)
   hat.P = jacket

   hat.Show()
   // 装扮:仅有一块遮羞布
   // 装扮:+穿上夹克
   // 装扮:+带上帽子

}