zoukankan      html  css  js  c++  java
  • 设计模式----抽象工厂

    今天,我们接着来说说设计模式中的抽象工厂模式,继上次工厂模式之后我们来说说他们中的大佬抽象工厂。

    首先,还是想象一个场景,今天我们用到的是我们项目中经常要用的切换数据库;

    例如,一开始项目用的是mysql数据库,后来又要切换成SQLserver数据库

    今天,我们就用这个场景来学习一下反射+抽象工厂模式。

    使用的dataBase优先的话我们当然是在项目中新建实体了

    class DepartMent
        {
            private int _id;
            public int ID
            {
                get { return _id; }
                set { _id = value; }
            }
            private string name;
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
        }
    class User
        {
            private int _id;
            public int ID
            {
                get { return _id; }
                set { _id = value; }
            }
            private string name;
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
        }

    这里我们新建两个实体,UserDepartMent,各有Id和Name两个属性,就是这么简单。

    然后接下来我们要干嘛呢(^_^),当然是抽象啦,设计模式怎么少得了抽象呢

    实体嘛,无非就是CRUD,所以我们就抽象他们

    interface IDepartment
        {
            void Insert(DepartMent departMent);
            DepartMent GetDepart(int id);
        }

    这里我们抽象出两个方法,获取对象和添加对象方法,细心的你应该会发现这里是写死的,我们的项目中,不可能只有一个表的吧,按照这种写法的话那岂不是每个表都要新建一个类吗,那岂不是类型数量要爆炸啊(汗颜)

    这里我们不急,我们首先看一个是怎么实现的,学会了一个,其他还不是一样的道理吗(搬砖),接下来就是要去实现了

    class AccessDepartment : IDepartment
        {
            public DepartMent GetDepart(int id)
            {
                Console.WriteLine("在Access中根据ID得到Department表一条记录");
                return null;
            }
    
            public void Insert(DepartMent departMent)
            {
                Console.WriteLine("在Access中给Department表增加一条记录");
            }
        }
    class SqlserverDepartment : IDepartment
        {
            public DepartMent GetDepart(int id)
            {
                Console.WriteLine("在SQL server中根据ID得到DepartMent表一条记录");
                return null;
            }
    
            public void Insert(DepartMent departMent)
            {
                Console.WriteLine("在SQL server 中给DepartMent表增加一条记录");
            }
        }

    这里我们新建了两个类,分别代表access数据库和SQLserver数据库,分别实现IDepartment接口,好了,实现了抽象接口,接下来就是创建了

    class DataAccess
        {
            private static readonly string AssemblyName = "抽象工厂模式";
            private static readonly string db = ConfigurationManager.AppSettings["DB"];
    
            public static IDepartment CreateDepartment()
            {
                string className = AssemblyName + "." + db + "Department";
                return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);
            }
    }

    创建一个DataAccess类,这里要解释下,首先AssemblyName这个属性是我们的命名空间,也就是我们的程序集名称,然后db是我们写在app.config配置文件中的数据库名称

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="DB" value="Sqlserver"/>
      </appSettings>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
        </startup>
    </configuration>

    当你想要切换数据库的时候,我们只需要修改这里的value值就可以达到切换数据库的功能,不用修改任何代码,是不是感觉有些小兴奋呢

    CreateDepartment方法中className是用来组合我们要创建的类的名称,然后通过反射去动态的创建

    最后,我们看看如何调用它

    class Program
        {
            static void Main(string[] args)
            {
    
                DepartMent departMent = new DepartMent();
    
    
                IDepartment id = DataAccess.CreateDepartment();
                id.Insert(departMent);
                id.GetDepart(1);
             }
         }

    实例化一个DepartMent实体,然后我们通过DataAccess类中的CreateDepartment方法去创建IDepartment,实际上我们创建的是SqlserverDepartment类,创建完成之后就可以使用方法执行数据库操作了

    到这里,一个实体我们就学完了,前面我们说了项目中我们不会是一个实体,有很多个实体,那怎么办呢(看代码)

    interface IUser<T>
        {
            void Insert(T user);
            T GetUser(int id);
        }

    我们可以抽象一个泛型接口IUser(这里名字不重要,只是我们前面写了User实体,所以借用一下),然后我们实现它

    class SqlserverUser:IUser<User>
        {
            public void Insert(User user)
            {
                Console.WriteLine("在SQL server 中给User表增加一条记录");
            }
    
            public User GetUser(int id)
            {
                Console.WriteLine("在SQL server中根据ID得到User表一条记录");
                return null;
            }
    
            public string GetTypeName(User t)
            {
                throw new NotImplementedException();
            }
        }
    class AccessUser : IUser<User>
        {
            public User GetUser(int id)
            {
                Console.WriteLine("在Access中根据ID得到User表一条记录");
                return null;
            }
    
            public void Insert(User user)
            {
                Console.WriteLine("在Access中给User表增加一条记录");
            }
        }

    同样是accessSQLserver各自实现,这里我们用User来做例子,你也可以用Depart或者其他来,这样是不是就解决了呢,然后依葫芦画瓢

      public static T CreateUser<T>()
            {
                string Name = typeof(T).GenericTypeArguments[0].Name;
                string className = AssemblyName + "." + db + Name;
                return (T)Assembly.Load(AssemblyName).CreateInstance(className);
            }

    我们在DataAccess类中添加一个方法CreateUser<T>泛型方法,这里Name是获取传入的参数类型的名称,然后同样是组合程序集名称通过反射创建

    同样,我们来看看如何使用

    User user = new User();
                IUser<User> iu = DataAccess.CreateUser<IUser<User>>();
                iu.Insert(user);
                iu.GetUser(1);

    这里实例化一个User对象,然后同样的道理通过DataAccess类的CreateUser泛型方法去创建,这里我们实际创建的是SqlserverUser类,如果你想创建AccessUserAccessDepartment类,可以修改我们之前在app.config配置文件中的SQLserver修改成Access,然后运行程序看看它实现的方法吧,这里就不再多说,留给你们去实现了。这里我们其实是通过名称来区分数据库的,其实只是为了说明反射的用法。好了,反射+抽象工厂就说到这了

  • 相关阅读:
    《DSP using MATLAB》Problem 6.17
    一些老物件
    《DSP using MATLAB》Problem 6.16
    《DSP using MATLAB》Problem 6.15
    《DSP using MATLAB》Problem 6.14
    《DSP using MATLAB》Problem 6.13
    《DSP using MATLAB》Problem 6.12
    《DSP using MATLAB》Problem 6.11
    P1414 又是毕业季II
    Trie树
  • 原文地址:https://www.cnblogs.com/liuhuimh/p/10631102.html
Copyright © 2011-2022 走看看