小戚园地

Do as I want to do!
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

红草莓(餐厅)--装饰者模式

Posted on 2010-04-13 01:41  YeanJay  阅读(585)  评论(0编辑  收藏  举报

    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;
        }
    }

OK.所有的类搞定,接下来开始测试这个模式了。下面写一个main方法,太迟了,明天早上再写了。

测试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里面都这么说的,这就是约定吧。当然在测试程序里面,我们可以使用工厂模式来产生相应的装饰者,之后会有用到。