设计模式 — 工厂方法模式(Factory Method)
在开发系统中,经常会碰到一个问题。现在需要实现的一些功能,但是这个功能模块以后一定是需要扩展的,那么现在开发中就不仅要实现现在的功能,还要考虑以后的扩展。那么为了系统的健壮,扩展就要遵循开闭原则(简单说,就是对修改关闭,对扩展开发)。
通过场景例子切入工厂方法模式
要实现这个功能,就是要找到一种方法。可以创建一些操作,但是现在不实现,等着以后来实现这个功能。
现在通过一个人成长过程中学到的技能来展示一下这种方案:
在社会中生存技能千千万万,人也是在不断学习技能的,但是都能学习到那些技能自己也不能确定。但是学习技能是一定的。这时候我们就先定义一个技能的类,但是不知道学习的是什么技能,所以就先实现一个技能接口。
package designPattern_3_FactoryMethod;
//技能接口
public interface ILifeKills {
public void kill();
}
学习的过程不要和技能耦合在一起,需要单独对象来实现,学习的过程就是创建技能对象的过程,所以这个学习对象就是用来生成具体的技能对象的。但是如果是一个人生学习技能方面的框架的话,肯定也不知道学习的是什么技能,那这就是自相矛盾了。怎么办呢?既然是框架,肯定有人来具体实现这个需要学习的技能和具体的学习方式。所以这个我们就知识定义学习方法,但是不定义学习的具体内容,让使用框架的人来实现。这就是定义一个抽象类。
package designPattern_3_FactoryMethod; //抽象学习方法
public abstract class AbstractLearn { public void learn(){
ILifeKills lifekill = factoryMethod();
lifekill.kill();
} protected abstract ILifeKills factoryMethod();
}
下面列出交流、开车的技能
package designPattern_3_FactoryMethod;
//交流技能
public class Talking implements ILifeKills {
public void kill(){
System.out.println("交谈技能");
}
}
package designPattern_3_FactoryMethod; //开车技术
public class Driver implements ILifeKills { @Override
public void kill() {
// TODO Auto-generated method stub
System.out.println("开车技术!");
}
}
具体学习的方法
package designPattern_3_FactoryMethod; //学习交流的对象
public class LearnTalking extends AbstractLearn { public ILifeKills learn(){ return new Talking();
}
}
package designPattern_3_FactoryMethod; //学习开车
public class LearnDriver extends AbstractLearn { @Override
protected ILifeKills factoryMethod() {
// TODO Auto-generated method stub
return new Driver();
} }
客户端调用
package designPattern_3_FactoryMethod; public class Client { public static void main(String[] args) {
AbstractLearn al = new LearnTalking();
al.learn();
AbstractLearn al2 = new LearnDriver();
al2.learn();
}
}
这面展示的例子就是工厂方法模式。只是我只生产一个具体的对象。以后根据需要可以生成对应的技能对象。接下来先看下工厂模式的定义,再结合简单工厂模式分析。结构图
分析工厂方法模式
定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
工厂方法的意义,在父类不知道需要生产具体对象的情况下,能够完成自身的功能调用,具体的实现延迟到其子类,实际上就是工厂类也抽象化了,具体的对象在各自的工厂子类中来实现。
通过定义可以看出:抽象出来具体对象的接口,同时把工厂类也抽象化,这样产品对象和具体工厂都实现各自的抽象类,以后在扩展具体的对象的时候不用修改原来的工厂类,这也更加符合开闭原则。同时也看出来了,工厂方法模式是简单工厂模式的衍生。如果把工厂类的抽象类省略到,用普通类选择实现,那么工厂方法模式就回来到简单工厂模式。
在使用工厂方法的时候要具有灵活性,在一个具体的工厂功法里面可以有多个不同的工厂方法,也可以在一个工厂类中实现十分相近的产品。看着有点类似简单工厂了,但是本质上还是工厂方法的本质。只是形式有些变化而已,但是这不重要。就像学习武功,只要内功深厚,很多招式都能够灵活运用,看似神奇,其实都是内功支撑。而设计模式也是如此。工厂方法模式只要把具体对象的实现延迟到子类,以后扩展工厂时候不用再去修改原来的工厂类,符合了开闭原则。那么就抓住了工厂方法模式的本质。
分析了这么多工厂模式的优点,它当然也有缺点。就是会加大代码的复杂度,如果在不合适的场景中用到很有可能得不偿失。
小结
工厂方法的本质:就是把对象的实现延迟到其子类来实现,使得对产品的扩展更加灵活。这也是工厂方法模式和简单公共的区别。
工厂方法不是不可以选择实现。以我的理解,在一个具体的工厂类中,可以实现相近的产品。以后扩展的时候再派生另外的类就可以了。
下一篇分析抽象工厂模式
设计模式 — 工厂方法模式(Factory Method)的更多相关文章
- 大话设计模式--工厂方法模式 Factory Method -- C++实现
1. 工厂方法模式 定义一个用于创建对象的接口, 让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 和简单工厂模式相比: A: 简单工厂模式最大的优点在于工厂类中包含有必要的逻辑判断, ...
- C#设计模式——工厂方法模式(Factory Method Pattern)
一.概述在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口.如何应对这种变化?如何提供一种封装机制来隔离出“这个易变对象 ...
- [设计模式]工厂方法模式(Factory Method)
模式目的 定义一个用于创建对象的接口,让其子类来决定实例化哪个类. 工厂方法模式将类的实例化延迟到了子类中进行. 模式结构 组成部分 产品(Product) - 定义了产品功能的接口 具体产品(Con ...
- 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)
原文:乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pa ...
- 设计模式-03工厂方法模式(Factory Method Pattern)
插曲.简单工厂模式(Simple Factory Pattern) 介绍工厂方法模式之前,先来做一个铺垫,了解一下简单工厂模式,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背 ...
- 【设计模式】工厂方法模式 Factory Method Pattern
在简单工厂模式中产品的创建统一在工厂类的静态工厂方法中创建,体现了面形对象的封装性,客户程序不需要知道产品产生的细节,也体现了面向对象的单一职责原则(SRP),这样在产品很少的情况下使用起来还是很方便 ...
- 二十四种设计模式:工厂方法模式(Factory Method Pattern)
工厂方法模式(Factory Method Pattern) 介绍定义一个用于创建对象的接口,让子类决定将哪一个类实例化.Factory Method使一个类的实例化延迟到其子类. 示例有SqlMes ...
- 工厂方法模式-Factory Method(Java实现)
工厂方法模式-Factory Method 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法让实例化的具体内容交给子类工厂来进行. 本文中的例子是这样的. 生产一个身份证, ...
- IOS设计模式浅析之工厂方法模式(Factory Method)
概述 在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口. 如何隔离出这个易变对象的变化,使得系统中“其它依赖该对象的对 ...
- 设计模式之工厂方法模式(Factory Method Pattern)
一.工厂方法模式的诞生 在读这篇文章之前,我先推荐大家读<设计模式之简单工厂模式(Simple Factory Pattern)>这篇文档.工厂方法模式是针对简单工厂模式中违反开闭原则的不 ...
随机推荐
- linux下编译visp库
#下载源码git clone "https://github.com/lagadic/visp.git"#work目录mkdir work#build目录mkdir build#c ...
- rs(0)与rs("字段名")的区别
rs(0)与rs("字段名")的区别 注意:rs是RecordSet对象 前者是按sqlyu语句读出来的记录急的先后顺序命名的, rs(0)就是你select ...
- JavaScript数据类型 Math对象详解
前言 javascript使用算术运算符实现基本的算术运算,如果要实现更加复杂的算术运算,需要通过Math对象定义的常量和函数来实现.和其他对象不同,Math只是一个静态对象,并没有Math()构造函 ...
- linux 上安装图形界面
linux 上安装 vncserver 后,图形界面里只有灰底和一个terminal 框, 解决方法: 修改 .vnc/xstartup为 unset SESSION_MANAGER # exec / ...
- Flask-Login用户登陆
Flask-Login Flask-Login 提供用户会话管理,处理常见的登录.退出和注册的任务. Flask-Login 没有绑定数据库,可以从数据库回调用户对象. 安装flask-login p ...
- temp 和 tmp 文件
TMP和TEMP文件是各种软件或系统产生的临时文件,也就是常说的垃圾文件.Windows产生的临时文件,本质上和虚拟内存没什么两样,只不过临时文件比虚拟内存更具有针对性,单独为某个程序服务而已.而它的 ...
- 学习itop4412开发板有哪些资料可学习?能否学会
1.光盘资料 下面简单的做一下了解,在需要使用这些资料的时候,会针对性的做详细介绍. 将文件以及文件夹按照“名称+递增”的方式排列,如下: 01_PCB_SCH_DATASHEET-- -----开发 ...
- 记录一个使用HttpClient过程中的一个bug
最近用HttpClient进行链接请求,开了多线程之后发现经常有线程hang住,查看线程dump java.lang.Thread.State: RUNNABLE at java.net.Socket ...
- Burp插件开发——环境配置
最近打算开发个Burp插件,从网上各种地找资料学习.第一步就应该是环境配置,请见下文. (其实最重要的前提是你已经安装了Burp,否则下面的所有内容都是无稽之谈了. https://pan.baidu ...
- Mac安装SecureCRT
8.3.1版本 链接:https://pan.baidu.com/s/1ohHunH_OVewF4QuRUzmChQ 密码:mc77 下载解压后直接是.app 直接打开会提示文件损害 打开终端,输入如 ...