设计模式二十四讲之《抽象工厂模式》

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

优点:1.易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置;
2.让具体的创建实例过程与客户端分离,客户端通过它们的抽象接口操作实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中;

缺点:当增加新功能时,必须做相应类的增加和相应类的修改:比如当增加项目表Project的时候,就至少要增加IProject、SqlseverProject、AccessProject三个类,还要更改IFactory、SqlserverFactory、AccessFactory这三个类才能实现。

使用时机:只有一个User类和User操作类的时候,是只需要工厂方法模式的,但现在显然你数据库中有很多的表,而SQL Server与Access有两大不同的分类,所以解决这种涉及多个产品系列的问题需要用到抽象工厂模式。游戏中例如QQ农场不同系列的建筑生成逻辑。


 class Program
    {
        static void Main(string[] args)
        {
            //User user = new User() ;                       //最开始最简单的没有调用设计模式的写法           
            //SqlserverUser su = new SqlserverUser();
            //su.Insert(user);
            //su.GetUser(1);
            //Console.Read();

            //User user = new User();                        //第二次改进后的代码                                                                  //执行步骤:1.实例化User对象;
            //IFactory factory = new SqlserverFactory();                                                                                           //          2.将继承于IFactory的SqlserverFactory实例化对象传递到factory;
            //IUser iu = factory.CreatUser();                                                                                                      //          3.将factory中的方法CreatUser实例后的对象(SqlserverUser())传递给继承的父类IUser的对象iu;
            //iu.Insert(user);                                                                                                                     //          4.iu通过方法Insert调用相应的方法(为了表现使用了User,我在这里传递了User的Name);
            //iu.GetUser(1);                                                                                                                       //          5.iu通过方法GetUser调用相应的方法(这里直接传递了一个Id);
            //Console.Read();

            //User user = new User();                        //第三次改进后的代码,用到抽象工厂模式                                                //执行步骤:1.实例化User/Department对象;
            //Department dept = new Department();                                                                                                  //          2.将继承于IFactory的SqlserverFactory实例化对象传递到factory;
            //IFactory factory = new SqlserverFactory();//或者“new AccessFactory();”只需确定实例化哪一个数据库访问对象给factory                        //          3.将factory.CreatUser()方法获得的对象SqlserverUser()传递给继承的父类IUser的对象iu;
            //IUser iu = factory.CreatUser();                                                                                                      //          4.iu通过方法Insert调用相应的方法(为了表现使用了User,我在这里传递了User的Name);
            //iu.Insert(user);                                                                                                                     //          5.iu通过方法GetUser调用相应的方法(这里直接传递了一个Id);
            //iu.GetUser(1);                                                                                                                       //          6.IDepartment 重复3.4.5.步骤
            //IDepartment iDerpart = factory.CreatDepartment();
            //iDerpart.Insert(dept);
            //iDerpart.GetDepartment(1);
            //Console.Read();

            User user = new User();                         //第四次改进后的代码,结合了简单工厂;第五次改进后使用反射实现                         //执行步骤:1.实例化User/Department对象,并将Name添加相应值;
            user.Name = "毛毛都的无聊生活 ";                                                                                                   //          2.通过DataAccess.CreatUser()和DataAccess.CreatDepartment()获得的对象传递【注意第五次改进后用到的反射方法,很方便】
            Department dept = new Department();                                                                                               //          3.执行iu所获得对象里面的Insert和GetUser方法
            dept.Name = "毛毛都的无聊生活 ";                                                                                                   //          4.执行idept所获得对象里面的Insert和GetUser方法
            IUser iu = DataAccess.CreatUser();
            iu.Insert(user);
            iu.GetUser(1);
            IDepartment idept = DataAccess.CreatDepartment();
            idept.Insert(dept);
            idept.GetDepartment(1);
            Console.Read();
        }
    }

  interface IFactory
    {
        IUser CreatUser();
        IDepartment CreatDepartment();
    }
    class SqlserverFactory:IFactory
    {
        public IUser CreatUser()
        {
            return new SqlserverUser();
        }
        public IDepartment CreatDepartment()
        {
            return new SqlserverDepartment();
        }       
    }
    class AccessFactory:IFactory
    {
        public IUser CreatUser()
        {
            return new AccessUser();
        }
        public IDepartment CreatDepartment()
        {
            return new AccessDepartment();
        }        
    }

 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; }
        }
    }
    //class SqlserverUser                 //跟上面类的配套初始写法
    //{
    //    public void Insert(User user)
    //    {
    //        Console.WriteLine("在SQL Server中给User表增加一条记录");
    //    }
    //    public User GetUser(int id)
    //    {
    //        Console.WriteLine("在SQL Server中根据ID得到User表一条记录");
    //        return null;
    //    }
    //}


    interface IUser
    {
        void Insert(User user);
        User GetUser(int id);
    }

    class SqlserverUser:IUser 
    {
        List<User> users = new List<User>();
        public void Insert(User user)
        {
            users.Add(user);
            Console.WriteLine("在SQL Server中给User表增加一条记录[{0}]",user.Name);
        }
        public User GetUser(int id)
        {
            Console.WriteLine("在SQL Server中根据ID[{0}]得到User表一条记录",id);
            User date = users[id];
            if (date != null)
            {
                return date;
            }
            return null;
        }     
    }
    class AccessUser:IUser
    {
        List<User> users = new List<User>();
        public void Insert(User user)
        {
            users.Add(user);
            Console.WriteLine("在Access中给User表增加一条记录[{0}]", user.Name);
        }
        public User GetUser(int id)
        {
            Console.WriteLine("在Access中根据ID[{0}]得到User表一条记录", id);
            User date = users[id];
            if (date != null)
            {
                return date;
            }
            return null;
        }       
    }

 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; }
        }
    }

    interface IDepartment
    {
        void Insert(Department department);
        Department GetDepartment(int id);
    }
    class  SqlserverDepartment:IDepartment
    {
        List<Department> departments = new List<Department>();
        public void Insert(Department department)
        {
            departments.Add(department);
            Console.WriteLine("在SQL Server中给User表增加一条记录[{0}]", department.Name);
        }
        public Department GetDepartment(int id)
        {
            Console.WriteLine("在SQL Server中根据ID[{0}]得到User表一条记录", id);
            if (departments[id] != null)
                return departments[id];
            return null;
        }       
    }
    class AccessDepartment : IDepartment
    {
        List<Department> departments = new List<Department>();
        public void Insert(Department department)
        {
            departments.Add(department);
            Console.WriteLine("在Access中给User表增加一条记录[{0}]", department.Name);
        }
        public Department GetDepartment(int id)
        {
            Console.WriteLine("在Access中根据ID[{0}]得到User表一条记录", id);
            if (departments[id] != null)
                return departments[id];
            return null;
        }      
    }

  class DataAccess
    {
        //private static readonly string db = "Sqlserver";//或者"Access"    数据库名称
        //public static IUser CreatUser()
        //{
        //    IUser result = null;
        //    switch (db)
        //    {
        //        case "Sqlserver":
        //            result = new SqlserverUser();
        //            break;
        //        case "Access":
        //            result = new AccessUser();
        //            break;
        //    }
        //    return result;
        //}
        //public static IDepartment CreatDepartment()
        //{
        //    IDepartment result = null;
        //    switch (db)
        //    {
        //        case "Sqlserver":
        //            result = new SqlserverDepartment();
        //            break;
        //        case "Access":
        //            result = new AccessDepartment();
        //            break;
        //    }
        //    return result;
        //}

        //第五次改进,应用反射时的写法--------所有在用简单工厂的地方,都可以考虑用反射技术来去除switch或if,解除分支判断带来的耦合

        private static readonly string AssemblyName = "抽象工厂模式";
        private static readonly string db = "Sqlserver";//或者“Access”,如果此时需要增加“Oracle”数据访问,就将其换成这个就行了
      

        public static IUser CreatUser()
        {
            string className = AssemblyName + "." + db + "User";
            return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);
        }
        public static IDepartment CreatDepartment()
        {
            string className = AssemblyName + "." + db + "Department";
            return (IDepartment )Assembly.Load(AssemblyName).CreateInstance(className);
        }
    }

转载请注明出处!!!

欢迎加入951815219群聊,共享知识,讨论交流~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值