当前位置: 首页 > news >正文

Java设计模式——工厂设计模式

工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类。
工厂模式的形态
工厂模式主要用一下几种形态:
1:简单工厂(Simple Factory)。
2:工厂方法(Factory Method)。
3:抽象工厂(Abstract Factory)。

简单工厂(Simple Factory)
又叫静态工厂,是工厂模式三中状态中结构最为简单的。主要有一个静态方法,用来接受参数,并根据参数来决定返回实现同一接口的不同类的实例。我们来看一个具体的例子:
假设一家工厂,几生产洗衣机,有生产冰箱,还有空调等等..
我们先为所有产品定义一个共同的产品接口

public interface Product{} 


接着我们让这个工厂的所有产品都必须实现此接口

public class Washer implements Product{ 

   public Washer(){ 

       System.out.println("洗衣机被制造了"); 

   } 

 

public class Icebox implements Product{ 

   public Icebox(){ 

       System.out.println("冰箱被制造了"); 

   } 

 

public class AirCondition implements Product{ 

   public Icebox(){ 

       System.out.println("空调被制造了"); 

   } 


接下来我们来写一个工厂类,有它来负责生产以上的产品

public class SimpleFactory { 

     

    public static Product factory(String productName) throws Exception{ 

        if(productName.equals("Washer")){ 

            return new Washer(); 

        }else if(productName.equals("Icebox")){ 

            return new Icebox(); 

        }else if(productName.equals("AirCondition")){ 

            return new AirCondition(); 

        }else

            throw new Exception("没有该产品"); 

        } 

    } 


好了,有了这个工厂类,我们就可以开始下定单了,SimpleFactory将根据不同的定单类决定生产什么产品。

public static void main(String[] args) { 

    try { 

              SimpleFactory.factory("Washer"); 

              SimpleFactory.factory("Icebox"); 

              SimpleFactory.factory("AirCondition"); 

            } catch (Exception e) { 

        e.printStackTrace(); 

    } 


由上面的代码可以看出,简单工厂的核心就是一个SimpleFactory类,他拥有必要的逻辑判断能力和所有产品的创建权利,我们只需要向把定单给他,就能得到我们想要的产品。这使用起来似乎非常方便。
但,实际上,这个SimpleFactory有很多的局限。首先,我们每次想要增加一种新产品的时候,都必须修改SimpleFactory的原代码。其次,当我们拥有很多很多产品的时候,而且产品之间又存在复杂的层次关系的时候,这个类必须拥有复杂的逻辑判断能力,其代码量也将不断地激增,这对以后的维护简直就是恐怖两个字...
还有就是,整个系统都严重依赖SimpleFactory类,只要SimpleFactory类一出问题,系统就进入不能工作的状态,这也是最为致命的一点....
以上的不足将在工厂模式的另外两种状态中得到解决。

工厂方法(Factory Method)
上面的代码告诉我们,简单工厂并不简单,它是整个模式的核心,一旦他出了问题,整个模式都将受影响而不能工作,为了降低风险和为日后的维护、扩展做准备,我们需要对它进行重构,引入工厂方法
工厂方法为工厂类定义了接口,用多态来削弱了工厂类的职能,以下是工厂接口的定义:

public interface Factory{ 

  public Product create(); 


我们再来定义一个产品接口

public interface Product{} 


一下是实现了产品接口的产品类

public class Washer implements Product{ 

   public Washer(){ 

       System.out.println("洗衣机被制造了"); 

   } 

 

public class Icebox implements Product{ 

   public Icebox(){ 

       System.out.println("冰箱被制造了"); 

   } 

 

public class AirCondition implements Product{ 

   public Icebox(){ 

       System.out.println("空调被制造了"); 

   } 


接下来,就是工厂方法的核心部分,也就是具体创建产品对象的具体工厂类,

//创建洗衣机的工厂 

public class CreateWasher implements Factory{ 

    public Product create(){ 

          return new Washer(); 

    } 

 

//创建冰箱的工厂 

public class CreateIcebox implements Factory{ 

    public Product create(){ 

          return new Icebox(); 

    } 

 

//创建空调的工厂 

public class CreateAirCondition implements Factory{ 

    public Product create(){ 

          return new AirCondition(); 

    } 


从上面创建产品对象的代码可以看出,工厂方法简单工厂的主要区别是,简单工厂是把创建产品的职能都放在一个类里面,而工厂方法则把不同的产品放在实现了工厂接口的不同工厂类里面,这样就算其中一个工厂类出了问题,其他工厂类也能正常工作,互相不受影响,以后增加新产品,也只需要新增一个实现工厂接口工厂类,就能达到,不用修改已有的代码。但工厂方法也有他局限的地方,那就是当面对的产品有复杂的等级结构的时候,例如,工厂除了生产家电外产品,还生产手机产品,这样一来家电是手机就是两大产品家族了,这两大家族下面包含了数量众多的产品,每个产品又有多个型号,这样就形成了一个复杂的产品树了。如果用工厂方法来设计这个产品家族系统,就必须为每个型号的产品创建一个对应的工厂类,当有数百种甚至上千种产品的时候,也必须要有对应的上百成千个工厂类,这就出现了传说的类爆炸,对于以后的维护来说,简直就是一场灾难.....

抽象工厂(Abstruct Factory)
抽象工厂:意的意图在于创建一系列互相关联或互相依赖的对象。<<Java设计模式>>
我自己觉得抽象工厂是在工厂方法的基础上引进了分类管理的概念....
工厂方法用来创建一个产品,它没有分类的概念,而抽象工厂则用于创建一系列产品,所以产品分类成了抽象工厂的重点,
我们继续用上面的例子来说明:
工厂生产的所有产品都用都用大写字母来标明它们的型号,比如冰箱,就有“冰箱-A",“冰箱-B",同样,其他的产品也都是遵守这个编号规则,于是就有了一下产品家族树

冰箱:


  1.   
  2. 冰箱-A  
  3. 冰箱-B


洗衣机:


  1.   
  2. 洗衣机-A  
  3. 洗衣机-B


我们可以为冰箱和洗衣机分别定义两个产品接口,以对他们进行分类,

//洗衣机接口 

public interface Washer{ 

 

//冰箱接口 

public interface Icebox{ 


接着,我们分别创建这两个接口的具体产品

//洗衣机-A 

public class WasherA implements Washer{ 

   public WasherA(){ 

       System.out.println("洗衣机-A被制造了"); 

   } 

 

//洗衣机-B 

public class WasherB implements Washer{ 

   public WasherB(){ 

       System.out.println("洗衣机-B被制造了"); 

   } 

 

//冰箱-A 

public class IceboxA implements Icebox{ 

   public IceboxA(){ 

       System.out.println("冰箱-A被制造了"); 

   } 

 

//冰箱-B 

public class IceboxB implements Icebox{ 

   public IceboxB(){ 

       System.out.println("冰箱-B被制造了"); 

   } 


到此,产品部分我们准备好了,接下来我们来处理工厂部分,我们先来定义工厂行为接口

public interface Factory{ 

       public Washer createWasher(); 

       public Icebox createIcebox(); 


接下来我创造具体的工厂类,我们根据上面产品的接口,把型号A的产品分为一类,由一个工厂来管理,把型号为B的产品有另一个工厂管理,根据这个分类,我们可以实现如下的两个具体工厂类

//创建型号为A的产品工厂 

public class FactoryA implements Factory{ 

       //创建洗衣机-A 

       public Washer createWasher(){ 

            return new WasherA(); 

       } 

 

       //创建冰箱-A 

       public Icebox createIcebox(){ 

            return new IceboxA(); 

       } 

 

//创建型号为B的产品工厂 

public class FactoryB implements Factory{ 

       //创建洗衣机-B 

       public Washer createWasher(){ 

            return new WasherB(); 

       } 

 

       //创建冰箱-B 

       public Icebox createIcebox(){ 

            return new IceboxB(); 

       } 


这样,我们的抽象工厂就完成了。有上面可以看出,在运用上我觉得工厂方法和抽象工厂,都有自己的应用场景,并没有什么优劣之分,但在应用抽象工厂之前,要先对创建的对象进行系统的分类,这点很重要,好的产品分类规则能为具体工厂类的选择调用和以后的扩展提供清晰的思路.

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Java开发中的23种设计模式详解(转)
  • CMMI学习
  • NetConf协议说明
  • HashMap 与 ConcurrentHashMap
  • java-策略模式
  • SNMP4J简介
  • SNMP 使用SNMP4J V2进行TRAP
  • JTable的清空小技巧以及JTable的详细介绍
  • JFrame简单的例子
  • org.apache.catalina.deploy.WebXml addFilter
  • Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modules
  • myEclipse中的web项目直接引入到eclipse中运行
  • 常用的网络传输协议
  • extjs3.2中datefield和comboBox使用readOnly不正常显示
  • spring两个重要属性lazy-init和abstract
  • [nginx文档翻译系列] 控制nginx
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • 【React系列】如何构建React应用程序
  • css布局,左右固定中间自适应实现
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • Docker下部署自己的LNMP工作环境
  • Hibernate【inverse和cascade属性】知识要点
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • JDK9: 集成 Jshell 和 Maven 项目.
  • k8s 面向应用开发者的基础命令
  • node和express搭建代理服务器(源码)
  • node入门
  • socket.io+express实现聊天室的思考(三)
  • windows下使用nginx调试简介
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 实战|智能家居行业移动应用性能分析
  • 硬币翻转问题,区间操作
  • 自制字幕遮挡器
  • 7行Python代码的人脸识别
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • # Redis 入门到精通(七)-- redis 删除策略
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • $NOIp2018$劝退记
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (搬运以学习)flask 上下文的实现
  • (层次遍历)104. 二叉树的最大深度
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (每日一问)操作系统:常见的 Linux 指令详解
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (转)拼包函数及网络封包的异常处理(含代码)
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • (自适应手机端)行业协会机构网站模板
  • .net core + vue 搭建前后端分离的框架
  • .NET Core 版本不支持的问题
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)