抽象工厂模式

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的类
该模式优缺点: 最大的好处是易于交换产品系列,由于具体工厂类, 在一个应用中只需要初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它需要在改变具体工厂即可使用不同的产品配置。 它让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的类名被具体的工厂实现分离,不会出现在客户代码中。

个人建议: 在学习该模式前,请先把工厂方法模式看一下,因为抽象工厂可以说是工厂方法的升级版

接下来看题:
一个项目所用的数据库原本是Sqlserver的,但是因为客户需要,所以要改成Access的,数据库中有两个表。 User和Department

先声明两个接口 IUser和IDepartment

Created with Raphaël 2.1.0 SqlserverUser SqlserverUser IUser IUser AccessUser AccessUser SqlserverDepartment SqlserverDepartment IDepartment IDepartment AccessDepartment AccessDepartment 继承 继承 继承 继承
Created with Raphaël 2.1.0 SqlserverFactory SqlserverFactory IFactory IFactory AccessFactory AccessFactory SqlserverUser SqlserverUser AccessUser AccessUser 继承 继承 实例化sqlserver的User和Department 实例化Access的User和Department
  public class User
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

    public class Department 
    {
        public int ID { get; set; }
        public string DeptName { get; set; }
    }

    public interface IDepartment 
    {
        void Insert(Department dept);
        Department GetDepartment(int id);
    }
    public interface IUser 
    {
        void Insert(User user);
        User GetUser(int id);
    }

    public class SqlserverUser :IUser
    {
        public void Insert(User user) 
        {
            Console.WriteLine("在SQL Server中给User表增加一条记录");
        }

        public User GetUser(int id)
        {
            Console.WriteLine("在SQL Server中根据ID 得到User表一条记录");
            return null;
        }
    }

    public class AccessUser : IUser 
    {
        public void Insert(User user)
        {
            Console.WriteLine("在Access中给User表增加一条记录");
        }

        public User GetUser(int id)
        {
            Console.WriteLine("在Access中根据ID 得到User表一条记录");
            return null;
        }
    }


    public class SqlserverDepartment : IDepartment 
    {
        public void Insert(Department dept) 
        {
            Console.WriteLine("向Sql server数据库中往表Department添加一条数据");
        }

        public Department GetDepartment(int id) 
        {
            Console.WriteLine("在Sqlserver 中根据ID 得到Department表一条记录");
            return null;
        }
    }

    public class AccessDepartment : IDepartment 
    {
        public void Insert(Department dept)
        {
            Console.WriteLine("向Access数据库中往表Department添加一条数据");
        }

        public Department GetDepartment(int id)
        {
            Console.WriteLine("在Access 中根据ID 得到Department表一条记录");
            return null;
        }
    }

在Main方法的调用:

    User user = new User();
            Department dept = new Department();

            IFactory factory = new SqlServerFactory();
            IUser suser = factory.CreateUser();
            IDepartment sdept = factory.CreateDepartment();
            suser.Insert(user);
            suser.GetUser(1);
            sdept.Insert(dept);
            sdept.GetDepartment(1);

结果:
这里写图片描述

可能我之前写的抽象模式UML图,大家看的不太懂,这也没办法,CSDN上面我能画成这样的图,也可以了。 为了让大家更清晰的看到模式UML图。我从网上找了一个。 思想方面还是一样的。

这里把Creator想象为IFactory , ProductA为IUser ,ProductB为IDepartment. 请大家自觉脑补。 嘿嘿。
这里写图片描述

这就是抽象工厂模式了,看到这里大家是不是觉得奇怪。(可能有人觉得,这才两个表, 代码就写的这么多了,那要是再多几个表,咋整啊。这模式也太不中用了。 )
别急,接下来,才是重点
解决抽象工厂模式大量冗余代码的方案是 —— 用反射+抽象工厂来处理

反射的写法:
1. using System.Reflection; 引用命名空间
2. IUser result = (IUser)Assembly.Load(AssemblyName).CreateInstance(命名空间.类名); AssemblyName 是程序集名称

这里的SimpleFactory类,用反射技术已经取代了,IFactory、SqlserverFactory 和AccessFactory


//App.cinfg
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="DB" value="Sqlserver"/>
  </appSettings>
</configuration>
 public class SimpleFactory 
    {
        private static readonly string AssemblyName = "AbstractFP";
        private static readonly string db = ConfigurationManager.AppSettings["DB"];
       // IUser result = (IUser)Assembly.Load(AssemblyName).CreateInstance("抽象工厂模式.SqlserverUser");

        public static IUser CreateUser() 
        {
            //获取本类的程序集名称
            string Name = typeof(SimpleFactory).Assembly.GetName().Name;
            string className = AssemblyName + "." + db + "User";
            return (IUser)Assembly.Load(AssemblyName).CreateInstance(className) ;
        }
        public static IDepartment CreateDepartment() 
        {
            string className = AssemblyName + "." + db + "Department";
            return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);
        }
    }

在Main方法中的:

 User u = new User();
            IUser sql = SimpleFactory.CreateUser();
            sql.Insert(u);
            sql.GetUser(1);
            Console.ReadLine();

结果:

这里写图片描述

(欢迎大家来访,如果有不足之处还请指出)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值