• 设计模式之装饰者模式


    一、简介

    装饰者模式,顾名思义,即为原有的对象添加新的职责。装饰者模式在不修改底层代码给原有对象添加了新的功能,相比继承更加具有弹性。

    装饰者模式特点:

    1. 具体被装饰者和装饰类都继承于相同的抽象类,继承的是类型,而不是行为。
    2. 可以使用多个装饰器装饰被装饰类。
    3. 由于被装饰类与装饰类具有同样的超类,因此能够用装饰后的对象代替原始对象。
    4. 装饰者可以在所委托被装饰者的行为之前或之后,加上自己的行为,以达到特定的目的。

    装饰者模式如下图所示,Component类为共同的超类,ConcreteComponent为被装饰类,Decorator为抽象装饰类,ConcreteDecoratorA/ConcreteDecoratorA为具体的装饰类,该类依赖Component类,并添加新方法,以添加新功能。

    decoator

    二、应用场景

    当一个超类有不同的子类,同时不同的子类有不同的附加功能,这时可以考虑使用装饰者模式。在Java IO中有具体的应用,如下图所示:

    io

    三、具体应用

    餐馆有2种食物,米饭和面条,可以加蛋、肉、大蒜,针对餐馆建立应用的类图如下所示:

    image

    源代码:

    /**
     * 食物抽象类
     */
    public abstract class Food {
      protected String description = "This is a food";
    
      public String getDescription() {
        return description;
      }
    
      public abstract double cost();
    
    }
    /**
     * 抽象装饰器类
     *
     */
    public abstract class SeasoningDecorator extends Food {
      protected Food food;
    
      public SeasoningDecorator(Food f) {
        food = f;
      }
    
      public abstract String getDescription();
    
    }

    具体的Component类,即被装饰类,rice和noodle

    /**
     * 米饭类
     */
    public class Rice extends Food {
      
       public Rice(){
         description ="This is rice";
       }
       
       public double cost() {
          return 1;
       }
    
    }
    /**
     * 面条
     */
    public class Noodle extends Food {
    
      public Noodle() {
        description = "This is noodle";
      }
    
      public double cost() {
        return 8;
      }
    
    }

    具体的装饰类

    /**
     * 蛋
     */
    public class Egg extends SeasoningDecorator {
      
      public Egg(Food f){
        super(f);
      }
    
      @Override
      public String getDescription() {
        return food.getDescription() + " with egg";
      }
    
      @Override
      public double cost() {
        return food.cost() + 1.0;
      }
    
    }
    /**
     * 肉
     */
    public class Meat extends SeasoningDecorator {
      public Meat(Food f) {
        super(f);
      }
    
      public String getDescription() {
        return food.getDescription() + " with meat";
      }
    
      public double cost() {
        return food.cost() + 5.0;
      }
    
    }
    /**
     * 大蒜
     */
    public class Garlic extends SeasoningDecorator {
      public Garlic(Food f) {
        super(f);
      }
    
      public String getDescription() {
        return food.getDescription() + " with garlic";
      }
    
      public double cost() {
        return food.cost() + 2;
      }
    
    }

    具体的测试类:

    public class FoodTest {
      public static void main(String[] args) {
        Food f1 = new Rice();
        f1 = new Meat(f1);
        f1 = new Egg(f1);
        System.out.println(f1.getDescription() + " $" + f1.cost());
    
        Food f2 = new Noodle();
        f2 = new Garlic(f2);
        f2 = new Egg(f2);
        f2 = new Egg(f2);
        System.out.println(f2.getDescription() + " $" + f2.cost());
      }
    }

    测试结果:

    This is rice with meat with egg $7.0
    This is noodle with garlic with egg with egg $12.0
  • 相关阅读:
    手把手教你用nodejs+SQL Server2012做增删改查
    js实现匀速运动及透明度动画
    SqlServer用sql对表名、字段做修改
    nodejs 使用fs实现多级联动
    关于此实现不是 Windows 平台 FIPS 验证的加密算法的一部分。
    访问快科技(驱动之家)某个新闻会自动跳转到web.techtoutiao.win
    在windows server上配置java jdk后,可能要些时间生效。
    .net webapi 收不到json 实体类参数,返回的json中带有k__BackingField
    空调 水槽 堵 用吹或吸都可以
    .net 4.0 程序遇到 停止工作 appcrash ,kernelbase.dll 等提示
  • 原文地址:https://www.cnblogs.com/codingexperience/p/5292855.html
Copyright © 2020-2023  润新知