java - 装饰者模式

装饰者模式

装饰者模式:动态将责任添加到对象上。如果需要扩展功能,装饰者提供了比继承更有弹性的解决方案。装饰者模式类图如下:


装饰者模式类图(来源Head First).png

举个栗子:
情景如下:去饭店点菜的例子,饭店(Component),中国饭店(ConcreteComponent),菜品(Decorate),鱼(FishDecorate装饰者),牛排(SteakDecorate装饰者)

  • 被装饰者
    1,创建基类
/**
 * 饭店
 * @author cuishuxiang
 */
public abstract class Restaurant {
    //点菜
    String orderFood="Order Nothing";
    
    public String getOrderFoods() {
        return orderFood;
    }
    
    //根据点的菜,计算价格
    abstract int cost();
}

2,创建饭店的具体实现类

/**
 * 中国餐馆
 * @author cuishuxiang
 */
public class ChinaRestaurant extends Restaurant{
    
    public ChinaRestaurant() {
        // TODO Auto-generated constructor stub
    }
    
    @Override
    public String getOrderFoods() {
        // TODO Auto-generated method stub
        return super.getOrderFoods();
    }

    @Override
    int cost() {
        // 此时没点菜,价格为 0 
        return 0;
    }

}
  • 装饰者(继承基类拥有同一个父类Restaurant
    1,创建装饰者基类
/**
 * 抽象装饰者
 * @author cuishuxiang
 *
 */
public abstract class Decorate extends Restaurant{

  public abstract String getOrderFoods();//点了什么菜
  
}

2,鱼(具体的装饰者)

/**
 * 点了鱼
 * @author cuishuxiang
 *
 */
public class FishDecorate extends Decorate{
    private Restaurant restaurant;
    
    public FishDecorate(Restaurant restaurant) {
        // 这里持有 Restaurant 的引用
        this.restaurant=restaurant;
    }

    @Override
    int cost() {
        // 此时应先计算上个的价格 再加上 鱼的价格
        return restaurant.cost()+10;
    }

    @Override
    public String getOrderFoods() {
        // TODO Auto-generated method stub
        return " 点了China饭店的 鱼!";
    }

}

3,牛排(具体的装饰者)

/**
 * 牛排
 * 
 * @author cuishuxiang
 *
 */
public class SteakDecorate extends Restaurant{
    Restaurant restaurant;
    
    public SteakDecorate(Restaurant restaurant) {
        this.restaurant=restaurant;
    }
    
    @Override
    public String getOrderFoods() {
        return restaurant.getOrderFoods()+",点了饭店的牛排。";
    }
    @Override
    int cost() {
        return restaurant.cost()+20;
    }

}
  • 测试
/**
 * 测试类
 * @author cuishuxiang
 */
public class RestaurantTest {

    public static void main(String[] args) {
        Restaurant restaurant=new ChinaRestaurant();
        
        //装饰者,点了鱼(将引用传入)
        restaurant=new FishDecorate(restaurant);
        //装饰者,点了牛排
        restaurant=new SteakDecorate(restaurant);
            
        System.out.println("点的菜:"+restaurant.getOrderFoods());
                
        System.out.println("总价为: "+restaurant.cost());
    }
}

结果为:


装饰者测试结果.png
调用逻辑如上图.png
总结
  • 装饰者模式特点
    1,装饰者与被装饰者拥有相同的父类(如上例中的Restaurant)。
    2,装饰者中都持有一个被装饰者的引用(如上例中构造器需要传入一个Restaurant引用)。
    3,装饰者执行完自己的逻辑之后,会将最终的结果传递给被装饰者(在装饰者类当中调用被装饰者类的方法,封装成新的功能方法。)。
    4,扩展性比较好,灵活性高。但是响应的会出现比较多的类。
    5,java中最常见的就是I/O,使用的就是装饰者模式。

你可能感兴趣的:(java - 装饰者模式)