zoukankan      html  css  js  c++  java
  • 创建型模式:抽象工厂(Abstract Factory)

    定义

    • 提供一个用于创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。

    UML类图

    工厂方法模式切换数据库

    namespace 抽象工厂02
    {
        /// <summary>
        /// 抽象产品
        /// </summary>
        public interface IUser
        {
            User GetUser(int id);
            void InsertUser(User entity);
        }
    }
    namespace 抽象工厂02
    {
        /// <summary>
        /// 用户表
        /// </summary>
        public class User
        {
            public int ID { get; set; }
    
            public string Name { get; set; }
        }
    }
    using System;
    
    namespace 抽象工厂02
    {
        /// <summary>
        /// 具体产品
        /// </summary>
        public class SqlServerUser : IUser
        {
            public User GetUser(int id)
            {
                Console.WriteLine("在SQL Server中根据ID得到User表中一条记录");
                return null;
            }
    
            public void InsertUser(User entity)
            {
                Console.WriteLine("在SQL Server中给User表中增加一条记录");
            }
        }
    }
    namespace 抽象工厂02
    {
        /// <summary>
        /// 抽象工厂
        /// </summary>
        public interface IFactory
        {
            IUser CreateUser();
        }
    }
    namespace 抽象工厂02
    {
        /// <summary>
        /// SqlServer方式具体工厂
        /// </summary>
        public class SqlServerFactory : IFactory
        {
            public IUser CreateUser()
            {
                return new SqlServerUser();
            }
        }
    }
    using System;
    
    namespace 抽象工厂02
    {
        /// <summary>
        /// Access方式访问数据--具体产品
        /// </summary>
        public class AccessUser : IUser
        {
            public User GetUser(int id)
            {
                Console.WriteLine("在Access中根据ID得到User表中一条记录");
                return null;
            }
    
            public void InsertUser(User entity)
            {
                Console.WriteLine("在Access中给User表中增加一条记录");
            }
        }
    }
    namespace 抽象工厂02
    {
        /// <summary>
        /// Access方式的工厂
        /// </summary>
        public class AccessFactory : IFactory
        {
            public IUser CreateUser()
            {
                return new AccessUser();
            }
        }
    }
    using System;
    
    namespace 抽象工厂02
    {
        /// <summary>
        /// 运用工厂方法模式实现(不同数据库的快速切换)
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                //1.创建具体工厂
                IFactory factory = new SqlServerFactory(); //如果用Access数据库只需要将SqlServerFactory改为AccessFactory就可以了
    
                //2.根据工厂生产具体
                IUser user= factory.CreateUser();
    
                user.InsertUser(new User() { Name="成吉思汗" });
                user.GetUser(3);
    
                Console.ReadKey();
            }
        }
    }
    

    抽象工厂切换数据库,新增一个产品部门

    namespace 抽象工厂03
    {
        /// <summary>
        /// 部门表
        /// </summary>
        public class Department
        {
            public int ID { get; set; }
            /// <summary>
            /// 部门名称
            /// </summary>
            public string Name { get; set; }
        }
    }
    namespace 抽象工厂03
    {
        /// <summary>
        /// 部门抽象接口
        /// </summary>
        public interface IDepartment
        {
            Department GetDepartment(int id);
    
            void InsertDepartment(Department entity);
        }
    }
    using System;
    
    namespace 抽象工厂03
    {
        public class AccessDepartment : IDepartment
        {
            public Department GetDepartment(int id)
            {
                Console.WriteLine("在Access中根据ID得到Department表中一条记录");
                return null;
            }
    
            public void InsertDepartment(Department entity)
            {
                Console.WriteLine("在Access中给Department表中增加一条记录");
            }
        }
    }
    namespace 抽象工厂03
    {
        /// <summary>
        /// 抽象工厂 (应该包含所有产品创建的抽象方法)
        /// </summary>
        public interface IFactory
        {
            IUser CreateUser();
    
            IDepartment CreateDepartment();
            
        }
    }
    namespace 抽象工厂03
    {
        /// <summary>
        /// Access方式的工厂(具体工厂创建具有特定实现的产品对象)
        /// </summary>
        public class AccessFactory : IFactory
        {
            public IDepartment CreateDepartment()
            {
                return new AccessDepartment();
            }
    
            public IUser CreateUser()
            {
                return new AccessUser();
            }
        }
    }
    
    using System;
    
    namespace 抽象工厂03
    {
        /// <summary>
        /// SqlServer部门产品
        /// </summary>
        public class SqlServerDepartment : IDepartment
        {
            public Department GetDepartment(int id)
            {
                Console.WriteLine("在SqlServer中根据ID得到Department表中一条记录");
                return null;
            }
    
            public void InsertDepartment(Department entity)
            {
                Console.WriteLine("在SqlServer中给Department表中增加一条记录");
            }
        }
    }
    namespace 抽象工厂03
    {
        /// <summary>
        /// SqlServer方式具体工厂
        /// </summary>
        public class SqlServerFactory : IFactory
        {
            public IDepartment CreateDepartment()
            {
                return new SqlServerDepartment();
            }
    
            public IUser CreateUser()
            {
                return new SqlServerUser();
            }
        }
    }
    using System;
    
    namespace 抽象工厂03
    {
        /// <summary>
        /// 运用抽象工厂模式实现(不同数据库的快速切换)
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                //1.创建具体工厂
                IFactory factory = new AccessFactory();
    
                //2.通过工厂生成具体产品
                IDepartment department = factory.CreateDepartment();
    
                //3.根据id获取部门
                department.GetDepartment(3);
    
                Console.ReadKey();
            }
        }
    }
    

    抽象工厂第二版

    • 去掉具体的AccessFactory和SqlServerFactory,增加一个工厂类DataAccess
    namespace 抽象工厂04
    {
        /// <summary>
        /// 增加工厂类改造抽象工厂
        /// </summary>
        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;
                    default:
                        break;
                }
                return result;
            }
    
            public static IDepartment CreateDepartment()
            {
                IDepartment result = null;
                switch (db)
                {
                    case "SqlServer":
                        result = new SqlServerDepartment();
                        break;
                    case "Access":
                        result = new AccessDepartment();
                        break;
                    default:
                        break;
                }
                return result;
            }
        }
    }
    namespace 抽象工厂04
    {
        /// <summary>
        /// 用简单工厂改造抽象工厂
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                IUser user = DataAccess.CreateUser();   //直接得到数据库实例,不存在任何依赖
                user.GetUser(3);
    
                IDepartment deparment = DataAccess.CreateDepartment();
                deparment.InsertDepartment(new Department() { Name="研发部" });
    
            }
        }
    }
    

    抽象工厂第三版优化

    • 使用反射的方式加配置文件的方式可做到动态切换数据库
    • 添加配置文件App.config
    using System.Configuration;
    using System.Reflection;
    namespace 抽象工厂05
    {
        /// <summary>
        /// 通过反射创建对象
        /// </summary>
        public class DataAccess
        {
            private static readonly string AssemblyName = "抽象工厂05";
            private static readonly string db = ConfigurationManager.AppSettings["db"];
    
            /// <summary>
            /// 创建用户抽象产品的工厂方法
            /// </summary>
            /// <returns></returns>
            public static IUser CreateUser()
            {
                string className= AssemblyName + "." + db + "User";
                
                return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);
            }
    
            /// <summary>
            /// 创建部门抽象产品的工厂方法
            /// </summary>
            /// <returns></returns>
            public static IDepartment CreateDepartment()
            {
                string className = AssemblyName + "." + db + "Department";
    
                return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);
            }
        }
    }
    
    using System;
    namespace 抽象工厂05
    {
        /// <summary>
        /// 反射+抽象工厂方式实现数据访问
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                IUser iUser = DataAccess.CreateUser();
                iUser.InsertUser(new User() { Name="赵一曼" });
    
                IDepartment iDepartment = DataAccess.CreateDepartment();
                iDepartment.GetDepartment(3);
    
                Console.ReadKey();
            }
        }
    }
    

    优点

    • 易于交换产品系列,由于具体工厂类在每一个应用中只需要在初始化的时候出现一次,这就使得改变一个具体应用工厂变得非常容易。只需要改变具体工厂即可改变不同的产品配置。
    • 它让具体的创建实例过程与客户端分类,客户端是通过它们的抽象接口操作实例,产品的具体类名也被具体工厂的实现分离。不会出现在客户代码中。
    • 很好的遵循了开放-封闭原则。对于新添加产品只需要在工厂方法里面添加新的工厂就可以了。

    缺点

    • 标准的抽象工厂需要额外增加很多工厂类,但是用简单工厂优化后就相对好很多。
  • 相关阅读:
    Zend Studio使用
    iOS中block实现的探究
    用python演示一个简单的AST(抽象语法树)
    Cocos2D-x权威指南: CCNode类方法:
    ListView的优化
    可变參数
    android媒体--stagefright概述【一】
    flume安装及配置
    linux包之sysstat之mpstat与pidstat命令
    Java实现第十届蓝桥杯等差数列
  • 原文地址:https://www.cnblogs.com/wgx0428/p/12862757.html
Copyright © 2011-2022 走看看