最近正在看四人帮写的Design Patterns,偶有心得,于是写了一个利用反射实现工厂方法的小程序,这是书里面没有的,也不知道有没有人比我先想到。
工厂方法经常使用参数的方法实现Creator。这里也使用了参数的方法,但是和传统的参数截然不同。
新建一个C#工程,在窗体里面放一个ComboBox,一个Button, 并且在ComboBox的Items属性里面输入MyProduct和YourProduct,我们以后就是通过这两个string来创建对象的。窗体如图所示。将项目的属性中的输出改成控制台应用程序。
然后在Form类的外面输入下面的代码。
public class Creator
{
public static Product CreateProduct(string ProductName)
{
Product product = null;
// 你也可以自己继承Pruduct接口,生成dll,然后在这里加载dll
Assembly a = Assembly.GetCallingAssembly();
// 类的全名
string s = @"ReflectingFactoryMethod." + ProductName;
// 创建对象
object o = a.CreateInstance(s);
// 将对象转化为Pruduct接口
product = o as Product;
return product;
}
}
public class TheirCreator : Creator
{
override public static Product CreateProduct(string ProductName)
{
Product product = null;
// 你也可以自己继承Pruduct接口,生成dll,然后在这里加载dll
Assembly a = Assembly.LoadFile(@"c:/windows/system32/a.dll");
// 类的全名
string s = @"SomeNameSpace." + ProductName;
// 创建对象
object o = a.CreateInstance(s);
// 将对象转化为Pruduct接口
product = o as Product;
return product;
}
}
public interface Product
{
void ShowProduct();
}
public class MyProduct : Product
{
public void ShowProduct()
{
// TODO: 添加 MyProduct.ShowProduct 实现
Console.WriteLine("My Producted");
}
}
public class YourProduct : Product
{
public void ShowProduct()
{
// TODO: 添加 YourProduct.ShowProduct 实现
Console.WriteLine("Your Producted");
}
}
最后在Button的Click事件里面输入下面的代码。
private void button1_Click(object sender, System.EventArgs e)
{
Product product = Creator.CreateProduct(this.comboBox1.Text);
product.ShowProduct();
}
从这里我们可以看到,我们是从 this.comboBox1.Text 来创建对象的,这是一个string。也可以读入另外一个dll,从那里创建对象。
如果我们这样来写Creator类:
public class Creator
{
public static Product CreateProduct()
{
Product product = null;
StreamReader sr = new StreamReader("config.txt");
string AssemblyName = sr.ReadLine();
string NameSpaceName = sr.ReadLine();
string ProductName = sr.ReadLine();
Assembly a = Assembly.LoadFile(AssemblyName);
string s = NameSpaceName + ProductName;
object o = a.CreateInstance(s);
product = o as Product;
return product;
}
}
这个Creator也可以实现刚才的功能,而且不需要写Creator的子类就可以实现功能扩展。只需要继承Product接口,编译成dll,然后适当的修改config.txt配置文件,就可以轻松实现。程序供应商可以只提供Product接口,却不需要提供Creator的接口。客户只需要根据自己的需要继承Product接口,而且不需要更改原有的可执行发布。虽然这个Creator也有一些缺陷,比如对于实现变化特别多的构造函数就比较困难,但是如果是统一的构造函数却能实现无穷的扩展能力。
但是这个Creator却和经典的工厂方法相矛盾了,经典的方法需要编写Creator的子类来实现扩展,而这个Creator却不需要。这个是由于引入了反射造成的。在没有反射这个功能之前,我们必须知道我们需要创建对象的类型,也就是说,在一个特定的Product类出现之前是不可能有一个Creator类能够创建这个类的对象的,而使用了反射的Creator可以创建所有的Product,即使这个Product的出现时间比Creator还要晚。
利用反射实现工厂方法只是第一步,利用反射还可以实现更多的模式。把新鲜技术和公认的经典模式相结合也许会嘣出新的火花。