设计模式之四(抽象工厂模式第三回合)

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介: 原文:设计模式之四(抽象工厂模式第三回合)前言 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 抽象工厂模式最大的好处便是易于交换产品系列,由于具体工厂类,例如IFactory factory=new AccessFactory(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。
原文: 设计模式之四(抽象工厂模式第三回合)

前言

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

抽象工厂模式最大的好处便是易于交换产品系列,由于具体工厂类,例如IFactory factory=new AccessFactory(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。我们的设计不能去防止需要的变更,那么我们的理想便是让改动变得最小,那么现在如果你要更改数据库访问,我们只需要更改具体工厂就可以做到。

第二大好处是,它让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现而分离,不会出现在客户代码中。

 

实际上,我们第二回合中的代码中,客户端所认识的只有IUser和IDepartment,至于它是用Sql Server来实现还是Access来实现就不知道了。

但是接下来的问题是,如果我们再添加一个项目表Project,该怎么办?

首先要增加三个类,IProject,SqlServerProject,AccessProject,还需要更改IFactory、以及SqlServerFactory和AccessFactory才可以实现。

用简单工厂来改进抽象工厂

现在我们要对上面的关系代码进行整改,需要前面的简单工厂模式。http://www.cnblogs.com/aehyok/archive/2013/05/10/3072008.html

public class DataAccess
{
    private static readonly string  db="SqlServer";
    //private static readonly string db="Access";

    public static IUser CreateUser()
    {
        IUser result=null;
        switch(db)
        {
            case"SqlServer":
                result=new SqlServerUser();
                break;
            case"Access":
                result=new AccessUser();
                break;    
        }
        return result;
    }

    public static IDepartment CreateDepartment()
    {
        IDepartment result=null;
        switch(db)
        {
            case"SqlServer":
                result=new SqlServerDepartment();
                break;
            case"Access":
                result=new AccessDepartment();
                break;
        }
        return result;
    }
}

原先一个接口,两个接口的实现,现在我们用一个DataAccess类就可以来代替了。

客户端调用方法也有所改动

public class Test
{
    public static void Main()
    {
        User user=new User();
        Console.WriteLine("调用开始");
        IUser iu=DataAccess.CreateUser();
        iu.Insert(user);
        iu.GetUser(1);

        Console.ReadLine();
    }
}

现在选择那个数据库是在DataAccess中定义的 private static readonly string  db="SqlServer";
当然更好的办法实在配置文件中进行变动就可以了。

如果如前言中所说 ,添加一个项目,那么我们只需要在DataAccess类中添加雷同的方法即可。

但是还是有问题,前面我们也稍微提到过,比如现在有需求要用Oracle数据库。原来只需要增加OracleFactory工厂就可以了,现在就比较麻烦了。

反射+抽象工厂的数据访问程序

 如果你还不太了解反射,那么可以简单的看一下我之前的一篇入门的反射博文http://www.cnblogs.com/aehyok/archive/2013/03/25/2963287.html

首先使用反射我们需要引用using System.Reflection来引用Reflection,就可以使用反射来优化抽象工厂模式的先天不足。

顺便来看一下反射的简单使用,来获得实例的方法

IUser result = new SqlServerUser();   ///这是常规的写法

接下来看看用反射的写法,别忘了首先要引用哦

IUser result = (IUser)Assembly.Load("程序集的名称").CreateInstance("命名空间.要实例化的类名");

那么现在可以发现用了反射我们可以利用字符串来实例化对象,而变量是可以替换的,而常规的写法都是写死在程序里的。
接下来看看我们用反射优化后的抽象工厂,其实也就是对上面DataAccess类进行的优化。

    public class DataAccess
    {
        private static readonly string db = "SqlServer";
        private static readonly string AssemblyName = "AbstractFactory";

        public static IUser CreateUser()
        {
            string ClassName = AssemblyName+"."+db+"User";
            IUser result = (IUser)Assembly.Load("程序集的名称").CreateInstance("命名空间.要实例化的类名");
            return (IUser)Assembly.Load(AssemblyName).CreateInstance(ClassName);
        }

        public static IDepartment CreateDepartment()
        {
            string ClassName ="AssemblyName"+ "."+db+"Department";
            return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(ClassName);
        }
    }

其实这里我们还可以简单的优化一下,就是用配置文件

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <!--<add key="DB" value="SqlServer"/>-->
    <add key="DB" value="Access"/>
  </appSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
    public class DataAccess
    {
        private static readonly string db = ConfigurationManager.AppSettings["DB"];
        private static readonly string AssemblyName = "AbstractFactory";

        public static IUser CreateUser()
        {
            string ClassName = AssemblyName+"."+db+"User";
            IUser result = (IUser)Assembly.Load("程序集的名称").CreateInstance("命名空间.要实例化的类名");
            return (IUser)Assembly.Load(AssemblyName).CreateInstance(ClassName);
        }

        public static IDepartment CreateDepartment()
        {
            string ClassName ="AssemblyName"+ "."+db+"Department";
            return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(ClassName);
        }

    }

这样需要什么数据库,只需要在配置文件当中进行配置即可。
所以,所有在用简单工厂的地方,都可以考虑用反射来去除switch或if,接触分支判断带来的耦合。

总结

 原来通过抽象工厂可以学到这么多的知识很好,要多多吸收才可以。

最终版本的抽象工厂模式实例代码下载链接为http://url.cn/GgWA2K

 

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
4月前
|
设计模式 Java
Java设计模式【三】:抽象工厂模式
Java设计模式【三】:抽象工厂模式
18 0
|
15天前
|
设计模式 Java Windows
23种设计模式,抽象工厂模式的概念优缺点以及JAVA代码举例
【4月更文挑战第10天】抽象工厂模式是一种创建型设计模式,它提供了一个接口用于创建相关或依赖对象的家族,而不需要指定具体类。该模式允许客户端在不知道具体类的情况下,通过其共同的接口来创建一组产品。
27 7
|
3月前
|
设计模式 Oracle 关系型数据库
设计模式 | 抽象工厂模式
设计模式 | 抽象工厂模式
22 0
|
3月前
|
设计模式 Go 开发工具
Golang设计模式——02抽象工厂模式
Golang设计模式——02抽象工厂模式
21 0
|
3月前
|
设计模式 前端开发
【设计模式】之抽象工厂模式
抽象工厂模式是一种创建型设计模式,适用于需要创建一系列相关或相互依赖对象的场景。在前端开发中,抽象工厂模式可以帮助我们更好地组织和管理代码,提高代码的可维护性和可扩展性。它通过封装对象的创建过程,使得客户端代码与具体类解耦,并且可以通过切换具体工厂类来改变整个系统的行为。然而,它也增加了系统的复杂度,并且当产品族较多时会导致大量的具体工厂类。因此,在使用抽象工厂模式时需要权衡利弊,并根据实际情况进行选择。
53 0
【设计模式】之抽象工厂模式
|
3月前
|
设计模式 NoSQL 中间件
设计模式 - 创建型模式_抽象工厂模式
设计模式 - 创建型模式_抽象工厂模式
21 0
|
4月前
|
设计模式
二十三种设计模式全面解析-抽象工厂模式:创造无限可能的工厂之道
二十三种设计模式全面解析-抽象工厂模式:创造无限可能的工厂之道
|
4月前
|
设计模式 SQL 数据库连接
设计模式之抽象工厂模式--创建一系列相关对象的艺术(简单工厂、工厂方法、到抽象工厂的进化过程,类图NS图)
设计模式之抽象工厂模式--创建一系列相关对象的艺术(简单工厂、工厂方法、到抽象工厂的进化过程,类图NS图)
|
5月前
|
设计模式 Java Maven
你不能不了解的Java23中设计模式之【抽象工厂模式】
你不能不了解的Java23中设计模式之【抽象工厂模式】
|
6月前
|
设计模式 Java iOS开发
JAVA设计模式3:抽象工厂模式,这是一种创建型设计模式
JAVA设计模式3:抽象工厂模式,这是一种创建型设计模式