Java 设计模式之装饰模式(八)

一、前言

本篇主题为结构型模式中的第三个模式–装饰模式。上篇 Java 设计模式主题为《Java 设计模式之桥接模式(七)》

二、简单介绍

2.1 定义

装饰模式又叫做包装模式,其功能是动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活,是继承关系的一个替换方案。

2.2 应用场景

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

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

三、实现方式

我们以人的打扮为例。人打扮需要穿衣,穿裤,穿鞋子。代码表示如下:

Person 类:

public class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }
    public void putOnClothes() {
        System.out.println(this.name + "穿衣服");
    }
    public void putOnTrousers() {
        System.out.println(this.name + "穿裤子");
    }
    public void putOnShoes() {
        System.out.println(this.name + "穿鞋子");
    }
}

客户端:

public class Client {
    public static void main(String[] args) {
        
        Person person = new Person("小白");
        
        person.putOnClothes();
        person.putOnTrousers();
        person.putOnShoes();
    }
}

打印:

小白穿衣服
小白穿裤子
小白穿鞋子

上述代码很简单,但是扩展性不好。当我们需要添加打领带、戴手表的行为时,需要修改 Person 类,违背了开放封闭原则。

因此,我们需要将人和打扮的行为抽离出来:

Person 类:

public class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    
}

打扮类:

public abstract class DressUp {
    public abstract void dressup(Person person);
}
class ClothesDressUp extends DressUp {
    @Override
    public void dressup(Person person) {
        System.out.println(person.getName() + "穿衣服");
    }
}
class TrousersDressUp extends DressUp {
    @Override
    public void dressup(Person person) {
        System.out.println(person.getName() + "穿裤子");
    }
}
class ShoesDressUp extends DressUp {
    @Override
    public void dressup(Person person) {
        System.out.println(person.getName() + "穿鞋子");
    }
}

客户端:

public class Client {
    public static void main(String[] args) {
        Person person = new Person("小白");
        
        DressUp du1 = new ClothesDressUp();
        du1.dressup(person);
        
        DressUp du2 = new TrousersDressUp();
        du2.dressup(person);
        
        DressUp du3 = new ShoesDressUp();
        du3.dressup(person);
    }
}

执行结果与上文的一致。现在,当我们添加新的打扮行为时,只需新增 DressUp 的子类即可。

但是,上边的代码没有封装性,每打扮一次都要调用 dressup 方法一次,就感觉人是光着身在公共场合进行打扮穿衣、穿鞋。因此,我们需要一种模式将这些打扮的细节封装起来,就像建造者模式一样。

不过,此次的需求不能使用建造者模式。因为建造者模式封装过程/细节是一个固定的顺序/模式,而当前需求是人的打扮,打扮的行为是多种多样的,如:穿衣穿裤、穿衣打领带、穿鞋戴手表等。

这样就引出了本章的主题–装饰模式:

Person 接口与实现类:

public interface Person {
    public void decorate();
}
class Man implements Person {
    @Override
    public void decorate() {
        System.out.println("男人打扮");
    }
    
}

装饰类:

public class Decorator implements Person {
    
    private Person person;
    public Decorator(Person person) {
        this.person = person;
    }
    @Override
    public void decorate() {
        this.person.decorate();
    }
}
class ClothesDecorator extends Decorator {
    public ClothesDecorator(Person person) {
        super(person);
    }
    public void decorate() {
        super.decorate();
        System.out.println("穿衣服");
    }
}
class TrousersDecorator extends Decorator {
    public TrousersDecorator(Person person) {
        super(person);
    }
    public void decorate() {
        super.decorate();
        System.out.println("穿裤子");
    }
}
class ShoesDecorator extends Decorator {
    public ShoesDecorator(Person person) {
        super(person);
    }
    public void decorate() {
        super.decorate();
        System.out.println("穿鞋子");
    }
}

客户端:

public class Client {
    public static void main(String[] args) {
        
        Person person = new Man();
        
        Person decorator = new Decorator(person);
        
        System.out.println("======第一种打扮=======");
        
        ClothesDecorator cd = new ClothesDecorator(decorator);
        
        TrousersDecorator td = new TrousersDecorator(cd);
        
        td.decorate();
        
        System.out.println("======第二种打扮=======");
        
        ShoesDecorator sd = new ShoesDecorator(person);
        
        sd.decorate();
    }
}

打印:

======第一种打扮=======
男人打扮
穿衣服
穿裤子
======第二种打扮=======
男人打扮
穿鞋子

总结:装饰模式有效地把类的核心职责和装饰功能区分开来,而且去除了相关类的重复的装饰逻辑。

UML 类图表示如下:

《Java 设计模式之装饰模式(八)》

    原文作者:算法小白
    原文地址: https://juejin.im/entry/5a0ce910f265da430c115ce5
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞