根据类名创建实例

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)   
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();
            }

        }


    }


    
    
}


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;

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();
        }

    }

}


posted on 2007-07-11 14:44  redpeachsix  阅读(2636)  评论(14编辑  收藏  举报

导航