为什么工厂模式是华而不实的—浅谈工厂模式的利与弊_工厂模式 很扯淡-程序员宅基地

技术标签: 面试  设计模式  工厂模式  

转载请注明出处:http://blog.csdn.NET/singwhatiwanna/article/details/17428923

说明:博主虚心接受大家的抨击,批评,指正

前言

我一直想介绍下工厂模式,我曾经搞过J2EE,用的是轻量级SSH框架,其中spring有IOC概念,可以称之为控制反转或者依赖注入,在系统开发中,IOC可以很好的替代工厂模式。若干年前,我只用过IOC,并没有用过工厂模式,但是工厂模式这个概念却是给我留下了深深的印象,毕竟,它是我所听说过第一个设计模式,我想它应该是很强大的吧。但是,事情不是我想的那个样子的,在我之前所参与的项目(Android)中几乎没有工厂模式的身影,仅仅是有一个项目采用了简单工厂模式去管理所有的业务管理器。后来,我开始仔细研究工厂模式,发现工厂模式是让我失望的。工厂模式有三种实现方式:简单工厂、工厂方法和抽象广场,除了简单工厂我还发现了一点使用价值外,后两者我基本没发现有啥可使用价值。也许我的理解还不够透彻,但是目前网上存在的大部分介绍工厂模式的文章都体现了一点:华而不实,难以实际应用。一篇文章不能清晰的介绍一个概念,不能清晰的说明为什么要使用这个东西以及如何使用这个东西,那么这篇文章不算好文章的。我目前所看到的关于工厂模式的介绍都是不充分的,包括我写的这篇,期待真正的好文章出现。下面将介绍简单工厂模式以及一个实际项目中使用的例子,后面我将会简单阐述我的观点:为什么工厂模式是华而不实的。

简单工厂模式

1.为什么要使用工厂模式

直接目的:避免在代码中出现大量的new关键字

根本目的:将对象的创建统一起来便于维护和整体把控

这一点可以理解,加入你在项目中new了某个对象100次,一年后由于业务逻辑变更,构造方法多了一个参数,你会怎么办?你应该会这么做:找到这100个对象new的地方,用新的构造方法来创建对象,你重复劳动了100次,假如采用工厂模式,你只用改一次:把创建工厂给改一下就好了。这就是工厂模式最简单最直接的好处。

2.工厂模式的示例

下面是最常见的一个示范,其实它的原理就是面向对象中的多态+接口编程,虽然返回的都是Car类型,但是drive的时候会调用真正的实例中的对应方法。按照抽象类和接口的意义归属,Car应该被定义成抽象类,因为Benz、Bmw和Car的关系是继承关系,而接口表示的一组行为。但是,为什么这里还要定义成接口,是因为Java和.NET不支持多继承,如果继承了Car,就无法继承其他类,有时候业务需要必须继承其他类,这个时候代码就不能用了。当然,C++中支持多继承,因此可以在C++中使用抽象类,另外C++没接口的概念,但你可以模拟接口。这里只介绍简单工厂模式,至于剩下两种工厂模式,我觉得更没有使用价值。

[java]  view plain   copy
  1. interface Car {  
  2.     void drive();  
  3. }  
  4.   
  5. class Benz implements Car {  
  6.   
  7.     @Override  
  8.     public void drive() {  
  9.         System.out.println("drive Benz");  
  10.     }  
  11.   
  12. }  
  13.   
  14. class Bmw implements Car {  
  15.   
  16.     @Override  
  17.     public void drive() {  
  18.         System.out.println("drive Bmw");  
  19.     }  
  20.   
  21. }  
  22.   
  23. class CarFactory {  
  24.     public static Car creator(String carType) {  
  25.         if (carType.equals("Benz")) {  
  26.             return new Benz();  
  27.         } else if (carType.equals("Bmw")) {  
  28.             return new Bmw();  
  29.         } else {  
  30.             throw new UnsupportedOperationException("car with type" + carType  
  31.                     + " is not supported.");  
  32.         }  
  33.     }  
  34. }  
  35.   
  36. public class A {  
  37.     public static void main(String args[]) {  
  38.         Car benz = CarFactory.creator("Benz");  
  39.         benz.drive();  
  40.         Car bmw = CarFactory.creator("Bmw");  
  41.         bmw.drive();  
  42.     }  
  43. }  

上述代码是没啥用的,看一个实际使用的例子。下面这个工厂模式的意义在于能够统一管理所有的业务管理器,仅此而已。

[java]  view plain   copy
  1. /** 
  2.  * 管理器的工程,初始化所有业务的管理器 
  3.  */  
  4. public class ManagerFactory {  
  5.     // 缓存管理器实例的集合  
  6.     private transient Map<Byte, IManager> mManagerMap = null;  
  7.   
  8.     private static ManagerFactory sIntance = new ManagerFactory();  
  9.   
  10.     private ManagerFactory() {  
  11.         mManagerMap = new HashMap<Byte, IManager>();  
  12.     }  
  13.   
  14.     public ManagerFactory getInstance() {  
  15.         return sInstance;  
  16.     }  
  17.   
  18.     /** 
  19.      * 获取管理器实例 
  20.      *  
  21.      * @param context  上下文 
  22.      * @param id  管理器ID 
  23.      * @return  管理器实例 
  24.      */  
  25.     protected IManager getManager(final Context context, final byte id) {  
  26.         IManager manager = mManagerMap.get(mId);  
  27.   
  28.         if (manager == null) {  
  29.             switch (id) {  
  30.             case DB_ID:  
  31.                 manager = new DBManager(context);  
  32.                 break;  
  33.             case DOWNLOAD_ID:  
  34.                 manager = new DownloadManager(context);  
  35.                 break;  
  36.             case NETWORK_ID:  
  37.                 manager = new NetworkManager();  
  38.                 break;  
  39.             case IMAGE_ID:  
  40.                 manager = new ImageManager();  
  41.                 break;  
  42.             default:  
  43.                 break;  
  44.             }  
  45.             mManagerMap.put(id, manager);  
  46.         }  
  47.   
  48.         return manager;  
  49.     }  
  50. }  

工厂模式为什么没有太大价值

1.有利有弊

优点:将对象的创建统一起来便于维护和整体把控,对扩展开放,对修改封闭

缺点:耦合性提高,由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中,这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利。

2.使用有限制

从工厂模式的示例可以看出:工厂模式需要类实现它的接口并且在业务内部存在明显的继承关系,比如汽车和奔驰宝马的关系。而继承关系往往存在于模型之间,业务之间很难存在继承关系,因此如果业务内部或者业务之间没有这种显式的继承关系该咋办?就算业务内部有继承关系,各个业务交给你统一管理,这样就会提高代码的耦合性,当创建逻辑复杂的时候,工厂方法就很复杂,容易产生干扰。

3.其开闭性优点很容易被替代

可以通过高度层次化和模块化来提高系统的开闭性,而不必生硬地去套用工厂模式。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/liyanlei5858/article/details/77124175

智能推荐

gis插入的文本怎么搞成两行_没有电脑怎么做PPT?用手机这样做!比电脑做出来的还要精美...-程序员宅基地

文章浏览阅读81次。前天晚上小编正躺在床上刷微博的时候,领导突然找我!要我帮他搞个PPT!吓得我差点从床上滚下来!能不做吗?当然不能了……懒癌晚期的我真的不想从床上爬起来开电脑做PPT!!!我和床是真爱!!!不要将我们分离!!!怎么办呢?嘿嘿!那就用手机做吧!什么?你不知道手机可以做PPT 吗?啧!看来还得我来教你!一、PPT制作1、安装WPS首先呢,我们当然需要工具!所以先在手机里安装一个WPS~这个大家不陌生吧?...

基于Docker搭建DzzOffice与OnlyOffice线上协同办公服务器_dzzoffice onlyoffice-程序员宅基地

文章浏览阅读9.5k次,点赞2次,收藏32次。基于Docker搭建DzzOffice与OnlyOffice线上协同办公服务器基于Docker搭建DzzOffice与OnlyOffice线上协同办公服务器 安装操作系统 安装数据库 安装部署DzzOffice 官方镜像提示: 安装部署Onlyoffice 安装操作系统我是用的是最新版的Ubuntu桌面系统,其实操作系统无所谓,使用Docker之后和操作系统的影响不是很大,容器化部署之后方便迁移和重新部署安装数据库在docker官方镜像源上下载mysql数据库镜_dzzoffice onlyoffice

C语言 | windows命令行编译(Cygwin)_cygwin编译命令-程序员宅基地

文章浏览阅读2.2k次。本文更好的排版方式:https://mp.weixin.qq.com/s?__biz=MzU5MzcyMjI4MA==&amp;amp;amp;amp;amp;mid=100000740&amp;amp;amp;amp;amp;idx=1&amp;amp;amp;amp;amp;sn=f2b589c6930bb6576b5f59997dbef111&amp;amp;amp;amp;amp;chksm=7e0d6d23497ae43532bc906510246c23a885_cygwin编译命令

IMX6ULL系列学习记录-sii902x移植篇-程序员宅基地

文章浏览阅读4.7k次,点赞5次,收藏19次。主题:IX6ULL sii902x移植记录(参考官方文档Sii9022a HDMI transmitter driver)硬件平台:野火IMX6ULL软件:ubuntu19.04交叉编译器:gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihfU-Boot:uboot-imx-rel_imx_4.1.15_2.1.0_gaker..._sii902x

跟着官方文档学DGL框架第十天——训练图神经网络之链接预测_链接预测 图神经网络-程序员宅基地

文章浏览阅读6.4k次,点赞14次,收藏65次。参考链接https://docs.dgl.ai/en/latest/guide/training-link.html#guide-training-link-prediction概述什么是链接预测链接预测就是预测图中给定节点间是否存在边,常用于推荐系统。形式化地,给定节点uuu和vvv,链接预测的任务就是得到它们间存在链接的概率yu,v=ϕ(u,v)y_{u,v}=\phi \left ( u,v\right )yu,v​=ϕ(u,v)。具体到GNN上,我们通过L层的GNN得到节点uuu和vv_链接预测 图神经网络

nginx和uwsgi的配置以及uwsgi日志文件的切割和过期日志的删除_uwsgi.log可以删除吗-程序员宅基地

文章浏览阅读2.7k次。nginx配置文件worker_processes 4;events { worker_connections 1024;}http { include /home/nginx/conf/mime.types; default_type application/octet-stream; log_format ..._uwsgi.log可以删除吗

随便推点

转:动态规划题目分类-程序员宅基地

文章浏览阅读155次。https://blog.csdn.net/cc_again/article/details/25866971一、简单基础dp这类dp主要是一些状态比较容易表示,转移方程比较好想,问题比较基本常见的。主要包括递推、背包、LIS(最长递增序列),LCS(最长公共子序列),下面针对这几种类型,推荐一下比较好的学习资料和题目。1、递推:递推一般形式比较单一,从前往后,分类枚举就..._杭电 动态规划大全` 题目分类

如何升级Carbide C++的GCCE Tool Chain_no tool chain set up in kit "desktop qt 5.9.6 gcc -程序员宅基地

文章浏览阅读2.4k次。Carbide C++的编译器在Symbian开发工程中,Carbide C++是非常好用的开发工具,目前提供GCCE,ARMV5和RVCT三种编译器的支持。前两种编译器是免费的,RVCT是收费的编译工具,网上下载的Carbide并不默认提供,需要自己下载并配置才能使用,由于RVCT提供了专门的优化,编译结果的目标文件体积很小,且代码执行效率更高,但问题是该编译器费用比较昂贵,普通开发_no tool chain set up in kit "desktop qt 5.9.6 gcc 64bit" for "c++".

断点续传、大文件上传、秒传、webuploader_webuploader 限制视频文件上传的秒数-程序员宅基地

文章浏览阅读317次。一、 功能性需求与非功能性需求 要求操作便利,一次选择多个文件进行上传;支持大文件上传(1G),同时需要保证上传期间用户电脑不出现卡死等体验;交互友好,能够及时反馈上传的进度;服务端的安全性,不因上传文件功能导致JVM内存溢出影响其他功能使用;最大限度利用网络上行带宽,提高上传速度;二、 设计分析 对于大文件的处理,无论是用户端还是服务端,如果一次性进行读取发送、接收都是..._webuploader 限制视频文件上传的秒数

gRPC学习之五:gRPC-Gateway实战,java分层架构_grpc gateway java-程序员宅基地

文章浏览阅读803次。GO的gRPC开发环境准备极速搭建gRPC-Gateway环境所谓的搭建gRPC-Gateway环境,其实是完成以下三件事:在搭建环境时参考了一些网上的文章,结果遇到了各种问题一直没有成功(我当然不会认为文章有问题,必须认识到是自己能力不足的原因所致);经过反复折腾后终于成功后,我把所有操作做成一个shell脚本,执行以下命令即可完成上图中的所有操作:curl -o install-grpc-gateway.sh \https://raw.githubusercontent._grpc gateway java

利用githubpage和codingpage创建个人主页_coding 实现 github.io 个人主页-程序员宅基地

文章浏览阅读1.9k次。github page 创建个人主页使用帮助:https://pages.github.com/我的主页:http://mouday.github.io/当然,我绑定了自己的域名:https://www.pengshiyu.com/至于域名前面的绿锁头可以参考: 给自己github绑定的域名加个绿锁头httpscoding page创建个人主页使用帮助:https..._coding 实现 github.io 个人主页

存储过程 @与字符连接_存储过程连接符-程序员宅基地

文章浏览阅读289次。&gt; BEGIN -&gt; declare a int; -&gt; declare b varchar(5000); -&gt; set a=1; -&gt; set b=''; -&gt; while a&lt;10 do -&gt; set b = concat(b,',',a); -&gt; set a=a+_存储过程连接符