根据类名创建实例
Source Code 最近有人问我一个问题,就是如何根据传入的字符串,由父类生成不同的子类。当然,肯定是不希望用switch语句了,也不希望每次创建instance时,都使用reflection。我觉得解决这个问题,应该使用工厂方法来处理。解释一下自己的code,如果有更好的方法,或者有什么可以改进的地方,还望请各位不吝赐教。
Shape class 的Create调用ShapeFactory返回一个Shape class
CreateShape根据传入到shape,使用反射创建一个ShapeFactory的instance,但是只创建一次,并且使用double check来保证多线程安全。所以这里的反射只会在需要的ShapeFactory不存在的时候才会创建,所以只是在第一次创建想要的shape时,才会使用到反射,以后都是直接使用instance
WinShape project: (class library)
window application:
Form1.Design.cs
Form1.cs
Shape class 的Create调用ShapeFactory返回一个Shape class
CreateShape根据传入到shape,使用反射创建一个ShapeFactory的instance,但是只创建一次,并且使用double check来保证多线程安全。所以这里的反射只会在需要的ShapeFactory不存在的时候才会创建,所以只是在第一次创建想要的shape时,才会使用到反射,以后都是直接使用instance
WinShape project: (class library)
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace WinShape
{
public abstract class Shape
{
public abstract string Draw();
public static Shape Create(string name)
{
return ShapeFactory.CreateShape(name);
}
}
public class Line : Shape
{
public override string Draw()
{
return "Draw Line: -----------------";
}
}
public class Circle : Shape
{
public override string Draw()
{
return "Draw Circle: OOOOOOOOOOOOOOOO";
}
}
public class Triangle : Shape
{
public override string Draw()
{
return "Draw Triangle: ^^^^^^^^^^^^^^";
}
}
internal abstract class ShapeFactory
{
private static Dictionary<string, ShapeFactory> factories = new Dictionary<string, ShapeFactory>();
protected abstract Shape GetShape();
internal static Shape CreateShape(string shapeName)
{
//double check to prevent create multiple instances by multiple threads
if(!factories.ContainsKey(shapeName))
{
lock (factories)
{
if (!factories.ContainsKey(shapeName))
{
Assembly assembly = Assembly.GetExecutingAssembly();
Type t = assembly.GetType(string.Format("WinShape.ShapeFactory+{0}Factory", shapeName));
if (t == null)
return null;
ShapeFactory factory = System.Activator.CreateInstance(t) as ShapeFactory;
factories.Add(shapeName, factory);
}
}
}
ShapeFactory fac = factories[shapeName];
return fac.GetShape();
}
private class LineFactory : ShapeFactory
{
protected override Shape GetShape()
{
return new Line();
}
}
private class CircleFactory : ShapeFactory
{
protected override Shape GetShape()
{
return new Circle();
}
}
private class TriangleFactory : ShapeFactory
{
protected override Shape GetShape()
{
return new Triangle();
}
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace WinShape
{
public abstract class Shape
{
public abstract string Draw();
public static Shape Create(string name)
{
return ShapeFactory.CreateShape(name);
}
}
public class Line : Shape
{
public override string Draw()
{
return "Draw Line: -----------------";
}
}
public class Circle : Shape
{
public override string Draw()
{
return "Draw Circle: OOOOOOOOOOOOOOOO";
}
}
public class Triangle : Shape
{
public override string Draw()
{
return "Draw Triangle: ^^^^^^^^^^^^^^";
}
}
internal abstract class ShapeFactory
{
private static Dictionary<string, ShapeFactory> factories = new Dictionary<string, ShapeFactory>();
protected abstract Shape GetShape();
internal static Shape CreateShape(string shapeName)
{
//double check to prevent create multiple instances by multiple threads
if(!factories.ContainsKey(shapeName))
{
lock (factories)
{
if (!factories.ContainsKey(shapeName))
{
Assembly assembly = Assembly.GetExecutingAssembly();
Type t = assembly.GetType(string.Format("WinShape.ShapeFactory+{0}Factory", shapeName));
if (t == null)
return null;
ShapeFactory factory = System.Activator.CreateInstance(t) as ShapeFactory;
factories.Add(shapeName, factory);
}
}
}
ShapeFactory fac = factories[shapeName];
return fac.GetShape();
}
private class LineFactory : ShapeFactory
{
protected override Shape GetShape()
{
return new Line();
}
}
private class CircleFactory : ShapeFactory
{
protected override Shape GetShape()
{
return new Circle();
}
}
private class TriangleFactory : ShapeFactory
{
protected override Shape GetShape()
{
return new Triangle();
}
}
}
}
window application:
Form1.Design.cs
private System.Windows.Forms.Button btnCreate;
private System.Windows.Forms.ComboBox cmbClassNames;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.ComboBox cmbClassNames;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using WinShape;
namespace CreateInstanceByClassName
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnCreate_Click(object sender, EventArgs e)
{
if (this.cmbClassNames.SelectedIndex < 0)
return;
string shapeName = this.cmbClassNames.Items[this.cmbClassNames.SelectedIndex].ToString();
Shape shape = Shape.Create(shapeName);
if (shape != null)
this.textBox1.Text = shape.Draw();
else
this.textBox1.Text = "Null Reference";
}
private void Form1_Load(object sender, EventArgs e)
{
Assembly assembly = Assembly.Load("WinShape");
Type shapeType = assembly.GetType("WinShape.Shape");
Type[] types = assembly.GetTypes();
foreach (Type t in types)
{
if (t.IsSubclassOf(shapeType) && !t.IsAbstract)
{
this.cmbClassNames.Items.Add(t.Name);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
Application.Exit();
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using WinShape;
namespace CreateInstanceByClassName
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnCreate_Click(object sender, EventArgs e)
{
if (this.cmbClassNames.SelectedIndex < 0)
return;
string shapeName = this.cmbClassNames.Items[this.cmbClassNames.SelectedIndex].ToString();
Shape shape = Shape.Create(shapeName);
if (shape != null)
this.textBox1.Text = shape.Draw();
else
this.textBox1.Text = "Null Reference";
}
private void Form1_Load(object sender, EventArgs e)
{
Assembly assembly = Assembly.Load("WinShape");
Type shapeType = assembly.GetType("WinShape.Shape");
Type[] types = assembly.GetTypes();
foreach (Type t in types)
{
if (t.IsSubclassOf(shapeType) && !t.IsAbstract)
{
this.cmbClassNames.Items.Add(t.Name);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
Application.Exit();
}
}
}
posted on 2007-07-11 14:44 redpeachsix 阅读(2636) 评论(14) 编辑 收藏 举报