第205章(1 / 1)

大话设计模式 吴强 2097 字 2个月前

通过例子告诉大家一点:任何设计不是一成不变的、模式的应用是极其灵活的……

大B:“装饰模式:Decorator常 被翻译成‘装饰’,我觉得翻译成‘油漆工’更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee。这两种实体在Decorator模式中是必须的。”

小A:“那我们应该如何去定义它?”

大B:“动态给一个对象添加一些额外的职责,就象在墙上刷油漆。使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。”

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

1、Ingredient(成分):所有类的父类,包括它们共有的方法,一般为抽象类且方法都有默认的实现,也可以为接口。它有Bread和Decorator两个子类。这种实际不存在的,系统需要的抽象类仅仅表示一个概念,2、Bread(面包):就是我们三明治中必须的两片面包。它是系统中最基本的元素,也是被装饰的元素,和IO中的媒质流(原始流)一个意义。在装饰器模式中属于一类角色,所以其颜色为紫色。

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

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

5、Mutton(羊肉):同上。

6、Celery(芹菜):同上。

7、Greengrocery(青菜):同上。

大B:“我们现在来总结一下装饰器模式中的四种角色:1、被装饰对象(Bread);2、装饰对象(四种);3、装饰器(Decorator);4、公共接口或抽象类(Ingredient)。其中1和2是系统或者实际存在的,3和4是实现装饰功能需要的抽象类。写段代码体会其威力!程序很简单,但是实现的方法中可以加入你需要的方法,意境慢慢体会吧!”

//Ingredient.java

publicabstractclassIngredient{

publicabstractStringgetDescription();

publicabstractdoublegetCost();

publicvoidprintDescription(){

System.out.println(“Name”+this.getDescription());

System.out.println(“PriceRMB”+this.getCost());

}

}

大B:“所有成分的父类,抽象类有一个描述自己的方法和一个得到价格的方法,以及一个打印自身描述和价格的方法。”

小A:“这个方法不就是与刚才的那两个方法构成模板方法吗?”

//Bread.java

publicclassBreadextendsIngredient{

privateStringdescription;

publicBread(Stringdesc){

this.description=desc;

}

publicStringgetDescription(){

returndescription;

}

publicdoublegetCost(){

return2.48;

}

}

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

//Decorator.java

publicabstractclassDecoratorextendsIngredient{

Ingredientingredient;

publicDecorator(Ingredientigd){

this.ingredient=igd;

}

publicabstractStringgetDescription();

publicabstractdoublegetCost();

}

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

//Pork.java

publicclassPorkextendsDecorator{

publicPork(Ingredientigd){

super(igd);

}

publicStringgetDescription(){

Stringbase=ingredient.getDescription();

returnbase+“\n”+“DecrocatedwithPork!”;

}

publicdoublegetCost(){

doublebasePrice=ingredient.getCost();

doubleporkPrice=1.8;

returnbasePrice+porkPrice;

}

}

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

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

//Mutton.java

publicclassMuttonextendsDecorator{

publicMutton(Ingredientigd){

super(igd);

}

publicStringgetDescription(){

Stringbase=ingredient.getDescription();

returnbase+“\n”+“DecrocatedwithMutton!”;

}

publicdoublegetCost(){

doublebasePrice=ingredient.getCost();

doublemuttonPrice=2.3;

returnbasePrice+muttonPrice;

}

}

羊肉的包装器。

//Celery.java

publicclassCeleryextendsDecorator{

publicCelery(Ingredientigd){

super(igd);

}

publicStringgetDescription(){

Stringbase=ingredient.getDescription();

returnbase+“\n”+“DecrocatedwithCelery!”;

}

publicdoublegetCost(){

doublebasePrice=ingredient.getCost();

doubleceleryPrice=0.6;

returnbasePrice+celeryPrice;

}

}

芹菜的包装器。

//GreenGrocery.java

publicclassGreenGroceryextendsDecorator{

publicGreenGrocery(Ingredientigd){

super(igd);

}

publicStringgetDescription(){

Stringbase=ingredient.getDescription();

returnbase+“\n”+“DecrocatedwithGreenGrocery!”;

}

publicdoublegetCost(){

doublebasePrice=ingredient.getCost();

doublegreenGroceryPrice=0.4;

returnbasePrice+greenGroceryPrice;

}

}

青菜的包装器。

大B:“我们来领略装饰器模式的神奇吧!我们有一个测试类,其中建立夹羊肉的三明治、全蔬菜的三明治、全荤的三明治。”

小A:“好像真的很香哦!”

publicclassDecoratorTest{

publicstaticvoidmain(String[]args){

Ingredientpound=newMutton(newCelery(newBread(“Master24sBread”)));

pound.printDescription();

pound=newCelery(newGreenGrocery(newBread(“Breadwithmilk”)));

pound.printDescription();

pound=newMutton(newPork(newBread(“Breadwithcheese”)));

pound.printDescription();

}

}

大B:“这就是一个简单的装饰器类!假如你对想中国式的吃法,可以将加入馒头、春卷皮、蛋皮……夹菜可以为肉丝……突然想到了京酱肉丝。”