Java设计模式之结构型模式-装饰器模式(Decorator)

  今天来讲讲装饰器模式,对于这个模式我还是比较有印象的。因为我去年考软件设计师的设计模式大题考的就是这个装饰器模式。当时真的是一窍不通,连拼带凑的把题做完了,还好我运气好给通过了:)。

装饰模式: 动态的为一个对象添加一些额外的职责。就增加功能来说,装饰器模式比生成子类的方式更加的灵活。

四个要素

  1. Component: 定义一个对象的接口,同时也可以动态的为其添加职责。
  2. ConcreteComponent: 定义的具体的对象,实现Component接口。
  3. Decorator: 装饰器抽象类,实现Component接口,拥有Component的职责,同时也可以扩展职责。
  4. ConcreteDecorator: 定义具体的装饰器实现类对象,可以向ConcreteComponent添加职责,同时也可以定义额外的职责。

示例

  女朋友最喜欢的事就是吃,干的最多的事也就是每次吃饭的时候发图片给我看,然后顺便安慰下正在苦逼撸代码的我要好好上班(我很感动,默默的拿出了我的刀。也没办法,谁让人家吃饭的时间总提早我半小时)。
  既然说到吃,那这里我就用吃举例子吧。
  我这里就以正餐 Dinner(即四个要素中的 Component)为例子,具体分为中餐ChineseMeal和西餐WesternStyleMeal(这两者即四个要素中的ConcreteComponent)。然后还有我们正餐所需的各种食物(即四个要素中的 ConcreteDecorator),至于四个要素中的Decorator我们可以理解为我们的菜单(Menu)。
  

类图

  以示例为基础,我这里粗略的画下类图:
  Java设计模式之结构型模式-装饰器模式(Decorator)_第1张图片

实现过程

  1. 创建对象接口 Dinner

public interface Dinner {

    void eat();
}

  2. 创建具体的对象类 ChineseMeal、WesternStyleMeal

public class ChineseMeal implements Dinner {

    @Override
    public void eat() {
        System.out.println("-----中餐套餐-----");
    }
}
public class WesternStyleMeal implements Dinner {

    @Override
    public void eat() {
        System.out.println("-----西餐套餐-----");
    }
}

  3. 创建抽象装饰器类 Menu

public abstract class Menu implements Dinner {

    protected Dinner dinner;

    public Menu(Dinner dinner) {
        this.dinner = dinner;
    }

    @Override
    public void eat() {
        dinner.eat();
    }
}

  4. 创建具体的装饰器类(我这里建的有点多)Steak、Spaghetti、Salad、Rice、BoiledMeat、BoiledFish

public class Steak extends Menu {

    public Steak(Dinner dinner) {
        super(dinner);
    }

    @Override
    public void eat() {
        super.eat();
        System.out.println("牛排");
    }

}
public class Spaghetti extends Menu {

    public Spaghetti(Dinner dinner) {
        super(dinner);
    }

    @Override
    public void eat() {
        super.eat();
        System.out.println("意大利面");
    }
}
public class Salad extends Menu {

    public Salad(Dinner dinner) {
        super(dinner);
    }

    @Override
    public void eat() {
        super.eat();
        System.out.println("沙拉");
    }
}
public class Rice extends Menu {

    public Rice(Dinner dinner) {
        super(dinner);
    }

    @Override
    public void eat() {
        super.eat();
        System.out.println("米饭");
    }
}
public class BoiledMeat extends Menu {

    public BoiledMeat(Dinner dinner) {
        super(dinner);
    }

    @Override
    public void eat() {
        super.eat();
        System.out.println("水煮牛肉");
    }
}
public class BoiledFish extends Menu {

    public BoiledFish(Dinner dinner) {
        super(dinner);
    }

    @Override
    public void eat() {
        super.eat();
        System.out.println("水煮鱼");
    }
}

  5. 创建装饰器测试类 DecoratorTest

public class DecoratorTest {

    public static void main(String[] args) {
        System.out.println("今天吃中餐");
        Dinner cmd = new ChineseMeal();
        Rice rice = new Rice(cmd);
        BoiledMeat boiledMeat = new BoiledMeat(rice);
        boiledMeat.eat();

        Rice rice1 = new Rice(cmd);
        BoiledFish boiledFish = new BoiledFish(rice1);
        boiledFish.eat();

        System.out.println("----------------\n\n今天吃西餐");
        Dinner wmd = new WesternStyleMeal();
        Salad salad = new Salad(wmd);
        Steak steak = new Steak(salad);
        steak.eat();

        Salad salad1 = new Salad(wmd);
        Spaghetti spaghetti = new Spaghetti(salad1);
        spaghetti.eat();
    }
}

程序运行结果如下:

今天吃中餐
-----中餐套餐-----
米饭
水煮牛肉
-----中餐套餐-----
米饭
水煮鱼
----------------

今天吃西餐
-----西餐套餐-----
沙拉
牛排
-----西餐套餐-----
沙拉
意大利面

优点

  1. 解耦: 装饰类和被装饰类可以独立发展不会相互耦合,每个具体的装饰对象只关心自己的功能。
  2. 易扩展: 作为继承的一个替代模式,可以动态的扩展装饰类。

你可能感兴趣的:(设计模式)