【设计模式】——简单工厂、工厂方法和抽象工厂

         简单工厂模式、工厂方法模式、抽象工厂模式均属于创建型模式,三种模式都不需要知道具体的类是什么。我们掌握一种思想,就是在创建对象的时候,把容易改变的地方封装起来,来控制变化,更好的适应客户的需求,项目的扩展和变化。

简单工厂模式

   又叫静态工厂模式,顾名思义,用来实例化目标类的静态类。不属于GOF 23种设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。是模式中最简单实用的模式。有利于软件整个体系结构的优化。其最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。但是违背了开放—封闭原则。(详见上篇博客)

工厂方法模式

  定义一个用于创建对象的接口,让子类决定实例化那一个类。工厂方法使一个类的实例化延迟到其子类。其意义在于定义一个创建产品对象工厂的接口,在接口作为核心工厂不再负责产品的具本创建。核心类成为一个抽象工厂角色,负责具本工厂子类必须实现的接口。而子类实现完成实际的创建工作。是最典型的模板方法模式应用。优点它实现了OCP原则,实现可扩展,层次结构更加复杂,可应用于产品结果复杂的场合。
 //例子,新增用户和得到用户为例。举SQL的例子,Access同理。
    //IUser接口,用于客户端访问,解除与具体数据库访问的耦合。
    interface IUser
    {
        void Insert(User user);
        User GetUser(int id);
    }
    //SqlserverUser类,用于访问SQL Sever的User
    class SqlserverUser:IUser 
    {
        public void Insert(User user)
        {
            Console.WriteLine("在SQL Sever中给User表添加一条记录");
        }
        public User GetUser(int id)
        {
            Console.WriteLine("在SQL Sever中根据ID得到User表一条记录");
            return null;
        }
    }
//IFactory接口,定义一个创建访问User表对象的抽象的工厂接口
    interface IFactory
    {
        IUser CreateUser();
    }
    //SqlSeverFactory类,实现IFactory接口,实例化SQLserverUser
    class SqlServerFactory:IFactory
    {
        public IUser CreateUser()
        {
            return new SqlserverUser ();
        }
    }
客户端代码:在使用了工厂方法,只需要转换实例化的工厂,由于此时声明的接口对象实现根本不知道在访问哪个数据库,但却可以在运行时很好的完成工作。这就是所谓的业务逻辑与数据访问的解耦。
static void Main(string[] args)
        {
            User user = new User();
            IFactory factory = new SqlServerFactory();  //若要更改Access数据库只需要修改本句即可。
            IUser iu = factory.CreateUser();
            iu.Insert(user);
            iu.GetUser(1);
            Console.Read();
         }

抽象工厂模式

  提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂最大到的好处就是易于交换产品系列,只需要改变具体工厂即可使用不同的产品配置。第二及时让具体的创建实例过程与客户端分离,客户端是通过他们的丑行接口操纵实例,产品的具体类名也被具体工厂实现分离,不会出现在客户端代码中。没有结合简单工厂使用之前,若要修改增加需求需要修改大量的代码,不符合编程的简单思想。
 //IDepartment接口,用于客户端访问,解除与具体数据库访问的耦合。
    interface IDepartment
    {
        void Insert(Department department);
        Department GetDepartment(int id);
    }
    //SqlserverDepartment类,用于访问SQL Server的Department
    class SqlserverDepartment:IDepartment
    {
        public void Insert(Department department)
        {
            Console.WriteLine("在SQL Server中给Department表增加一条记录");

        }
        public Department GetDepartment(int id)
        {
            Console.WriteLine("在SQL Server中根据ID得到Department表一条记录");
            return null;
        }
    }
    //AccessDepartment类,用于访问Access的Department.
    class AccessDepartment : IDepartment
    {
        public void Insert(Department department)
        {
            Console.WriteLine("在Access中给Department表增加一条记录");
        }
        public Department GetDepartment(int id)
        {
            Console.WriteLine("在Access中根据ID得到Department表一条记录");
            return null;
        }
    }
    //简单工厂对抽象工厂进行了修改,简化了代码,解耦目的实现。
    class DateAccess
    {
        private static readonly string db = "Sqlserver";
        //private static readonly string db="Access";  //数据库的名称,可以替换成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;
        }
    }
static void Main(string[] args)//客户端代码
        {
 User user = new User();
            Department dept = new Department();
            IUser iu = DateAccess.CreateUser();  //直接得到实际的数据库访问实例,而不存在任何依赖。
            iu.Insert(user);
            iu.GetUser(1);
            IDepartment id = DateAccess.CreateDepartment();  //直接得到实际的数据库访问实例,而不存在任何的依赖。
            id.Insert(dept);
            id.GetDepartment(1);
            Console.Read();
        }

小结

   其实,无论是简单工厂模式、工厂模式还是抽象工厂模式,它们本质上都是将不变的部分提取出来,将可变的部分留作接口,以达到最大程度上的复用。究竟用哪种设计模式更适合,这要根据具体的业务需求来决定。


你可能感兴趣的:(【设计模式】——简单工厂、工厂方法和抽象工厂)