• [设计模式]装饰者模式(decorator)


    1、定义:装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

    2、满足OO设计原则——开放-关闭原则:类应该对扩展开放,对修改关闭。

    注:装饰者模式是一个简单的能够实现开放-关闭原则的设计模式

    3、优点:

    • 能够遵循开放-关闭原则,使系统更有弹性
    • 组合和委托可以用于在运行时动态地加上新的行为
    • 装饰者类反映出被装饰的组件类型(事实上,它们具有相同的类型,都经过接口或集成实现)
    • 装饰者可以再被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。

    4、缺点:装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂。

    5、具体实现(完整代码保存在github上):

    • 抽象组件类:
    //饮料超类
    public abstract class Beverage{
        String description = "Unknown Beverage";
        public String getDescription(){
            return description;
        }
    
        public abstract double cost();
    }
    • 具体组件类:
    //饮料:深焙
    public class DarkRoast extends Beverage{
        public DarkRoast(){
            description = "DarkRoast";
        }
        public double cost(){
            return .99;
        }
    }
    
    //饮料:低咖啡因
    public class Decaf extends Beverage{
        public Decaf(){
            description = "Decaf";
        }
        public double cost(){
            return 1.05;
        }
    }
    
    //饮料:浓缩
    public class Espresso extends Beverage{
        public Espresso(){
            description = "Espresso";
        }
        public double cost(){
            return 1.99;
        }
    }
    
    //饮料:综合
    public class HouseBlend extends Beverage{
        public HouseBlend(){
            description = "House Blend coffee";
        }
        public double cost(){
            return .89;
        }
    }
    • 抽象装饰者类:
    //调料都继承自这里
    public abstract class CondimentDecorator extends Beverage{
        public abstract String getDescription();    
    }
    • 具体装饰者类:
    //调料:牛奶
    public class Milk extends CondimentDecorator{
        Beverage beverage;
        public Milk(Beverage beverage){
            this.beverage = beverage;
        }
        public String getDescription(){
            return beverage.getDescription() + ",Milk";
        }
        public double cost(){
            return .10 + beverage.cost();
        }
    }
    
    //调料:摩卡
    public class Mocha extends CondimentDecorator{
        Beverage beverage;
        public Mocha(Beverage beverage){
            this.beverage = beverage;
        }
        public String getDescription(){
            return beverage.getDescription() + ",Mocha";
        }
        public double cost(){
            return .20 + beverage.cost();
        }
    }
    
    //调料:豆浆
    public class Soy extends CondimentDecorator{
        Beverage beverage;
        public Soy(Beverage beverage){
            this.beverage = beverage;
        }
        public String getDescription(){
            return beverage.getDescription() + ",Soy";
        }
        public double cost(){
            return .15 + beverage.cost();
        }
    
    //调料:奶泡
    public class Whip extends CondimentDecorator{
        Beverage beverage;
        public Whip(Beverage beverage){
            this.beverage = beverage;
        }
        public String getDescription(){
            return beverage.getDescription() + ",Whip";
        }
        public double cost(){
            return .10 + beverage.cost();
        }
    }
    • 测试:
    public class StarbuzzCoffee{
        public static void main(String args[]){
            Beverage beverage = new Espresso();
            System.out.println(beverage.getDescription() + " $" + beverage.cost());
    
            Beverage beverage2 = new DarkRoast();
            beverage2 = new Mocha(beverage2);
            beverage2 = new Mocha(beverage2);
            beverage2 = new Whip(beverage2);
            System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
    
            Beverage beverage3 = new HouseBlend();
            beverage3 = new Soy(beverage3);
            beverage3 = new Mocha(beverage3);
            beverage3 = new Whip(beverage3);
            System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
    
        }
    }

    运行结果如下图所示:

    参考资料

    [1] head first 设计模式

  • 相关阅读:
    SignalR
    log4net
    nginx
    mongodb
    uni-app监听软键盘是否弹起,ios不支持
    js插件开发兼容commonJS、AMD、CDM的UMD写法
    uni-app 实现后端返回的图片文件流转base64
    input输入框限制只能输入数字和一个小数点
    Uni-app工程转vue-cli工程步骤
    H5 移动端开发注意事项
  • 原文地址:https://www.cnblogs.com/mj-selina/p/12470057.html
Copyright © 2020-2023  润新知