11:30超出了,哥们几个(当然还有几个女的,比如:“全总”,“鞠总”。),脚步依旧。沿着熟悉的路线,穿过那漫长的十字路口,奔着我们的食物(抽象类),当然这个抽象类包含了计算价格这个方法了getCost(),不过如果某一天红草莓发慈悲,可以我们这些劳苦大众,免费给我们吃,当然是非常愿意的啦,冲向红草莓(新型餐厅)。
来到红草莓楼下,几位女同志比较喜欢在一楼吃那些什么砂锅,面条什么的(具体的食物,实现了食物这个抽象类的getCost()方法,因为不管怎么样,都是要收费的),介于男同胞一直以来体力消耗都比较厉害,所以那些东西基本上吃不饱,所以就到二楼吃饭。
先来看看把,首先说女同志吧,女同志特别爱挑剔,吃个砂锅,要往里面加入一些配料,比如说,金针菇啊,海带啊,油豆腐啊,豆腐干啊,反正很多,跟每个人的口味有关。
好吧,那就先“全总”先来:我要一个砂锅,里面+金针菇+海带。OK,
全总的这个砂锅类:
砂锅金针菇海带 extends 食物 {getCost() {return 砂锅4元+金针菇2元+海带1元}}
鞠总的砂锅类:
砂锅金针菇 extends 食物{getCost() {return 砂锅4元+金针菇2元}}
接下来,公司又来了一堆MM。我要,砂锅+海带,我要砂锅+油豆腐,我要砂锅+豆腐干,我要……,我要……,发挥想象她到底要啥东西啊???
OH,my lady gaga,每个MM的食物一个类,要“类爆炸”了,神呐救救我吧。
这还不够,二楼的man还没说话呢,我要米饭+大排+小排+牛排(绝对的肉食动物),我要米饭+鲤鱼……又是一堆……
神啊。装饰者模式披着超人的披风,头戴性感黑丝袜,飞到了红草莓餐厅。
大家不要慌,我,装饰者模式先来介绍下自己(装饰者模式类图):
既然知道了这个类图,咱们就直接将具体场景翻译成这个类图吧。就直接上中文类图了(非常不推荐的方法)。
既然类图都出来了。那代码也就出来了。OK,下面直接实现代码吧。下面的代码中,类就直接用中文表示了。(实际操作中如果是这样操作,
当然是要被项目经理先砍头,然后再分尸的!)。这里我用了两种语言:JAVA和C#
JAVA食物类:
package DesignPattern.DecoratorPattern;
public abstract class 食物 {
String name = "不知道什么食物";
public String getName() {
return name;
}
public abstract double getCost();
}
C#食物类:
public abstract class 食物
{
protected String name = "不知道什么食物";
public virtual String getName() {
return name;
}
public abstract double getCost();
}
JAVA菜类:
package DesignPattern.DecoratorPattern;
public abstract class 菜 extends 食物 {
//所有的菜装饰者都要重新实现getName()这个方法
//为了之后显示主要食物和加了什么菜的。
public abstract String getName();
}
C#菜类:
/// <summary>
/// Description of 菜.
/// </summary>
public abstract class 菜:食物
{
public 菜(){
}
}
JAVA砂锅类:
package DesignPattern.DecoratorPattern;
public class 砂锅 extends 食物 {
// 构造函数
public 砂锅() {
name = "砂锅";
}
@Override
public double getCost() {
// TODO Auto-generated method stub
return 4.0;
}
}
C#砂锅类:
/// <summary>
/// Description of 米饭.
/// </summary>
public class 砂锅:食物
{
public override string getName()
{
return "砂锅";
}
public override double getCost()
{
return 4.0;
}
}
JAVA米饭类:
package DesignPattern.DecoratorPattern;
public class 米饭 extends 食物 {
// 构造函数
public 米饭() {
name = "米饭";
}
@Override
public double getCost() {
// TODO Auto-generated method stub
return 1.0;
}
}
C#米饭类:
/// <summary>
/// Description of 米饭.
/// </summary>
public class 米饭:食物
{
public override double getCost()
{
return 1.0;
}
public 米饭(){
}
public override string getName()
{
return "米饭";
}
}
JAVA香干类:
package DesignPattern.DecoratorPattern;
public class 香干 extends 菜 {
食物 obj;
public 香干(食物 obj) {
this.obj = obj;
}
public String getName() {
// TODO Auto-generated method stub
return obj.getName() + ",+香干";
}
public double getCost() {
// TODO Auto-generated method stub
return 0.5 + obj.getCost();
}
}
C#香干类:
/// <summary>
/// Description of 香干.
/// </summary>
public class 香干:菜
{
食物 obj;
public override string getName()
{
return obj.getName()+",香干";
}
public override double getCost()
{
return 0.5+obj.getCost();
}
public 香干(食物 obj)
{
this.obj=obj;
}
}
JAVA大排类:
package DesignPattern.DecoratorPattern;
public class 大排 extends 菜 {
食物 obj;
public 大排(食物 obj) {
this.obj = obj;
}
public String getName() {
// TODO Auto-generated method stub
return obj.getName() + ",+大排";
}
public double getCost() {
// TODO Auto-generated method stub
return 4 + obj.getCost();
}
}
C#大排类:
public class 大排:菜
{
食物 obj;
public override string getName()
{
return obj.getName()+",大排";
}
public override double getCost()
{
return 4+obj.getCost();
}
public 大排(食物 obj)
{
this.obj=obj;
}
}
测试JAVA类:
package DesignPattern.DecoratorPattern;
public class Decorator {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
食物 ricedan=new 米饭();
System.out.println(ricedan.getName()+" ¥"+ricedan.getCost());
食物 rice = new 米饭();
rice = new 大排(rice);
rice = new 香干(rice);
System.out.println(rice.getName() + " ¥" + rice.getCost());
食物 tajines=new 砂锅();
tajines=new 香干(tajines);
System.out.println(tajines.getName()+" ¥"+tajines.getCost());
}
}
测试结果:
米饭 ¥1.0
米饭,大排,香干 ¥5.5
砂锅,香干 ¥4.5
C#版本:
/*
* Created by SharpDevelop.
* User: qiyj
* Date: 2010-4-13
* Time: 2:34
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
namespace ConsoleProject
{
public class A
{
public static void Main()
{
食物 rice=new 米饭();
Console.WriteLine(rice.getName()+" ¥"+rice.getCost());
食物 rice2=new 米饭();
rice2=new 大排(rice2);
Console.WriteLine(rice2.getName()+" ¥"+rice2.getCost());
Console.ReadKey();
}
}
}
结果:
米饭 ¥1
米饭,大排 ¥5
总结:
在使用装饰者模式中,用到了抽象类,没有用到接口,当然最好的情况是用接口,但是普遍都是使用抽象类的,GOF里面都这么说的,这就是约定吧。当然在测试程序里面,我们可以使用工厂模式来产生相应的装饰者,之后会有用到。