设计模式之装饰者模式

一、简介

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

装饰者模式特点:

  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
posted @ 2016-03-18 17:05  苍穹2018  阅读(332)  评论(5编辑  收藏  举报