简单工厂模式+工厂方法模式

在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。 在这些情况,新对象的建立就是一个 “过程”,不仅是一个操作,像一部大机器中的一个齿轮传动。

模式的问题:你如何能轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程呢?

解决方案:建立一个工厂来创建对象

实现:

一、引言
    1)还没有工厂时代:假如还没有工业革命,如果一个客户要一款宝马车,一般的做法是客户去创建一款宝马车,然后拿来用。
    2)简单工厂模式:后来出现工业革命。用户不用去创建宝马车。因为客户有一个工厂来帮他创建宝马.想要什么车,这个工厂就可以建。比如想要320i系列车。工厂就创建这个系列的车。即工厂可以创建产品。
    3)工厂方法模式时代:为了满足客户,宝马车系列越来越多,如320i,523i,30li等系列一个工厂无法创建所有的宝马系列。于是由单独分出来多个具体的工厂。每个具体工厂创建一种系列。即具体工厂类只能创建一个具体产品。但是宝马工厂还是个抽象。你需要指定某个具体的工厂才能生产车出来。

   4)抽象工厂模式时代:随着客户的要求越来越高,宝马车必须配置空调。于是这个工厂开始生产宝马车和需要的空调。

   最终是客户只要对宝马的销售员说:我要523i空调车,销售员就直接给他523i空调车了。而不用自己去创建523i空调车宝马车.

   这就是工厂模式。

二、分类 
        工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。 
工厂模式可以分为三类: 

1)简单工厂模式(Simple Factory) 
2)工厂方法模式(Factory Method) 
3)抽象工厂模式(Abstract Factory) 

 这三种模式从上到下逐步抽象,并且更具一般性。 
        GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。

        将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。 

三、区别 
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。   
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。   
每个具体工厂类可以创建多个具体产品类的实例。   
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。   
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
两者皆可。 

 四、简单工厂模式 
建立一个工厂(一个函数或一个类方法)来制造新的对象。
分布说明引子:从无到有。客户自己创建宝马车,然后拿来用。

 

 

[java] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. public class BMW320 {  
  2.     public BMW320(){  
  3.         System.out.println("制造-->BMW320");  
  4.     }  
  5. }  
  6.   
  7. public class BMW523 {  
  8.     public BMW523(){  
  9.         System.out.println("制造-->BMW523");  
  10.     }  
  11. }  
  12.   
  13. public class Customer {  
  14.     public static void main(String[] args) {  
  15.         BMW320 bmw320 = new BMW320();  
  16.         BMW523 bmw523 = new BMW523();  
  17.     }  
  18. }  

客户需要知道怎么去创建一款车,客户和车就紧密耦合在一起了.为了降低耦合,就出现了工厂类,把创建宝马的操作细节都放到了工厂里面去,客户直接使用工厂的创建工厂方法,传入想要的宝马车型号就行了,而不必去知道创建的细节.这就是工业革命了:简单工厂模式

即我们建立一个工厂类方法来制造新的对象。如图:

产品类:

[java] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. abstract class BMW {  
  2.     public BMW(){  
  3.           
  4.     }  
  5. }  
  6.   
  7. public class BMW320 extends BMW {  
  8.     public BMW320() {  
  9.         System.out.println("制造-->BMW320");  
  10.     }  
  11. }  
  12. public class BMW523 extends BMW{  
  13.     public BMW523(){  
  14.         System.out.println("制造-->BMW523");  
  15.     }  
  16. }  

工厂类:

[java] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. public class Factory {  
  2.     public BMW createBMW(int type) {  
  3.         switch (type) {  
  4.           
  5.         case 320:  
  6.             return new BMW320();  
  7.   
  8.         case 523:  
  9.             return new BMW523();  
  10.   
  11.         default:  
  12.             break;  
  13.         }  
  14.         return null;  
  15.     }  
  16. }  


客户类:

[java] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. public class Customer {  
  2.     public static void main(String[] args) {  
  3.         Factory factory = new Factory();  
  4.         BMW bmw320 = factory.createBMW(320);  
  5.         BMW bmw523 = factory.createBMW(523);  
  6.     }  
  7. }  

   简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。 
      先来看看它的组成: 
         1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品
         2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。         
         3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在Java中由一个具体类实现。 
        
        下面我们从开闭原则(对扩展开放;对修改封闭)上来分析下简单工厂模式。当客户不再满足现有的车型号的时候,想要一种速度快的新型车,只要这种车符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想,因为每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑(createBMW(int type)方法需要新增case),这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类或者上帝类。 
        我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员。
        于是工厂方法模式作为救世主出现了。 工厂类定义成了接口,而每新增的车种类型,就增加该车种类型对应工厂类的实现,这样工厂的设计就可以扩展了,而不必去修改原来的代码。
五、工厂方法模式 
        工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。 
工厂方法模式组成: 
       1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 
       2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。 
       3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。 
       4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。 
       工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有 的代码。可以看出工厂角色的结构也是符合开闭原则的! 

代码如下: 

产品类:

[java] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. abstract class BMW {  
  2.     public BMW(){  
  3.           
  4.     }  
  5. }  
  6. public class BMW320 extends BMW {  
  7.     public BMW320() {  
  8.         System.out.println("制造-->BMW320");  
  9.     }  
  10. }  
  11. public class BMW523 extends BMW{  
  12.     public BMW523(){  
  13.         System.out.println("制造-->BMW523");  
  14.     }  
  15. }  


创建工厂类:

[java] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. interface FactoryBMW {  
  2.     BMW createBMW();  
  3. }  
  4.   
  5. public class FactoryBMW320 implements FactoryBMW{  
  6.   
  7.     @Override  
  8.     public BMW320 createBMW() {  
  9.   
  10.         return new BMW320();  
  11.     }  
  12.   
  13. }  
  14. public class FactoryBMW523 implements FactoryBMW {  
  15.     @Override  
  16.     public BMW523 createBMW() {  
  17.   
  18.         return new BMW523();  
  19.     }  
  20. }  


客户类:

[java] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. public class Customer {  
  2.     public static void main(String[] args) {  
  3.         FactoryBMW320 factoryBMW320 = new FactoryBMW320();  
  4.         BMW320 bmw320 = factoryBMW320.createBMW();  
  5.   
  6.         FactoryBMW523 factoryBMW523 = new FactoryBMW523();  
  7.         BMW523 bmw523 = factoryBMW523.createBMW();  
  8.     }  
  9. }  


 工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口,但使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。

参考http://blog.csdn.NET/hguisu/article/details/7505909


以上就是简单工厂模式,工厂方法模式,抽象工厂模式在这里。


微博:http://weibo.com/2553717707

博客:http://blog.csdn.net/jason0539(转载请说明出处)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/464661.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows下搭建ESP-IDF开发环境,适合ESP32/S2/C3/S3系列模组二次开发

前言本教程适用于以下两种用户:①无Linux环境搭建经验或搭建Linux开发环境不成功;②使用安信可windows一体化环境IDE V1.5开发环境搭建不成功;本教程提供了windows下搭建 ESP-IDF 开发环境的方法。适用系统:Windows 10 64 位版本、…

Lync Server 2010的部署系列_第六章 安装配置拓扑生成器、前端Server、前端池

一、安装 Lync Server 2010 管理工具(包括拓扑生成器) 1) 登录Front.Gianthard.com(192.168.1.21)。在“Microsoft Lync Server 2010 - 部署向导”页上,单击“安装拓扑生成器”。 2) 进行SQL方面的客户端。 3) 安装成功…

被 HR 直接怼:估计你一辈子就是个程序员

今天看到一个非常扯蛋的事情。事情来自网络,不是作者本人。我一直认为程序员是可以做一辈子的事情,程序员是一种做得越久技术越熟练的工作。但是有的人并不这样认为。---有程序员因为能力很强,公司非常满意,结果派了一位 HR 与其谈…

一起谈.NET技术,在MVC2.0使用Lodop为WEB打印提出完美解决方案

通过好友CallHot介绍Lodopweb打印控件。由于是国人开发的,故这两天认真了研究下,打算在未来的项目中使用。现将学习成果与园友分享。如果存在不足的地方,希望您指出。 具体的实现步骤如下: 一、准备工作 1.MVC2.0 jQuery1.4.1 开…

(转)python调取C/C++的dll生成方法

本文针对Windows平台下,python调取C/C的dll文件。 1.如果使用C语言,代码如下,文件名为test.c。 __declspec(dllexport) int sum(int a,int b) {return (a b); } 如果使用C语言,代码如下,文件名为test_cpp.cpp。在Wind…

生产者-消费者模式

生产者/消费者问题的多种Java实现方式 实质上,很多后台服务程序并发控制的基本原理都可以归纳为生产者/消费者模式,而这是恰恰是在本科操作系统课堂上老师反复讲解,而我们却视而不见不以为然的。在博文《一种面向作业流(工作流)的轻量级可复用…

周末,说下我喜欢的篮球

我应该有很久没有看NBA比赛了,没有其他原因,确实是因为工作太忙了,即使是在带薪上厕所,也没有足够的时间看下NBA比赛。如果说忙是一个比较好的托词,那还有一个原因,我现在更多的喜欢野球圈的新闻。刚毕业那…

没有串口,如何打印单片机调试信息?

输出调试信息是嵌入式开发中必不可少的调试利器,嵌入式开发的一个特点是很多时候没有操作系统,或者没有文件系统,常规的打印log到文件的方法基本不适用。最常用的是通过串口输出uart log,例如51单片机,只要实现串口驱动…

Linux驱动小技巧 | 利用DRIVER_ATTR实现调用内核函数

1. 前言 很多朋友在调试驱动的时候,都会遇到这样一个场景:修改一个参数,然后调用某个内核中的函数。比如将某个gpio的值拉高/拉低,修改某个寄存器的值等等。如果每一个参数都通过字符设备的ioctl接口,增加对应的cmd&am…

myeclipse运行java项目_myeclipse运行自己从前的或其他人的javaweb项目

1.配置javaweb 连接部署好本地的tomcat服务器方法如下:1.运行Myecipse-->Window-->preference2.MyEclipse-->Servers-->Runtime Environments-->add-->Apache Tomcat v8.03.next->Browser(Tomcat的安装目录)-->finishMyeclipse 设置jdk版本…

MYSQL性能调优及架构设计学习笔记-影响MYSQL性能的相关因素之实例分析

为什么80%的码农都做不了架构师?>>> 需求概述 一个简单的讨论区系统,需要有用户,用户组,组讨论区这三部分基本功能 简要分析 1) 须要存放用户数据的表; 2) 须要存放分组信息和用户与…

软件测试第三次作业

一、开头 (1)合作者:201631062521,201631062421 (2)代码地址:https://gitee.com/h2503652646/WordCount.git (3)本次作业链接地址:https://edu.cnblogs.com/campus/xnsy/Test/homework/2203 二、正文 (1)互审代码情况 已经实现Wor…

Linux驱动开发中与设备树相关的6种debug方法

整理出了6种驱动开发时与设备注册、设备树相关的调试方法,彼此间没有优先级之分,每种方法不一定是最优解,但可以作为一种debug查找问题的手段,快速定位问题原因。例如在芯片验证时,不同时钟频率下系统启动情况摸底时&a…

DiscoveryService.getRemoteAdvertisements是否会获得本地通告?

从该方法名称上来说,应该是不能获得本地通告,本着探究的精神,首先做个小测试,再从源代码中寻找答案。----------------------------------------------------------------------------- 测试结果:本地通告确实取不到&a…

Linux的bc命令计算π的值预估系统算力

这是今天突然想到的一个事情,几年前我和一个朋友做一个开发板,然后我们需要完成的这个开发板有算力的要求,当时我们测试的时候就用了一个shell脚本来分析系统的算力。今天我突然想不起这个命令,然后就想写篇文章记录下&#xff0c…

面向对象的思想是什么?

我同事的回答,我觉得这句话可以读十遍说下我自己的理解你不是人,你是猪。解释一下我们在编写面向对象的代码时,一定要有抽象的思想,什么是抽象,抽象是一种概念的东西,不是实实在在的,看不见摸不…

python编程格式化输出_Python的三种格式化输出

今天刚学了python的三种格式化输出,以前没接触过这么有趣的输出方式,现在来分享一下。#!/user/bin/env python#coding:utf-8#三种格式化输出#第一种格式化输出nameinput("name:")ageinput("age:")jobinput("job:")salaryi…

多线程的异常捕捉

为什么要单独讲多线程的异常捕捉呢?先看个例子: public class ThreadException implements Runnable{Overridepublic void run() {throw new RuntimeException();}//现象:控制台打印出异常信息,并运行一段时间后才停止public stat…

Linux 安装配置JDK 、 MySQL 、nginx

今天我来讲一下在Linux下各环境的搭建,主要就讲一下jdk、MySQL、和一个代理服务器nginx 1、 jdk的安装配置 1)卸载自带openjdk 当我们拿到一个全新的ECS的时候上面有的会自带一个openjdk,但是我们一般不会用这个,所以在这里我们会先卸载这个自…

wat java_并发工具优于wati、notify(69)

现在几乎没有理由在使用wait 和 notify,使用高级工具代替java.util.concurrent 包并发工具分三类:Executor 框架并发集合(concurrent Collection)同步器(synchronizer)并发集合对标准集合接口(List、Map、Queue)封装了高性能的并发实现为了提高并发性&am…