一个简单的装饰器类

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/gnuhpc/archive/2009/10/21/4710427.aspx

 

“三明治”的例子:三明治必不可少的是两块面包片,然后可以在夹层里加上蔬菜、沙拉、咸肉等等,外面可以涂上奶油之类的。假如现在你要为一个三明治小店构造一个程序,其中要设计各种三明治的对象。可能你已经创建了一个简单的Sandwich对象,现在要产生带蔬菜的就是继承原有的Sandwich添加一个蔬菜的成员变量,看起来很“正点”的做法,以后我还要带咸肉的、带奶油的、带蔬菜的又分为带青菜的、带芹菜的、生菜的……还是一个一个继承是吧!假如我们还需要即带蔬菜又带其它肉类,设置我们还要求这些添加成分的任意组合,那你就慢慢继承吧!下面我们就使用装饰器模式来设计这个库吧!下图是我们的设计图:

 

下面是以上各个类的意义:

1. Ingredient(成分):所有类的父类,包括它们共有的方法,一般为抽象类且方法都有默认的实现,也可以为接口。它有Bread和Decorator两个子类。这种实际不存在的,系统需要的抽象类仅仅表示一个概念,图中用红色表示。

2. Bread(面包):就是我们三明治中必须的两片面包。它是系统中最基本的元素,也是被装饰的元素,和IO中的媒质流(原始流)一个意义。在装饰器模式中属于一类角色,所以其颜色为紫色。

3. Decorator(装饰器):所有其它成分的父类,这些成分可以是猪肉、羊肉、青菜、芹菜。这也是一个实际不存在的类,仅仅表示一个概念,即具有装饰功能的所有对象的父类。图中用蓝色表示。

4. Pork(猪肉):具体的一个成分,不过它作为装饰成分和面包搭配。

5. Mutton(羊肉):同上。

6. Celery(芹菜):同上。

7. Greengrocery(青菜):同上。

总结一下装饰器模式中的四种角色:1.被装饰对象(Bread);2.装饰对象(四种);3.装饰器(Decorator);4.公共接口或抽象类(Ingredient)。其中1和2是系统或者实际存在的,3和4是实现装饰功能需要的抽象类。

写段代码体会其威力吧!(程序很简单,但是实现的方法中可以假如如何你需要的方法,意境慢慢体会吧!)

//Ingredient.java

public abstract class Ingredient {

public abstract String getDescription();

public abstract double getCost();

public void printDescription(){

System.out.println(" Name "+ this.getDescription());

System.out.println(" Price RMB "+ this.getCost());

}

}

所有成分的父类,抽象类有一个描述自己的方法和一个得到价格的方法,以及一个打印自身描述和价格的方法(该方法与上面两个方法构成模板方法哦!)

//Bread.java

public class Bread extends Ingredient {

private String description ;

public Bread(String desc){

this.description=desc ;

}

public String getDescription(){

return description ;

}

public double getCost(){

return 2.48 ;

}

}

面包类,因为它是一个具体的成分,因此实现父类的所有的抽象方法。描述可以通过构造器传入,也可以通过set方法传入。同样价格也是一样的,我就很简单地返回了。

//Decorator.java

public abstract class Decorator extends Ingredient {

Ingredient ingredient ;

public Decorator(Ingredient igd){

this.ingredient = igd;

}

public abstract String getDescription();

public abstract double getCost();

}

装饰器对象,所有具体装饰器对象父类。它最经典的特征就是:1.必须有一个它自己的父类为自己的成员变量;2.必须继承公共父类。 这是因为装饰器也是一种成分,只不过是那些具体具有装饰功能的成分的公共抽象罢了。在我们的例子中就是有一个Ingredient作为其成员变量。Decorator继承了Ingredient类。

//Pork.java

public class Pork extends Decorator{

public Pork(Ingredient igd){

super(igd);

}

public String getDescription(){

String base = ingredient.getDescription();

return base +"\n"+"Decrocated with Pork !";

}

public double getCost(){

double basePrice = ingredient.getCost();

double porkPrice = 1.8;

return basePrice + porkPrice ;

}

}

具体的猪肉成分,同时也是一个具体的装饰器,因此它继承了Decorator类 。猪肉装饰器装饰可以所有的其他对象,因此通过构造器传入一个Ingredient的实例,程序中调用了父类的构造方法,主要父类实现了这样的逻辑关系。同样因为方法是具体的成分,所以getDescription得到了实现,不过由于它是具有装饰功能的成分,因此它的描述包含了被装饰成分的描述和自身的描述。价格也是一样的。价格放回的格式被装饰成分与猪肉成分的种价格哦!

从上面两个方法中我们可以看出,猪肉装饰器的功能得到了增强,它不仅仅有自己的描述和价格,还包含被装饰成分的描述和价格。主要是因为被装饰成分是它的成员变量,因此可以任意调用它们的方法,同时可以增加自己的额外的共同,这样就增强了原来成分的功能。

//Mutton.java

public class Mutton extends Decorator{

public Mutton(Ingredient igd){

super(igd);

}

public String getDescription(){

String base = ingredient.getDescription();

return base +"\n"+"Decrocated with Mutton !";

}

public double getCost(){

double basePrice = ingredient.getCost();

double muttonPrice = 2.3;

return basePrice + muttonPrice ;

}

}

羊肉的包装器。

//Celery.java

public class Celery extends Decorator{

public Celery(Ingredient igd){

super(igd);

}

public String getDescription(){

String base = ingredient.getDescription();

return base +"\n"+"Decrocated with Celery !";

}

public double getCost(){

double basePrice = ingredient.getCost();

double celeryPrice =0.6;

return basePrice + celeryPrice ;

}

}

芹菜的包装器。

//GreenGrocery.java

public class GreenGrocery extends Decorator{

public GreenGrocery (Ingredient igd){

super(igd);

}

public String getDescription(){

String base = ingredient.getDescription();

return base +"\n"+"Decrocated with GreenGrocery !";

}

public double getCost(){

double basePrice = ingredient.getCost();

double greenGroceryPrice = 0.4;

return basePrice + greenGroceryPrice ;

}

}

青菜的包装器。

下面我们就领略装饰器模式的神奇了!我们有一个测试类,其中建立夹羊肉的三明治、全蔬菜的三明治、全荤的三明治。
public class DecoratorTest{

public static void main(String[] args){

Ingredient compound = new Mutton(new Celery(new Bread("Master24's Bread")));

compound.printDescription();

compound = new Celery(new GreenGrocery(new Bread("Bread with milk")));

compound.printDescription();

compound = new Mutton(new Pork(new Bread("Bread with cheese")));

compound.printDescription();

}

}

以上就是一个简单的装饰器类。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值