读书人

每日一个设计模式(策略模式 -2011.4.1

发布时间: 2011-12-23 23:32:01 作者: rapoo

每天一个设计模式(策略模式 -2011.4.18 星期一)期待提问和讨论
在昨天的帖子里用简单工厂模式的方法实现了一个简单的计算功能
有同修积极回帖并提出用 策略模式 来实现更为适合
所以今天的模式就用策略模式实现昨天的计算功能

C# code
namespace 策略模式{    //抽象算法类    abstract class Operation    {        private double _leftNum;        public double LeftNum        {            get { return _leftNum; }            set { _leftNum = value; }        }        private double _rightNum;        public double RightNum        {            get { return _rightNum; }            set { _rightNum = value; }        }        public double GetResult();    }    //具体算法1 继承抽象算法类    public class OperationAdd : Operation    {        public override double GetResult()        {            double result = 0;            result = LeftNum + RightNum;            return result;        }    }    public class OperationSub : Operation    {        public override double GetResult()        {            double result = 0;            result = LeftNum + RightNum;            return result;        }    }    public class OperationMul : Operation    {        public override double GetResult()        {            double result = 0;            result = LeftNum * RightNum;            return result;        }    }    public class OperationDiv : Operation    {        public override double GetResult()        {            double result = 0;            if (LeftNum == 0)            {                throw new Exception("除数不能为 0。");            }            result = LeftNum / RightNum;            return result;        }    }    public class OperationSqr : Operation    {        public override double GetResult()        {            double result = 0;            result = LeftNum * LeftNum;            return result;        }    }    public class OperationSqrt : Operation    {        public override double GetResult()        {            double result = 0;            if (LeftNum == 0)            {                throw new Exception("负数不能开平方根。");            }            result = Math.Sqrt(LeftNum);            return result;        }    }    public class OperationReverse : Operation    {        public override double GetResult()        {            double result = 0;            result = -LeftNum;            return result;        }    }    //上下文,用来维护一个对 算法 的引用    public class Context    {        Operation _op;        public Context(Operation op)        {            _op = op;        }        public void ContextInterface()        {            _op.GetResult();        }    }}


策略模式特点:定义算法家族,分别封装,互相可以替换,让算法的变化不影响使用算法的客户(代码)

可以看出策略模式和简单工厂模式非常的相似

最明显的区别的工厂模式在自己内部判断应该实例化哪个类

而策略模式把这个工作放到了外部,也就是客户


if(operation=="+")
new conText(new OperationAdd()).ContextInterface();

[解决办法]
这个好像是那个设计模式那本书的
[解决办法]
C#提供了委托和Lambda表达式。所以可以用极其精简的代码实现策略模式。

甚至都看不出来是策略模式(也可以说不用任何模式,但是这样lz不爱听,如同一条线的长度为0,线退化成一个点,但是你也可以称为一条长度为0的线,其实已经没有线了)。

有时间给大家做个演示,如何用C#3和4特有的语法代替大部分设计模式。因为绝大多数人都把C#当作C/C++或者Java的兼容版本来看待C#的,虽然也能写出正确的程序,但是如同外国人说中文一样,有生涩的感觉。

C# code
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication1{    class Program    {        static void Main(string[] args)        {            Console.WriteLine(CalcByBinaryOperator<int>(4, 5, (x, y) => x + y));            Console.WriteLine(CalcByBinaryOperator<float>(4.5f, 5f, (x, y) => x - y));            Console.WriteLine(CalcByBinaryOperator<double>(4f, 0.5f, (x, y) => Math.Pow(x, y)));        }        static T CalcByBinaryOperator<T>(T left, T right, Func<T, T, T> Strategy)        {            return Strategy(left, right);        }    }} 


[解决办法]
这个代码用到了策略模式,为了让你看出它是策略模式,我故意用了Strategy作为参数名。否则恐怕你就看不出来了。

这里Func<T, T, T>相当于是策略的父类,三个Lambda表达式就是三个策略的子类。因为只用到一次,所以名字都不需要了。

注意看这段代码,真的只用到了策略模式么?

其实还用到了Flyweight,在哪里呢?
Console.WriteLine();
这居然就是一个模式!Flyweight,因为装箱和拆箱,这就是不折不扣的享元!也许你第一天写程序根本不懂什么是设计模式,就用到了。

还有呢?还有模板模式,泛型就是C#里的模板模式的实现。
哦,我听到有人批评我了,模板和模板模式是两回事!!!错了,模板是模板模式的特例。不信你去重载泛型类型的运算符,你再看看。

只是让lz体验下,绝大多数的设计模式已经被语言/框架本身实现或者空留下概念而无影无踪。

下面我把程序改一改:

C# code
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication1{    class Program    {        static Action<object> Output = (x) => Console.WriteLine(x);        static void Main(string[] args)        {            CalcByBinaryOperator<int>(4, 5, (x, y) => x + y, Output);            CalcByBinaryOperator<float>(4.5f, 5f, (x, y) => x - y, Output);            CalcByBinaryOperator<double>(4f, 0.5f, (x, y) => Math.Pow(x, y), Output);        }        static T CalcByBinaryOperator<T>(T left, T right, Func<T, T, T> Strategy, Action<object> ToDo)        {            ToDo(Strategy(left, right));            return Strategy(left, right);        }    }}
[解决办法]
学习了!建议 caozhy 写个新版设计模式的系列。
[解决办法]
互相可以替换
我觉得这才是策略的精粹
caozhy提出的 委托+Lambda 可以相互替换吗?
委托+Lambda只是实现了算法
还不达到互相可以替换吧?

感觉 委托+Lambda 是实现,策略的层次比较高

而且我看的是<Head First设计模式>
策略模式位于第一章
里面是为了不要让每个继承接口的子类都去实现接口方法,因为有很多都是相同的
所以把算法封装起来,让子类选择就可以了

但你的 委托+Lambda 貌似有要每个都实现了一次了,如果有很多的话,
如果要修改 鸡鸡疼

随便买一下请教一下,3年工作经验,思想达到这个层次了 在深圳可以卖多少钱
准备找工作的说
[解决办法]
探讨
这个代码用到了策略模式,为了让你看出它是策略模式,我故意用了Strategy作为参数名。否则恐怕你就看不出来了。

这里Func<T, T, T>相当于是策略的父类,三个Lambda表达式就是三个策略的子类。因为只用到一次,所以名字都不需要了。

注意看这段代码,真的只用到了策略模式么?

其实还用到了Flyweight,在哪里呢?
Console.WriteLine();
这居然……

[解决办法]
探讨
互相可以替换
我觉得这才是策略的精粹
caozhy提出的 委托+Lambda 可以相互替换吗?
委托+Lambda只是实现了算法
还不达到互相可以替换吧?

感觉 委托+Lambda 是实现,策略的层次比较高

而且我看的是<Head First设计模式>
策略模式位于第一章
里面是为了不要让每个继承接口的子类都去实现接口方法,因为有很多都是相同的
所以把算法封装起来,让子类……

[解决办法]
C# code
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication1{    class Program    {        static void Main(string[] args)        {            List<Person> list = new List<Person>()            {                new Person() { Name = "张三", Age = 27 },                new Person() { Name = "张四", Age = 21 },                new Person() { Name = "李三", Age = 29 },                new Person() { Name = "李四", Age = 32 },                new Person() { Name = "王五", Age = 36 },                new Person() { Name = "王二", Age = 24 }            };            Console.WriteLine("Before sort:");            list.ForEach(p => Console.WriteLine(p));            list.Sort(new Person.AgeComparer());            Console.WriteLine("After sort:");            list.ForEach(p => Console.WriteLine(p));        }    }    class Person    {        public string Name { get; set; }        public int Age { get; set; }        public override string ToString()        {            return string.Format("{0}({1})", Name, Age);        }        public class AgeComparer : IComparer<Person>        {            public int Compare(Person x, Person y)            {                return x.Age - y.Age;            }        }    }} 


[解决办法]
C#优美
[解决办法]
觉得什么委托、什么策略、什么工厂、什么范型,

都不如Javascript 强大,

C# code
function add(){  int n;  for(int i=0;i<arguments.length;i++){    n+=Tools.toInt(arguments[i]+""); //省略  }}add(1,2,3,4);this.addproperty = "sfsf";this.addproperty1 = "sfsf";this.addproperty2 = "sfsf";alert(this["addproperty"]);
[解决办法]
不错,支持楼主坚持写下去

读书人网 >C#

热点推荐