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),带来的缺点是什么。

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

    知识没有高低贵贱之分。
     
     
  • 相关阅读:
    yolo v1
    012. MVC5中Razor引擎使用模板页
    Centos 7 下, 安装odoo 10
    011. 解决VS2015中CS1528: Expected ; or = (cannot specify constructor arguments in declaration)
    010. VS2015创建MVC项目
    解决IE增强配置的问题
    解决Centos 7 下 tomcat字体异常 Font '宋体' is not available to the JVM
    tomcat7.0在centos7下中文乱码问题解决汇总
    windows服务器审核失败消息:事件ID: 861 进程标识符:904
    使用USBWriter做U盘启动盘后容量变小的解决办法
  • 原文地址:https://www.cnblogs.com/Rozdy/p/4496508.html
Copyright © 2011-2022 走看看