Fork me on GitHub

李可

导航

设计模式 简单工厂+工厂方法+抽象工厂

简单工厂

简单工厂的优缺点:

缺点:①违反了OCP(开放-封闭原则)。(当工厂内增加一个方法创建对象时候,需要在原来的工厂内,添加一个case语句)。修改原来的类,是违反设计原则的。

        ②增加客户端和工厂类的耦合。

优点:①去除(非降低)客户端和具体产品的耦合。客户端和具体产品中间增加一个工厂类,增加客户端和工厂类的耦合。

   ②封装工厂类,实现代码多平台的复用性。创建对象的过程被封装成工厂类,可以多平台(控制台+WEB+Winform...手机端)调用这个工厂。

   ③封装工厂类,创建对象的过程(具体逻辑)包含必要的逻辑,根据客户端的要求,我们可以动态的去创建对象。比如用反射或者new的方式来创建。

“产品”类

 public class PersonClass
   {
      public string Name { get; set; }
      public double Height { get; set; }
   }
   class WhitePerClass : PersonClass
   {     
   }
   class BlackPerClass : PersonClass
   {      
   }
   class YellowPerClass : PersonClass
   {     
   }

“工厂”类:

 public static class ClassFactory
  {
    public static PersonClass CreateObject(string str)
    {
      PersonClass perClass = null;
      //也可以用反射等逻辑来创建对象。客户端调用时,是管不到我怎么样创建对象的。这是封装的好处之一。
      switch (str)
      {
        case "white":
          perClass = new WhitePerClass();
          break;
        case "black":
          perClass = new BlackPerClass();
          break;
        case "yellow":
          perClass = new YellowPerClass();
          break;
      }
      return perClass;
    }
  }
}

“客户端”:

 static void Main(string[] args)
      {
         //PersonClass perWhite = new WhitePerClass();//虽然“产品”类PersonClass,采用了面向高层的方法,不用工厂创建对象,还是有一定的耦合。
         PersonClass perClass = null;
         perClass = ClassFactory.CreateObject("white");
         perClass.Name = "小白";
         perClass.Height = 1.7;
         Console.WriteLine(perClass.Name + perClass.Height);
         perClass = ClassFactory.CreateObject("black");
         perClass.Name = "小黑";
         perClass.Height = 2.1;
         Console.WriteLine(perClass.Name + perClass.Height);
         perClass = ClassFactory.CreateObject("yellow");
         perClass.Name = "小黄";
         perClass.Height = 1.8;
         Console.WriteLine(perClass.Name + perClass.Height);
         Console.Read();
      }

结果:

再述简单工厂:

产品本身采用了多态。可以new一个产品出来,这样本身降低了客户端和“产品”的耦合,但是未去除耦合。由工厂进一步去除耦合。

缺点:当增加一个产品时,需要在工厂添加一个case语句,修改了原来工厂类。违反了OCP开放封闭原则。

总结简单工厂:

给工厂传一个字符串,返回一个对象。创建逻辑各式各样。

产品树(产品等级)+产品族

都是指的产品。根据品牌和生产厂家分类。

 

产品树(产品等级):针对产品。指一个产品:品牌不同。

①车(产品):宝马车,奥迪车,奥拓车。

②数据库(产品):MS-SQL,ORACLE,ACCESS,DB2,MongoDB

 

产品族:针对工厂。一个工厂,产各种产品,各种产品统称一“族”。

①宝马(工厂)生产:宝马自行车,宝马三轮车0.0,宝马的其他产品,衣服,鞋子,宝箱等等。都是一族

②MS-SQL(工厂)生产: user表,department表,role表

 

工厂方法

 

特点:只处理一个产品树。可以理解为,只对一张表处理。也是和下面的抽象工厂区别的地方

优点:就是解决简单工厂的缺点(违反了OCP)。和抽象工厂一样,提高程序的扩展性,可以改数据库。增加对应数据库工厂。

缺点:不能增加一个“产品”,只能增加一个工厂,实现了换数据库的功能。但只能处理一个表。若增加一个表就是抽象工厂了。

 

类图:

 

个人总结:我们平时用到了工厂模式,一般属于简单工厂或者抽象工厂,因为可以对多个表处理。

 

抽象工厂 

优点:去除了简单工厂的违反OCP原则,通过添加子类,而不是改变原来类。来增加”产品“。

缺点:每增加一个产品:需要添加一个产品接口+sql产品+oracle产品,还要增加工厂接口+sql工厂+oracle工厂的一个方法。

“产品“类

用户:

  interface IUserDal
  {
    void CRUD();
  }
  class SqlUserDal : IUserDal
  {
    public void CRUD()
    {
      Console.WriteLine("sql数据库User的CRUD");
    }
  }
  class OracleUserDal : IUserDal
  {
    public void CRUD()
    {
      Console.WriteLine("Oracle数据库User的CRUD");
    }
  }

部门:

interface IDepartmentDal
  {
    void CRUD();
  }
  class SqlDepartmentDal :  IDepartmentDal
  {
    public void CRUD()
    {
      Console.WriteLine("sql数据库Department的CRUD");
    }
  }
  class OracleDepartmentDal : IDepartmentDal
  {
    public void CRUD()
    {
      Console.WriteLine("Oracle数据库Department的CRUD");
    }
  }

”工厂“类

  interface IFactory
  {
    IUserDal CreateUserDal();
    IDepartmentDal CreateDepartmentDal();
  }
  class SqlFactory : IFactory
  {
    public IUserDal CreateUserDal()
    {
      return new SqlUserDal();
    }
    public IDepartmentDal CreateDepartmentDal()
    {
      return new SqlDepartmentDal();
    }
  }
  class OracleFactory : IFactory
  {
    public IUserDal CreateUserDal()
    {
      return new OracleUserDal();
    }
    public IDepartmentDal CreateDepartmentDal()
    {
      return new OracleDepartmentDal();
    }
  }

客户端:

      static void Main(string[] args)
      {
         //创建Sql对应dal
         SqlFactory sqlFactory=new SqlFactory();
         IUserDal sqlUserDal = sqlFactory.CreateUserDal();
         sqlUserDal.CRUD();
         IDepartmentDal sqlDeparmentDal = sqlFactory.CreateDepartmentDal();
         sqlDeparmentDal.CRUD();
        
         //换数据库了,需要创建Oracle对应Dal
         OracleFactory oracleFactory = new OracleFactory();
         IUserDal oracleUserDal = oracleFactory.CreateUserDal();
         oracleUserDal.CRUD();
         IDepartmentDal oracleDeparmentDal = oracleFactory.CreateDepartmentDal();
         oracleDeparmentDal.CRUD();
         Console.Read();
      }

 结果:

总结:

①理解产品族和产品树(产品等级),方便记忆类图。

②知道工厂方法和抽象工厂的区别

③工厂方法和抽象工厂改善了简单工厂的缺点(违反ocp),带来的缺点是什么。

 

为了改变抽象工厂增加一个”产品“,带来的繁琐代码,你想到怎么改进了吗?

posted on 2015-05-11 20:56  李可在江湖  阅读(1554)  评论(0编辑  收藏  举报