使用静态类工厂,动态实例化类

.Net技术 码拜 9年前 (2015-03-19) 1155次浏览 0个评论
 

为了实现动态实例化类的效果,写了个类似如下功能的静态方法
public static A createA(int  type)
        {
            switch (type)
            {
                case 1:
                    return new Aa();
                case 2:
                    return new Ab();
                default:
                    return new A();
            }
        }
使用静态类工厂,不需要实例化,调用比较方便,但添加新产品后这个类是经常要更改的,使用静态类似乎不妥,不知大家都是怎么处理这种问题的?

 
使用静态类工厂,动态实例化类
方法就是控制反转:
1. 使用代码注册,用代码向工厂注册对象的键和对象的创建过程,这样有新的东西时工厂不用改,只是多一条注册语句。
2. 使用配置文件注册,工厂使用配置文件的定义,动态创建对象。这样有新的东西时工厂同样不用改,只是多一条配置。
3. IoC/DI框架,主流框架同时支持上面两种方式,工厂也不用写了。
使用静态类工厂,动态实例化类
pre class=”brush: csharp”>
interface IHandler { }
    class AHandler : IHandler
    {
        public void Hello()
        {
            MessageBox.Show(“Hello Jimmy”);
        }
    }
public static IHandler CreateHandler(string ClassName)
         {
            IHandler handler = (IHandler) System.Activator.CreateInstance(typeof(ClassName));
eturn handler;
         }
/pre>
调用的时候
pre class=”brush: csharp”>IHandler h = CreateHandler(“xxxx”);
            AHandler ah = h as AHandler;
/pre>
/div>
使用静态类工厂,动态实例化类
随便给你搜了个网页,可以参考一下:http://www.360doc.com/content/10/1206/14/16915_75504826.shtml
使用静态类工厂,动态实例化类
15分
或者参考这个更好一些:
a href=”http://blog.csdn.net/st_kalecgos/article/details/20791649″ target=”_blank”>http://blog.csdn.net/st_kalecgos/article/details/20791649
a href=”http://ywjwest.blog.163.com/blog/static/11923417820112131143869/” target=”_blank”>http://ywjwest.blog.163.com/blog/static/11923417820112131143869/
/div>
使用静态类工厂,动态实例化类
简单来说,假设需要编写一个工厂方法返回 A子类对象(这个类型是“以后”才扩展的),那么你可以写

public static class MyFactory
{
        public static A CreateInstance()
         {
             string cfg= ConfigurationManager.AppSettings["provider_A"].ToString();
             string[] cfs = cfg.Split(",");    //用逗号前边为类型名称(包含命名空间),逗号后边为Assembly名称
       Assembly asm = Assembly.Load(cfs[1]);
            Type t = asm.GetType(cfs[0]);
            return (A)System.Activator.CreateInstance(t);
         }
}
/pre>
使用静态类工厂,动态实例化类
15分
我给你写个通过代码注册的吧:
pre class=”brush: csharp”>
使用方法如下:
// 按照程序集里面类型的MyClassAttribute自动注册
MyFactory.RegisterAssembly(Assembly.GetExecutingAssembly());
// 手动注册
MyFactory.Register(“c”, () => new MyClassC());
// 按key创建对象
var a = MyFactory.Create(“a”);
var b = MyFactory.Create(“b”);
var c = MyFactory.Create(“c”);
// 打印检查下具体类型
Console.WriteLine(a.GetType().Name);
Console.WriteLine(b.GetType().Name);
Console.WriteLine(c.GetType().Name);
代码:
public interface IMyInterface { }
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class MyClassAttribute : Attribute
{
    public string Key { get; private set; }
    public MyClassAttribute(string key)
    {
        Key = key;
    }
}
[MyClass(“a”)]
public class MyClassA : IMyInterface { }
[MyClass(“b”)]
public class MyClassB : IMyInterface { }
public class MyClassC : IMyInterface { }
public class MyFactoryBase<T>
{
    private static Dictionary<string, Func<T>> s_funcs = new Dictionary<string, Func<T>>();
    public static void Register(string key, Func<T> createFunc)
    {
        s_funcs[key] = createFunc;
    }
    public static void RegisterAssembly(Assembly a)
    {
        foreach (var type in a.GetTypes().Where(t => t.IsPublic && t.IsClass && !t.IsAbstract && typeof(T).IsAssignableFrom(t)))
        {
            var attr = Attribute.GetCustomAttribute(type, typeof(MyClassAttribute)) as MyClassAttribute;
            if (attr != null)
            {
                var t = type;
                Register(attr.Key, () => (T)Activator.CreateInstance(t));
            }
        }
    }
    public static T Create(string key)
    {
        return s_funcs[key]();
    }
}
public class MyFactory : MyFactoryBase<IMyInterface>
{
    
}
/pre>
这代码我没写任何检查。关于Activator.CreateInstance,这个东西比较慢,如果要这样创建大量对象,可以用表达式编译优化,这里就不写了。
可以看到,使用时如果有新的类,那么加一个手动注册,或者加个attribute让它自动注册。factory本身是不需要改的。
使用静态类工厂,动态实例化类
泛型方法
public static A create<T>() where T:A
当然ioc是极好的
使用静态类工厂,动态实例化类
引用 楼主 u010412702 的回复:

为了实现动态实例化类的效果,写了个类似如下功能的静态方法
public static A createA(int  type)
        {
            switch (type)
            {
                case 1:
                    return new Aa();
                case 2:
                    return new Ab();
                default:
                    return new A();
            }
        }
使用静态类工厂,不需要实例化,调用比较方便,但添加新产品后这个类是经常要更改的,使用静态类似乎不妥,不知大家都是怎么处理这种问题的?

可以考虑IOC的方式,用抽象 +  反射实现。
程序分为:调用,定义,生成 3个部分。
调用端不管。
定义部分包含工厂和生成A的接口定义。工厂用抽象的A作为返回值,工厂使用反射来创建A或A的派生类。生成A的接口定义了生成部分需要实现的创建方法,返回值是A。
生成部分实现生成A接口。然后,在配置文件里指定生成部分的DLL和类。工厂根据这个配置信息得到A或者A的派生类。由于接口关系,生成部分是可扩展的,不管派生出A的什么子类,只要实现接口方法,返回值是A就行。


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明使用静态类工厂,动态实例化类
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!