zoukankan      html  css  js  c++  java
  • 设计模式 简单工厂+工厂方法+抽象工厂

    简单工厂

    简单工厂的优缺点:

    缺点:①违反了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),带来的缺点是什么。

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

  • 相关阅读:
    HDU 1009 FatMouse' Trade
    HDU 2602 (简单的01背包) Bone Collector
    LA 3902 Network
    HDU 4513 吉哥系列故事——完美队形II
    LA 4794 Sharing Chocolate
    POJ (Manacher) Palindrome
    HDU 3294 (Manacher) Girls' research
    HDU 3068 (Manacher) 最长回文
    Tyvj 1085 派对
    Tyvj 1030 乳草的入侵
  • 原文地址:https://www.cnblogs.com/leee/p/4494411.html
Copyright © 2011-2022 走看看