每天一个设计模式(策略模式 -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年工作经验,思想达到这个层次了 在深圳可以卖多少钱
准备找工作的说
[解决办法]
[解决办法]
[解决办法]
- 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"]);
[解决办法]
不错,支持楼主坚持写下去