zoukankan      html  css  js  c++  java
  • 【设计模式】2.装饰者模式

    装饰者模式

    装饰者模式(Decorator),不改变原本对象,动态地给一个对象添加一些额外的职责,比继承更加灵活(继承在扩展功能上是静态的),符合开闭原则(对于扩展是开放的,对于更改是封闭的)

    Component:抽象的装饰主体

    ConcreteComponent:具体的装饰主体

    Decorator:抽象的装饰者

    ConcreteDecorator:具体的装饰者

    结构图:

    场景:

      假如现在有饮料需要加配料出售,饮料分为纯牛奶和纯净水,配料有糖、茶,如果使用子类继承的方式(饮料都加配料)实现价格计算,将需要六种方案,也就是需要写六个子类来实现。如果业务扩展,饮料种类增加,配料种类也增加,将会产生大量的子类,即“类爆炸”。

    解决:

      采用装饰者模式将可以解决这个问题。被装饰的是饮料本身(纯牛奶、纯净水),配料的不同选择即为不同的装饰。

    结构图:

    例:

    public interface Drink {              // Component
        float cost();
        String desc();
    }
    public class Milk implements Drink {  // ConcreteComponent1
    
        @Override
        public float cost() {
            return 10.0f;
        }
    
        @Override
        public String desc() {
            return "纯牛奶";
        }
    }
    public class Water implements Drink {  // ConcreteComponent2
        @Override
        public float cost() {
            return 1.0f;
        }
    
        @Override
        public String desc() {
            return "纯净水";
        }
    }
    public abstract class DrinkDecorator implements Drink {  // Decorator
    
        private Drink drink;  // 要装饰的对象
    
        public Decorator(Drink drink) {
            this.drink = drink;
        }
    
        @Override
        public float cost() {
            return drink.cost();
        }
    
        @Override
        public String desc() {
            return drink.desc();
        }
    }
    public class SugarDecorator extends DrinkDecorator{
        public SugarDecorator(Drink drink) {
            super(drink);
        }
    
        @Override
        public float cost() {
            return super.cost() + 1.0f;
        }
    
        @Override
        public String desc() {
            return super.desc() + "+糖";
        }
    }
    public class TeaDecorator extends DrinkDecorator{
        public TeaDecorator(Drink drink) {
            super(drink);
        }
    
        @Override
        public float cost() {
            return super.cost() + 2.0f;
        }
    
        @Override
        public String desc() {
            return super.desc() + "+茶";
        }
    }
    public class Test {
        public static void main(String[] args) {
            System.out.println("装饰方式一:");             // 主料:纯牛奶,先加糖后加茶
            Drink milk = new Milk();
            SugarDecorator sugar = new SugarDecorator(milk); // 纯牛奶 + 糖(第一步装饰)
            TeaDecorator tea = new TeaDecorator(sugar);       // 纯牛奶 + 糖 + 茶(第二步装饰)
            System.out.println(tea.desc());
            System.out.println(tea.cost());
    
            System.out.println("装饰方式二:");             // 主料:纯净水,先加茶后加水
            Drink water = new Water();
            TeaDecorator tea1 = new TeaDecorator(water);   // 纯净水 + 茶(第一步装饰)
           SugarDecorator sugar1 = new SugarDecorator(tea1); // 纯净水 + 茶 + 糖(第二步装饰)
            System.out.println(sugar1.desc());
            System.out.println(sugar1.cost());
        }
    }

    输出:

    装饰方式一:
    纯牛奶+糖+13.0
    装饰方式二:
    纯净水+茶+4.0

    说明:

    根据面向接口编程的思想,Drink(角色:Component)需是接口,MilkWater(角色:ConcreteComponent)是其具体实现类,DrinkDecorator(角色:Decorator)也需是其实现类,SugarDecoratorTeaDecorator(角色:ConcreteDecorator)是DrinkDecorator的子类。

    分析:

    Drink milk = new Milk();

    SugarDecorator sugar = new SugarDecorator(milk);   // 1.纯牛奶 + 糖(第一步装饰)

    TeaDecorator tea = new TeaDecorator(sugar);       // 2.纯牛奶 + + 茶(第二步装饰)

      首先创建装饰主体:Milk类对象milk,然后利用SugarDecorator的构造器对其进行装饰,随后再将SugarDecorator装饰过的对象传入TeaDecorator的构造器对其进行再次装饰。

      看第2处代码,再次装饰时,构造器需传入Drink的实现类对象,所以已被装饰过的对象必须是Drink接口的实现类,而已被装饰过的对象是DrinkDecorator的子类,所以DrinkDecoratorDecorator)需实现Drink接口(Component)。

      如果,饮料只有一种(纯牛奶),则不需要Drink接口(Component),直接将DrinkDecoratorDecorator)继承MilkConcreteComponent)即可。结构图如下:

      而且Decorator也可以有多个,完成不同场景下的装饰工作。

  • 相关阅读:
    201671030123叶虹 实验十四 团队项目评审&课程学习总结
    201671030123叶虹《英文文本统计分析》结对项目报告
    201671030123 叶虹 实验三作业互评与改进报告
    《构建之法》——三个问题
    201671030129 周婷 实验十四 团队项目评审&课程学习总结
    201671030129 周婷 《英文文本统计分析》结对项目报告
    201671030129 词频统计项目报告
    201671030129 周婷 实验三:作业互评与改进
    快速通读《现代软件工程——构建之法》
    201673020127 郁文曦 课程学习总结
  • 原文地址:https://www.cnblogs.com/jiazhongxin/p/12794067.html
Copyright © 2011-2022 走看看