工厂方法模式 名字 跟已经介绍的 简单工厂模式很类似.

实际上它们的模型也是十分相似的.

我们先看看工厂模式的定义.

一. 工厂方法(Factory Method)模式定义

教材上是这样写的:

工厂方法模式(Factory Method):

定义1个用于创建对象的接口, 让子类决定实例化哪个类.   工厂模式使1个类的实例化延迟到其子类.

是不是觉得定义很恶心, 我也觉得, 刚开始完全看不懂啊.

这里稍稍先分析一下.

定义1个用于创建对象的接口, 让子类决定实例化哪个类.   工厂模式使1个类的实例化延迟到其子类.

上面那句话出现了4个对象.

分别是: 对象 接口 类 子类

它们的关系是这样的:

是指业务类,

对象  的实例化对象.

接口 指Java 的 interface 或者 抽象类. (工厂)

子类接口 的子类(或者叫实现类).

(工厂)子类 会创建1个 (业务)类对象

至于延迟是什么意思?  还是在下面举个例子来讲把.

二. 手机的例子.

显示上手机有很多种. (包括Nokia手机, BlackBerry手机)

常用的功能有3种.

1. 打电话,

2. 发邮件.

3. 播放mp3.

现在有个人很有钱任性.

他有3台Nokia , 1台在打电话, 一台发邮件, 一台听歌..

用代码如何实现呢.

三. 简单工厂模式实现.

UML:

CellPhone接口:

public interface CellPhone {public abstract void call();public abstract void playMusic();public abstract void sendEmail();
}

BlackBerry:

public class BlackBerry implements CellPhone {@Overridepublic void call(){System.out.println("calling by BlackBerry");}@Overridepublic void playMusic(){System.out.println("playing Music by BlackBerry");}@Overridepublic void sendEmail(){System.out.println("sending Email by BlackBerry");}}

Nokia:

public class Nokia implements CellPhone {@Overridepublic void call(){System.out.println("calling by nokia");}@Overridepublic void playMusic(){System.out.println("playing Music by nokia");}@Overridepublic void sendEmail(){System.out.println("sending Email by nokia");}}

工厂类CellPhoneFactory:

public class CellPhoneFactory {public static CellPhone createCellPhone(String name){CellPhone p = null;switch(name){case "Nokia" : p = new Nokia(); break;case "BlackBerry" : p = new BlackBerry(); break;}return p;}
}

客户端:

 String name = "Nokia";CellPhone p = CellPhoneFactory.createCellPhone(name);CellPhone p2 = CellPhoneFactory.createCellPhone(name);CellPhone p3 = CellPhoneFactory.createCellPhone(name);p.call();p2.sendEmail();p3.playMusic();

四. 简单工厂的1个缺点.

简单工厂对客户端封装了真正的业务类, 这是以前说过的.

但是如果我要增加1个业务, 例如那个人想用一台Sony手机.

除了修改客户端代码外

那么我必须新增1个Sony类  -> 符合封闭-开放原则

还必须修改工厂类代码, 增加1个case 字句 -> 不符合封闭-开放原则,     原则上是不应该修改原有类的.

五. 工厂方法的实现.

UML:

其中CellPhone, BlackBerry, Nokia3个类或接口跟上面是一样的没有变化.

工厂抽象类CellPhoneFactory:

现在这个类变成了抽象类了.

public abstract class CellPhoneFactory {public abstract CellPhone createCellPhone();
}

NokiaFactory:

Nokia工厂, 只会创建Nokia对象,  而且创建对象的方法已经不是静态方法, 需要实例化1个工厂来创建.

public class NokiaFactory extends CellPhoneFactory{@Overridepublic CellPhone createCellPhone(){return new Nokia();}
}

BlackBerryFactory:

public class BlackBerryFactory extends CellPhoneFactory{@Overridepublic CellPhone createCellPhone(){return new BlackBerry();}
}

客户端代码:

 CellPhoneFactory factory = new NokiaFactory();CellPhone p = factory.createCellPhone();CellPhone p2 = factory.createCellPhone();CellPhone p3 = factory.createCellPhone();p.call();p2.sendEmail();p3.playMusic();

六. 工厂方法与简单工厂方法的区别.

好了, 通过对比, 我们知道区别如下:

1. 简单工厂的工厂类是1个非抽象类.  而工厂方法的工厂类是一个抽象类(或者接口), 它下面还有子类.

2. 简单工厂的业务类对象由工厂类的静态方法直接创建, 而工厂方法的业务类对象由工厂类的子类来创建.

这个就是工厂方法里, 那句" 工厂模式使1个类的实例化延迟到其子类" 的原因,  延迟是相当于简单工厂来讲的.

如果要新增1个sony手机.

工厂方法, 除了修改客户端代码之外,

还需要

新加个sony手机类.

新家1个sony手机工厂类.

看起来是完全符合开放-封闭原则的.

但是实际上,  简单工厂方法的判断在工厂类的switch字句内.

而工厂方法看起来不需要判断, 但实际上是把判断交给了客户端.

也就是说这一句

CellPhoneFactory factory = new NokiaFactory();

客户端需要自己判断使用哪个工厂.

而简单工厂只需要传入"Nokia"的名字就得到对应的业务对象.

有没有折中方法呢? 就是只需要手机名字的参数,  而且符合开放封闭原则的写法.

那就需要利用java里的反射机制.(所谓反射就是可以根据类名获取哪个类的对象或其他资源)

七. 反射简单工厂.

重写简单工厂的工厂类,   不使用switch 字句, 而是java的反射..

public class CellPhoneReflectFactory {public static CellPhone createCellPhone(String name){Class<?> c = null;Class<?>[] argTypes = {}; //指明所要调用的构造方法的形参  Constructor<?> cst = null;CellPhone p = null;Object obj = null;try {c = (Class<?>) Class.forName("factory.simple." + name);cst = c.getConstructor(argTypes);//获取指定参数的构造方法obj = cst.newInstance(argTypes);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}p = (CellPhone)obj;return p;}
}

而客户端的写发不需要改变, 新增业务类也无需修改这个工厂类了.

工厂方法模式(Factory Method)简介相关推荐

  1. 【设计模式】工厂方法模式 Factory Method Pattern

    在简单工厂模式中产品的创建统一在工厂类的静态工厂方法中创建,体现了面形对象的封装性,客户程序不需要知道产品产生的细节,也体现了面向对象的单一职责原则(SRP),这样在产品很少的情况下使用起来还是很方便 ...

  2. 设计模式之六:工厂方法模式(Factory method Pattern)

    工厂方法(Factory Method)模式就是定义一个创建对象的工厂接口,将实际创建工作推迟到子类当中. 核心工厂类不再负责具体产品的创建,仅提供了具体工厂子类必须实现的接口,这样核心类成为一个抽象 ...

  3. 设计模式之工厂方法模式(Factory Method)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式包括:1.FactoryMethod(工厂方法模式):2.Abstract Factory(抽象工厂模式):3.Sin ...

  4. 设计模式之工厂方法模式---factory method

    模式的介绍 模式的定义 Define an interface for creating an object,but let subclassed decide which class to inst ...

  5. 软件工程 - 设计模式学习之工厂方法模式Factory Method

    在现实生活中我们可以看见,乐事在卖薯片,可比克也在卖. 我敢肯定的说它们各自都有自己的工厂来生产薯片,而且生产出来的薯片味道还是不一样的. 这就是我们这里所谓的工厂方法模式. 我们来看看这个模式的UM ...

  6. 设计模式之工厂方法模式(Factory Method Pattern)

    一.工厂方法模式的诞生 在读这篇文章之前,我先推荐大家读<设计模式之简单工厂模式(Simple Factory Pattern)>这篇文档.工厂方法模式是针对简单工厂模式中违反开闭原则的不 ...

  7. 设计模式题目-工厂方法模式(Factory Method)

    设计一个程序来读取多种不同存储格式的图片,针对每一种图片格式都设计一个图片读取器(ImageReader),如GIF格式图片读取器(GifReader)用于读取GIF格式的图片,JPEG格式图片读取器 ...

  8. C++实现工厂方法模式Factory Method Pattern

    设计原则6:要依赖抽象,不要依赖具体类.(又称依赖倒置原则Dependency Inversion Principle) 不能让高层组件依赖低层组件,而且,不管高层组件或低层组件,两者都应该依赖于抽象 ...

  9. 极速理解设计模式系列:9.工厂方法模式(Factory Method Pattern)

    五个角色:产品角色(Product).真实产品角色(ConcreteProduct).工厂角色(Creator).真实工厂角色(ConcreteCreator).客户端(Client) 产品角色(Pr ...

最新文章

  1. Python Qt GUI设计:如何调整组件布局比例?(拓展篇—1)
  2. 定义了浮动元素后margin-bottom失效的解决办法
  3. Pandas中兼并数组和字典功能的Series 2013-03-24 11:24:00 分类: Python/Ruby In [2]: # 这段代码用于并排显示多个Series对象 from it
  4. 协调器太多,cc2530的终端或则路由器选择性加入协调器的方法
  5. android led闪烁功能,如何在Android应用层中制作一个LED指示灯效果
  6. :批量制作档案表,要从excel表格中将每个人的数据导入到docx档案
  7. Oracle学习总结(3)——Navicat客户端连接Oracle数据库常见问题汇总
  8. IIS 返回 405 - 不允许用于访问此页的 HTTP 谓词。终极解决办法!!!!
  9. MySql安装错误代码1045的解决方案
  10. 语音识别行业成长红利期已过,行业寡头显现,小公司生存状况堪忧
  11. 不通用版(从SVN取版本,通过MAVEN生成JAVA包,通过SALTSTACK传送到远程服务器并自动重启TOMCAT服务)PYTHON代码...
  12. 生产级mysql双写_生产级Mysql物理全量备份-Xtrabackup
  13. 优酷吃土豆后果严重么?
  14. java命名规则及规范
  15. XUI 熟练使用之(一) ----------- 将 XUI 引入项目
  16. linux sftp连接报错:JSchException: Algorithm negotiation fail问题的解决方法
  17. 冠军方案解读 | nnUNet改进提升笔记
  18. Unity Sunny Land开发流程(二)
  19. 如何设置过滤器Filter
  20. 4.1.3.9 监听网络状态,3G,WIFI,

热门文章

  1. 删除-ARMV8-V9-ATF-FFA学习笔记目录-2021-08
  2. [思考]-32位的应用程序为什么不能跑64位的应用程序
  3. armv8/armv7中SCTLR的区别
  4. Boost Part III. 函数对象与高级编程 Library 10. Lambda 用法 switch_statement
  5. 移动重定位表到新增节
  6. vector邻接表建图+DFS+BFS
  7. C++实现仿射加密法
  8. photoshop学习笔记(一)2015-12-4【新浪云搬运】
  9. 【rsyslogd】rsyslog 中 timereported 与 timegenerated 区别
  10. sublime text 3170 破解工具