先说点题外话:这几天的帖子基本全部纠结在星期一的帖子里一个朋友提出的需求了这完全背离了我的初衷发这个帖子的本意 是想和大家讨论寻求一些让我们在平时工作中所写的代码能具有更方便扩展和维护的方法。而不是具体的去解决什么需求。印象中每一本关于设计模式的书都会提到一句话大概意思是“不要把自己的代码仅仅局限于实现功能”实际工作中我也经常遇到这样的情况,当一个系统验收完成后用户使用了一段时间,一年,两年,或者更长突然有一天 用户需要对软件的核心功能进行添加,或者其他的什么原因导致你需要重新拿起这个丢了很长时间的系统去增加功能。这个时候就我个人而言大部分情况是不得不顺着代码先拟一遍系统的运行过程,及一些解决需求的思路对我来说这是一个非常枯燥和痛苦的事情。所以,有了一些想法,以至于后来有了这个帖子。面相对象的基本原则 封边-开放,到我们现在要讨论的设计模式,其实就我理解,设计模式的核心目的是对系统的功能进行解耦,最终目标是当我需要增加一个什么功能的时候我只需要关心我现在需要增加的功能,而不去关心以前的。举个最简单的例子,就像电脑内部的内存条吗,而做为主板,我根本不需要关心内存条内部是怎么工作不管他是1g,还是2g又或是8m的内存,我只需要提供个接口让他 插进来 就可以了,既PNP,即插即用 囧为什么我们的软件不能有这么方便的可扩展呢?这才是我这个帖子想要讨论和思考的
以下是今天的模式 命令模式 没有关心实现,还是以前天的 薪水问题 做为案例。
代码比较简单,希望愿意看代码的人参与讨论
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Salary s = new Salary();
            Prize1 p1 = new Prize1();
            Prize2 p2 = new Prize2();
            Prize3 p3 = new Prize3();
            Command c = new ConcreteCommand(s);
            Invoker i = new Invoker();
            i.SetCommand(c);
            Console.WriteLine("基本工资:" + i.ExecuteCommand());
            c = new ConcreteCommand(p1);
            i.SetCommand(c);
            Console.WriteLine("奖金1:" + i.ExecuteCommand());
            c = new ConcreteCommand(p2);
            i.SetCommand(c);
            Console.WriteLine("奖金2:" + i.ExecuteCommand());
            c = new ConcreteCommand(p3);
            i.SetCommand(c);
            Console.WriteLine("奖金3:" + i.ExecuteCommand());
            Console.Read();
        }
    }    abstract class Command
    {
        protected Receiver _receiver;        public Command(Receiver receiver)
        {
            this._receiver = receiver;
        }        abstract public string Execute();
    }    class ConcreteCommand : Command
    {
        public ConcreteCommand(Receiver receiver)
            : base(receiver)
        {
        }        public override string Execute()
        {
            return base._receiver.Action();
        }
    }    class Invoker
    {
        private Command _command;        public void SetCommand(Command cmd)
        {
            this._command = cmd;
        }        public string ExecuteCommand()
        {
            return this._command.Execute();
        }
    }    class Receiver
    {
        public virtual string Action()
        {
            return "执行命令";
        }
    }    class Salary : Receiver
    {        public override string Action()
        {
            return "1000";
        }
    }    class Prize1 : Receiver
    {        public override string Action()
        {
            return "500";
        }
    }    class Prize2 : Receiver
    {        public override string Action()
        {
            return "400";
        }
    }    class Prize3 : Receiver
    {        public override string Action()
        {
            return "300";
        }
    }
}

解决方案 »

  1.   

    有没有UML图?这样理解起来就会好很多。
      

  2.   

    首先,纠正lz一个问题,你应该使用Receiver类型,而不是具体的命令类型,否则Command就没有意义了。Receiver s = new Salary();
    Receiver p1 = new Prize1();
    Receiver p2 = new Prize2();
    Receiver p3 = new Prize3();下面用C#来改写这个程序。第一步,Command是没有用的,因为C#支持委托,委托事实上就是这样一个类,它可以封装某一种类型的方法调用。为了保持和lz例子的一致,我仍然将这个委托称之为 Invoker下面是代码:using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Receiver s = new Salary();
                Receiver p1 = new Prize1();
                Receiver p2 = new Prize2();
                Receiver p3 = new Prize3();
                Invoker i = new Invoker(s.Action);
                Console.WriteLine("基本工资:" + i.Invoke());
                i = new Invoker(p1.Action);
                Console.WriteLine("奖金1:" + i.Invoke());
                i = new Invoker(p2.Action);
                Console.WriteLine("奖金2:" + i.Invoke());
                i = new Invoker(p3.Action);
                Console.WriteLine("奖金3:" + i.Invoke());
            }
        }    delegate string Invoker();    interface Receiver
        {
            string Action();
        }    class Salary : Receiver
        {
            public string Action()
            {
                return "1000";
            }
        }    class Prize1 : Receiver
        {
            public string Action()
            {
                return "500";
            }
        }    class Prize2 : Receiver
        {
            public string Action()
            {
                return "400";
            }
        }    class Prize3 : Receiver
        {
            public string Action()
            {
                return "300";
            }
        }
    }
      

  3.   

    本帖最后由 caozhy 于 2011-04-22 22:42:55 编辑
      

  4.   


    这里的代码只是用来作为模式的演示.你当然能简化,哈哈试想一下,当作为实际代码的时候你还能这样简化吗?稍晚来回,今天遇到个很悲剧的事,电脑崩拉,现在连输入法都没有而且崩的莫名其妙,但是我怀疑多半是盗版win7引起的,开始是总莫名其妙的重启今天鬼火了,准备装回xp,进入dos>>fdisk的时候看到有个100m的分区,不知道是啥玩意,觉得奇怪,就把这分区给干掉了,结果所有分区全部消失,我x.....全电脑所有数据丢失,写了20多天的个私活也没了,下周末就要交测试,真想把电脑砸了,鸟微软,鸟宏基
      

  5.   

    到此为止,你的数据几乎可以100%恢复出来,
    挂在别的机器上,启动时跳过checkDisk,然后使用常见的恢复软件,如R-Studio(对于楼主的情况首选此软件)或者FinalData
      

  6.   

    可以。因为我只是去掉了C#语言和框架库实现的部分。Command命令的核心价值就是将调用者和命令实现解耦。
    原来是
    调用者-〉具体的命令
    使用了命令模式就是
    调用者-〉命令-〉具体的命令。讲解一个真实的使用命令模式的场合:这个例子来源于3年前我做过的一个项目我设计了一套插件系统的框架,这个框架实现了依赖翻转的插件系统。它拥有一个主界面,主界面包括菜单、工具条等一系列元素,同时包括一个客户区。还包括若干的模块。每个功能被放入单独的dll中。靠配置文件和反射被主程序调用。每个插件必须向主程序提供一个描述信息表:FeatureList.Add("命令名", "说明文字", CommandDelegate(this.InitFeature));主程序根据这样的清单去创建菜单和导航面板,为菜单产生响应事件。当菜单被触发的时候,很自然地就会调用命令,最后传导到插件。你可以看到,插件的设计者提供命令,但是他不知道这个命令会和主菜单的一个菜单项关联,还是和导航面板的一个链接关联。框架装配命令,它不调用它,只是把命令和控件的事件处理程序关联了起来。主程序则很自然地调用了被组织好的命令,它不知道这个命令隶属于哪个插件,调用了这个插件的哪个方法。那么你的程序是如何实现这个思想的呢?其实你的Main()函数干了两件事情,一个是框架库的职责,SetCommand负责装配,而ExecuteCommand相当于界面。定义的那些Command相当于插件。我的简化程序仍然保持了他们的职责关系。lambda 表达式相当于插件,定义了具体命令要做的事情。那些静态的委托成员相当于框架库,把命令方法装配到这些成员中去。主程序相当于界面。所以简化的版本仍然是Command模式,并且更好地去除了不相干的东西,留下了Command的本质。
      

  7.   

    本帖最后由 caozhy 于 2011-04-23 02:58:25 编辑
      

  8.   

    虽然我没学过C#,只学过C语言,但这个学期有教java,感觉跟java很相似,我学习了,谢谢楼主
      

  9.   

    还有,版主说 我让他帮我写代码,
    实话说,版主你写的代码,对我没有参考价值,而且我用的是 VS2005,
    看到这样的代码:
                Invoker i = new Invoker(s);
                Console.WriteLine("基本工资:" + i.Invoke());
                i = new Invoker(p1);
                Console.WriteLine("奖金1:" + i.Invoke());
                i = new Invoker(p2);
                Console.WriteLine("奖金2:" + i.Invoke());
                i = new Invoker(p3);
                Console.WriteLine("奖金3:" + i.Invoke());我是不想笑都不行了,难道工资项目都得固化在程序里面么?
      

  10.   

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;namespace ConsoleApplication1
    {
        class Program
        {
            delegate string Invoker();        static Invoker Salary = () => "1000";
            static Invoker Prize1 = () => "500";
            static Invoker Prize2 = () => "400";
            static Invoker Prize3 = () => "300";        static void Main(string[] args)
            {
                Console.WriteLine("基本工资:" + Salary());
                Console.WriteLine("奖金1:" + Prize1());
                Console.WriteLine("奖金2:" + Prize2());
                Console.WriteLine("奖金3:" + Prize3());
            }
        }
    }
      

  11.   

    被 caozhy简化后的程序,要是不联系到楼主的发的程序,估计没有几个人能看出他是在做命令模式。简化的很好,但有点误导人。
      

  12.   

    看了前面人不停的简化,再简化,思想固然是好的,但有些东西,切屏蔽掉了命令模式的原理在C#中delegate虽然能很好的处理了命令模式的基础,但也掩盖了真相讨论技术的目的是明白模式的原理,用的时候可能是技巧,也可能是工具
      

  13.   

    在这并没有分析出命令模式来,只是强行的套概念。在http://blog.csdn.net/CShareMySide/archive/2011/04/24/6348897.aspx上有分析,欢迎指正
      

  14.   

    在这并没有分析出命令模式来,只是强行的套概念。在http://blog.csdn.net/CShareMySide/archive/2011/04/24/6348897.aspx上有分析,欢迎指正