首页 > 技术文章 > 设计模式之装饰者模式

huipengbo 2017-05-20 05:39 原文

一.装饰者模式特点:
1.装饰者和被装饰者对象有相同的超类
2.可以用一个或多个装饰者包装一个对象
3.由于装饰者和被装饰者具有相同超类,所以任何需要被包装对象的场合,可以用装饰过的对象代替
4.装饰者可以再所委托被装饰者的行为之前或之后,加上自己的行为,以达到特定的目的(重点)
5.对象可以在任何时候被装饰,所以可以在运行时动态的不限量的用你喜欢的装饰者来装饰对象
二.装饰者模式定义:

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

三.代码部分

1.咖啡超类

 

 1 package com.pattern.decorate;
 2 /*
 3  * 咖啡超类
 4  */
 5 public abstract class Coffee {
 6     
 7     String des;//对咖啡的描述
 8 
 9     public String getDes() {
10         return des;
11     }
12 
13     public void setDes(String des) {
14         this.des = des;
15     }
16     
17     public abstract double cost();//不同的咖啡花费不同
18     
19 }

 

2.咖啡实体类一意大利咖啡,被修饰者

 1 package com.pattern.decorate;
 2 /**
 3  * 意大利咖啡,被装饰者
 4  * @author Administrator
 5  *
 6  */
 7 public class ItalianCoffee extends Coffee {
 8 
 9     public ItalianCoffee() {
10         des = "意大利咖啡";
11     }
12     
13     @Override
14     public double cost() {
15         return 10.99;
16 
17     }
18 
19 }

3.咖啡实体类2被装饰者

 1 package com.pattern.decorate;
 2 /**
 3  * 美式咖啡,被装饰者
 4  * @author Administrator
 5  *
 6  */
 7 public class CafeAmericano extends Coffee {
 8 
 9     public CafeAmericano() {
10         des = "美式咖啡";
11     }
12     
13     @Override
14     public double cost() {
15         // TODO Auto-generated method stub
16         return 8.10;
17     }
18 
19 }

4.装饰者超类,调料

 1 package com.pattern.decorate;
 2 /**
 3  * 装饰者的超类,咖啡调料,也是咖啡一部分,所以继承Coffee
 4  * @author Administrator
 5  *
 6  */
 7 public abstract class CoffeeCondiment extends Coffee {
 8 
 9     
10     
11     @Override
12     public abstract String getDes();//要知道调料加到什么咖啡中
13     @Override
14     public abstract double cost();//不同的调料价格不一样
15 }

5.装饰者实现类1巧克力

 1 package com.pattern.decorate;
 2 /**
 3  * 装饰者实现类,用来修饰Coffee对象
 4  * @author Administrator
 5  *
 6  */
 7 public class Chocolate extends CoffeeCondiment {
 8 
 9     Coffee coffee;//肯定会有这个引用表示调料要加到咖啡中
10 
11     public Chocolate(Coffee coffee) {
12         this.coffee = coffee;
13         this.des = "巧克力";
14     }
15 
16     @Override
17     public String getDes() {
18         // TODO Auto-generated method stub
19         return this.des+coffee.getDes();
20     }
21 
22     @Override
23     public double cost() {
24         // TODO Auto-generated method stub
25         return coffee.cost()+5.1;//加一种调料价钱加一点
26     }
27 
28 }

6.装饰者实现类2冰块

 1 package com.pattern.decorate;
 2 /**
 3  * 装饰者实现类,用来修饰Coffee对象,
 4  * @author Administrator
 5  *
 6  */
 7 public class Ice extends CoffeeCondiment {
 8 
 9     Coffee coffee;//肯定会有这个引用表示调料要加到咖啡中
10 
11     public Ice(Coffee coffee) {
12         this.coffee = coffee;
13         this.des = "冰块";
14     }
15 
16     @Override
17     public String getDes() {
18         // TODO Auto-generated method stub
19         return this.des+coffee.getDes();
20     }
21 
22     @Override
23     public double cost() {
24         // TODO Auto-generated method stub
25         return coffee.cost()+1.5;//加一种调料价钱加一点
26     }
27 
28 }

7.装饰者实现类3摩卡

 1 package com.pattern.decorate;
 2 /**
 3  * 装饰者实现类,用来修饰Coffee对象,
 4  * @author Administrator
 5  *
 6  */
 7 public class Mocha extends CoffeeCondiment {
 8 
 9     Coffee coffee;//肯定会有这个引用表示调料要加到咖啡中
10 
11     public Mocha(Coffee coffee) {
12         this.coffee = coffee;
13         this.des = "摩卡";
14     }
15 
16     @Override
17     public String getDes() {
18         // TODO Auto-generated method stub
19         return this.des+coffee.getDes();
20     }
21 
22     @Override
23     public double cost() {
24         // TODO Auto-generated method stub
25         return coffee.cost()+8.2;//加一种调料价钱加一点
26     }
27 
28 }

8.测试类

 1 package com.pattern.decorate;
 2 /**
 3  * 装饰者模式测试代码
 4  * @author Administrator
 5  *
 6  */
 7 public class Client {
 8 
 9     public static void main(String[] args) {
10         //创建原始对象,意大利咖啡
11         Coffee coffee1 = new ItalianCoffee();
12         System.out.println("给我来一杯"+coffee1.getDes()+",价格:"+coffee1.cost());
13         System.out.println("---------------------------------------------");
14         Coffee coffee2 = new CafeAmericano();
15         System.out.println("给我来一杯"+coffee2.getDes()+",价格:"+coffee2.cost());
16         System.out.println("---------------------------------------------");
17         //创建装饰者
18         Coffee co = new  Chocolate(coffee1);//加入巧克力
19         co = new Ice(co);//在加入冰块
20         co = new Mocha(co);//再加入摩卡
21         System.out.println("给我来一杯"+co.getDes()+",价格:"+co.cost());
22         System.out.println("------------------------------------------------");
23         Coffee cof = new Ice(coffee2);
24         cof = new Mocha(cof);
25         System.out.println("给我来一杯"+cof.getDes()+",价格:"+cof.cost());
26         
27         
28         
29     }
30 
31 }

9.运行结果

10.装饰者模式要点:

@1继承属于扩展形式之一,但不是达到弹性设计的最佳方案

@2在我们的设计中,应该允许行为可以被扩展,而无需修改现有的代码

@3组合和委托可用于在运行时动态添加新的行为

@4除了继承装饰者模式也可以让我们扩展行为

@5装饰者模式意味着一群装饰者类,这些类用来包装具体的组件

@6装饰这类反映出被装饰者的组件类型,事实上他们都具有相同的类型,都经过接口或者继承实现

@7装饰者可以在被装饰者的行为前面与后面加上自己的行为,甚至被装饰者的整个行为替换掉而达到特定目的

@8可以用许许多多装饰者包装一个组件

@9装饰者一般对组件的客户是透明的,除非客户程序依赖于组建的具体类型

@10装饰者会导致设计中出现许许多多的小对象,如果过度使用,会让程序变得很复杂

 

推荐阅读