1.反射
“到底如何去改良策略模式呢?”小菜恳切地问道。
“你仔细观察过没有,你的代码,不管是用工厂模式写的,还是用策略模式写的,那个分支的 switch 依然去不掉。 原因在哪里?”大鸟反问道。
“因为程序里有下拉选择,用户是有选择的,那么程序就必须要根据用户的选择来决定实例化哪一个子类对象。 无论是在客户端窗体类编程还是到工厂类里编程,这个 switch 总是少不掉的。问题主要出在这里。”小菜十分肯定的说。
“是呀,”大鸟道,“所以我们要考虑的就是可不可以不在程序里写明‘如果是打折就去实例化 CashRebate 类,如 果是返利就去实例化 CashReturn 类’这样的语句,而是在当用户做了下拉选择后,再根据用户的选择去某个地方找应 该要实例化的类是哪一个。这样,我们的 switch 就可以对它说再见了。”
“听不太懂哦,什么叫‘去某个地方找应该要实例化的类是哪一个’?’小菜糊涂地说。 “,我要说的就是一种编程方式:依赖注入(Dependency Injection),从字面上不太好理解,我们也不去管它。关 键在于如何去用这种方法来解决我们的 switch 问题。
本来依赖注入是需要专门的 IoC 容器提供,比如 spring.net,显然 当前这个程序不需要这么麻烦,你只需要再了解一个简单的.net 技术‘反射’就可以了。” “大鸟,你一下子说出又是‘依赖注入’又是‘反射’这些莫名其妙的名词,我有点晕哦!”小菜有些犯困,“我 就想知道,如何向 switch 说 bye-bye!至于那些什么概念我不想了解。” “心急讨不了好媳妇!你急什么?”大鸟嘲笑道,“反射技术看起来很玄乎,其实实际用起来不算难。”
“请看下面的两个样例:
1//实例化方法一
2//原来我们把一个类实例化是这样的
3Animal animal=new Cat(); //声明一个动物对象,名称叫 animal,然后将 animal 实例化成猫类的对象
4
5//实例化方法二
6//我们还可以用反射的办法得到这个实例
7using System.Reflection;//先引用 System.Reflection
8//假设当前程序集是 AnimalSystem,名称空间也是 AnimalSystem
9Animal animal = (Animal)Assembly.Load("AnimalSystem").CreateInstance("AnimalSystem.Cat"); 其中关键是 Assembly.Load("程序集名称").CreateInstance("名称空间.类名称")
那也就是说,我们可以在实例化的时候,再给计算机一个类的名称字符串,来让计算机知道应该实例化哪一个类。”大 鸟讲解道。
“ 你 的 意 思 是 , 我 之 前 写 的 ‘ cc.setBehavior(new CashNormal()); ’ 可 以 改 写 为 ‘cc.setBehavior((CashSuper)Assembly.Load("商场管理软件").CreateInstance("商场管理软件.CashNormal")’,不过,这只 不过是换了种写法而已,又有什么神奇之处呢?”小菜依然迷茫。 “分析一下,原来 new CashNormal()是什么?是否是写死在程序里的代码,你可以灵活更换吗?”大鸟问。 “不可以,那还换什么,写什么就是什么了呗。”
“那你说,在反射中的 CreateInstance("商场管理软件.CashNormal"),可以灵活更换‘CashNormal’吗?”大鸟接 着问。 “还不是一样,写死在代码…………等等,哦!!!我明白了。”小菜一下子顿悟过来,,兴奋起来。“因为这里是字 符串,可以用变量来处理,也就可以根据需要更换。哦,My God!太妙了!”
客户端主要代码: