设计模式--------工厂模式

前言

  两个月前写过一次设计模式系列,但很不满意就删除了。显然希望能做到学以致用,而非看书总结,设计模式绝对是你解决问题的一个思路,但在这有点自己的小建议,设计模式

并不是用作提高你代码的效率,用它的目的只是让你的代码看起来更规范,更易扩展与维护。所以有的时候你站在你自身需要去选择要不要使用设计模式。上周工作当中有一个需求

正好是适合用工厂模式来解决的,所以就在这给大家讨论讨论工厂模式吧。

1.简单工厂模式

  在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

比如说,我要给其他终端提供保存实例的接口,但是实例却用很多个,这时提供的接口,如果每个实例都提供一边,就会变成这样提供多个端口,如果要增加就要继续提供接口,故

此我就想到了用工厂模式。

1.1.简介:

就好比中午你下楼去吃饭,别人问你干啥去?你说我去吃黄焖鸡,我去吃烩面,我去吃肯德基,去吃麻辣烫。。。。这些好像没错,但是估计你不会这么回答,你一般都是回答

我去吃饭。这就是工厂模式要走的,具体你要吃什么东西,不用告诉别人,别人问的主题是你去干什么,你告诉他你娶吃饭就行,具体你要吃什么,是你自己的决定,无需说出来。

  优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。

      2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。

     3、屏蔽产品的具体实现,调用者只关心产品的接口。

  缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这

并不是什么好事。

1.2.实现(注:以下代码均为不带逻辑的实例代码)

组成部分:

工厂类角色:这是本模式的核心,在此它会根据不同的产品选择生产什么东西。

抽象产品角色:它一般是具体产品继承的父类或者实现的接口。由接口或者抽象类来实现。

具体产品角色:工厂类所创建的对象就是此角色的实例。

首先定义一个接口(抽象产品角色):

public interface ISaveACDb
    {
        void SaveACDB();
    }

根据产品定义各自的类(具体产品类)

  public class SaveACDDbToBuChong : ISaveACDb
    {
        public bool SaveACDB()
        {
            return true;
        }
    }
    public class SaveACDDbToArchivesCases : ISaveACDb
    {
        public bool SaveACDB()
        {
            return true;
        }
    }

接口工厂类的定义:

  public class SaveACDb_Factory
    {
        public static ISaveACDb Create_SaveACDb_Factory(string type)
        {
            ISaveACDb save = null;
            switch (type)
            {
                case "ArchivesCases":
                    save = new SaveACDDbToArchivesCases();
                    break;
                case "BuChong":
                    save = new SaveACDDbToBuChong();
                    break;
            }
            return save;
        }
    }

调用代码:

 public class WinformClientDbController : Controller
    {
        [HttpPost]
        public void SaveACInfo(string type)
        {
            var result = SaveACDb_Factory.Create_SaveACDb_Factory(type);
            result.SaveACDB();
        }
    }

问:如果一直增加产品,是不是就要增加产品类?

答:是的。

有没有发现问题,这样不断增加产品,然后增加产品类到时没什么,但是相应的回去修改工厂类,有没有发现,那么这样就有问题,就像我上篇设计模式提到的“开闭原则”,我们在

这种模式下就充分的违背了,所以如果产品类如果会大量增加的话,你最起码要知道这是违背设计原则的。

问:那该怎么解决呢?

答:用反射。

2.简单工厂与反射

  反设我已经在基础拾遗------反射详解介绍过来。

简单工厂中使用反射的目的就是去掉工厂类中的switch(或if)。ps:想一想这一改变,特别是我现在这种给其他客户端提供接口的程序,大大第提高代码的解耦。

代码如下:

  public class SaveACDb_Factory
    {
        public static ISaveACDb Create_SaveACDb_Factory(string obj, string className)
        {
            Assembly assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集
            var result = (ISaveACDb)assembly.CreateInstance("StrokeLocalWinformInterface" + ".SaveACDDbTo" + className);
            return result;
        }
    }

调用

        [HttpPost]
        public void SaveACInfo(string obj, string userNickeName, string userToken, string className)
        {
            if (1 > 2)//验证usertoken
                return;
            var result = SaveACDb_Factory.Create_SaveACDb_Factory(obj, className);
            result.SaveACDB(obj);
        }

3.抽象工厂

  就像上面说的,如果我们的产品不断增加且成树装结构增加,我们就要说说抽象工厂。

3.1.简介:

如果别人为你干啥去,你说你去吃饭去,但是你再去的过程当中,如果考虑肯德基要吃鸡翅还是汉堡,他们都是什么口味,去吃快餐都是有什么。。。。这样如果选择一次吃

饭,是不是要想半个小时,所以去吃烩面这个产品也可以把它当作吃饭这个超级工厂的子工厂。

  抽象工厂就是围绕这超级工厂建立的其他工厂。超级工厂是其他工厂的工厂。

  优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

  缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

3.2.实现:

  抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。

具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。

  抽象产品角色:它是具体产品继承的父类或者是实现的接口。

  具体产品角色:具体工厂角色所创建的对象就是此角色的实例。

  以下案例为借鉴过来的,就是公司老板有很多车,司机开车是一个超级工厂,每辆车是具体操作是另外一个工厂,这次偷个懒就不自己写案例啦。

抽象产品:就是定一个车的类,此类有一个司机开车的方法抽象方法,和具体是什么车,进行赋值的方法。

 abstract class Car{  
        private String name;  
          
        public abstract void drive();  
          
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
    } 

具体产品:继承抽象产品,宝马和奔驰都是不同的车。

 class Benz :Car{  
        public void drive(){  
           //
        }  
    }  
    class Bmw :Car{  
        public void drive(){  
           
//
        }  
    }  
      

抽象工厂:司机就是要开车吗。这个工厂抽象司机开车。

abstract class Driver{  
        public abstract Car createCar(String car) throws Exception;  
    }  

具体工厂:开宝马和奔驰还是不一样的,这个工厂针对不同的车去实例。

    class BenzDriver :Driver{  
        public Car createCar(String car) throws Exception {  
            return new Benz();  
        }  
    }  
    class BmwDriver :Driver{  
        public Car createCar(String car) throws Exception {  
            return new Bmw();  
        }  
    }  

以上就是抽象工厂的组成部分,客户端只需在实例化相应的工厂调用即可。

调用代码:

//老板  
    public class Boss{  
        public static void main(String[] args) throws Exception {  
            Driver d = new BenzDriver();  
            Car c = d.createCar("benz");   
            c.setName("benz");  
            c.drive();  
        }  
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大数据挖掘DT机器学习

新手学python 如何求职拿offer?

从八月底开始找工作,短短的一星期多一些,面试了9家公司,拿到5份Offer,可能是因为我所面试的公司都是些创业性的公司吧,不过还是感触良多,因为学习Python...

51060
来自专栏Linyb极客之路

简洁又快速地处理集合——Java8 Stream(上)

本篇文章主要是让大家能够理解 Stream,理解它的基本原理,理解我们为什么需要使用 Stream 以及它的好处,而具体的实战环节我会在下篇文章中讲解。

69450
来自专栏java学习

每日一练(2017/5/23)

Java基础 | 数据库 | Android | 学习视频 | 学习资料下载 课前导读 ●回复"每日一练"获取以前的题目! ●答案公布时间:为每期发布题目的第二...

26870
来自专栏Java Web

Java 8——行为参数化

前言 《Java8实战》不得不说是一本好书,捧起来看起来就兴奋得不想放下,其中介绍的函数式编程实在是太令人兴奋了,不仅仅大大提高了代码的可读性,而且提高了代码的...

46370
来自专栏张泽旭的专栏

回溯法解决八人过河问题

一家六口,一个爸爸,一个妈妈,俩儿子,俩女儿,还有一个警察,一个坏蛋,过一条河,爸爸不在妈妈伤害儿子,妈妈不在爸爸伤害女儿,警察不在坏蛋伤害一家六口,只有妈妈爸...

10020
来自专栏顶级程序员

如何拿到半数面试公司Offer——我的Python求职之路

从八月底开始找工作,短短的一星期多一些,面试了9家公司,拿到5份Offer,可能是因为我所面试的公司都是些创业性的公司吧,不过还是感触良多,因为学习Pytho...

33450
来自专栏CDA数据分析师

如何拿到半数面试公司Offer——我的Python求职之路

从八月底开始找工作,短短的一星期多一些,面试了9家公司,拿到5份Offer,可能是因为我所面试的公司都是些创业性的公司吧,不过还是感触良多,因为学习Python...

30680
来自专栏PPV课数据科学社区

是学习Java还是Python?一张图告诉你!

Java 和 Python 一直都是两种很火很强大的编程语言,对于刚开始起步学习编程的同学来说,会迷惑且最经常问的问题是,我该学 Java 还是 Python,...

37070
来自专栏小文博客

蓝桥杯 C语言省赛 习题1 奖券数目

17920
来自专栏老九学堂

学习C语言的用途以及如何快速掌握C语言

C是基础的语言 被广泛用于操作系统和编译器的开发 功能非常强 虽然现在不是最流行但它是 最基础的东西 也是比较好学的语言 如:金山的创始人江明 从30...

47070

扫码关注云+社区

领取腾讯云代金券