• 设计模式----抽象工厂


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

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

    例如,一开始项目用的是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,然后运行程序看看它实现的方法吧,这里就不再多说,留给你们去实现了。这里我们其实是通过名称来区分数据库的,其实只是为了说明反射的用法。好了,反射+抽象工厂就说到这了

  • 相关阅读:
    C# WinForm 只允许运行一个实例
    C# WinForm 获得文字的像素宽度
    Windows 下使用命令行升级 Npm 和 NodeJS
    每日踩坑 2020-04-15 C# 与 Java 对应 DES 加密算法
    robot自动化测试(二)--- template使用
    robot自动化测试(一)---安装
    linux io优化
    python 远程统计文件
    编程类学习资料整合,更多干货
    两份安卓学习资料,我建议你看完
  • 原文地址:https://www.cnblogs.com/liuhuimh/p/10631102.html
Copyright © 2020-2023  润新知