利用设计模式可以使我们的代码更灵活,更容易扩展,更容易维护。各种面向对象的程序设计语言都提供了基本相同的机制:比如类、继承、派生、多态等等。但是又有各自的特色,C# 中的反射机制便是一个很重要的工具,好好地利用就可以在实际中发挥很大的作用。
我们来看一个例子:
我的程序中有需要一系列的对象,比如apple,orange…, 要想利用他们,我们就必须在程序中根据用户要求,然后一个个调用 new 操作符来生成他们,这样客户程序就要知道相应的类的信息,生成的代码显然不够灵活。我们可以在代码中不利用具体的类,而只是说明我们需要什么,然后就能够得到我们想要的对象吗?
好吧抽象工厂,我们看看吧,“提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类”,至少“无需指定它们具体的类”
符合我们的要求。来看看它的结构吧:
我们的问题好像用不到这么复杂吧,只有orange,apple 等等,他们显然是一类的,都是fruit,我们只要一个生产水果的工厂就可以,看看下面的代码,先别管它正统不正统,实用就行
我们的FruitFactory 应该是怎么样呢?我就MakeOrange
怎么使用这个工厂呢?我们来写下面的代码:
编译运行,然后在控制台输入想要的东西,呵呵,成功了。沉浸在幸福中的你得意忘
形了吧。
不过等等,它好像还不完美,我如果想要pear,我既要在客户代码中的switch中加入
判断,又要在工厂方法中加入MakePear 方法,好像不怎么优雅。更好一点,在工厂中只提
供一个方法,MakeFruit,然后传递进一个参数Name,代表我们想要的水果的名称,这样的
话,似乎我们的客户代码中的那个switch就可以不要了,相反,在FruitFactory中好像需要
一个,还等什么呢?实现吧。
FruitFactory:
客户代码:
这样看起来好多了,至少我客户代码中不要再写那么一长串的判断代码了。
阿Q 精神又在起作用,我们又沉浸在成功的喜悦中了。 嗯,代码好像可以,应该没
有什么改进了。但是好像又有另外一个声音在说:
“除了一点……”
“嗯? 等等,什么?”
“FruitFactory也有switch啊,看起来也ugly啊!”
“哼,肯定是看《重构》或者是《TDD》了,怎么要求那么苛刻!反正闲着也是闲着,
看看可以改不?”
既然不要条件判断,传入的只有水果的名称,假如Name = “Apple”,要生成一个Apple
的对象,我需要new Apple(),如果我能够这样多好: new MakeItToClass(Name),把字符串
转换成一个类。C#中虽然没有上述语法,但是提供了相应的机制,那就是反射。其中一个
重要的类就是System.Type类,它对于反射起着核心的作用。我们可以使用 Type 对象的方
法、字段、属性和嵌套类来查找有关该类型的所有信息。
另外一个重要的类就是System.Activator,它包含特定的方法,用以在本地或从远程创
建对象类型,或获取对现有远程对象的引用。
我们可以先利用Type 类获取Name 指定的类名的类的Type 信息,然后可以根据这个
信息利用Activator 创建对象。还等什么呢?
过这样的处理以后,增加新的水果的时候,我们不需要修改客户代码了,同时工厂
的代码也不需要修改了,怎么样,爽吧!