设计模式 — 工厂方法模式(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)>这篇文档.工厂方法模式是针对简单工厂模式中违反开闭原则的不 ...
随机推荐
- 苹果“抄袭”雷军PPT?小米高管如此评论
3月26日凌晨,苹果如期举行了春季发布会,但发布会上并没有发布任何新硬件,主角全部是电视.游戏.信用卡等软件新品,值得一提的是,在苹果PPT上,有一张将硬件/软件/服务三部分单独提炼出来. “抄袭”雷 ...
- [Luogu 4245] 任意模数NTT
Description 给定 \(2\) 个多项式 \(F(x), G(x)\),请求出 \(F(x) * G(x)\). 系数对 \(p\) 取模,且不保证 \(p\) 可以分解成 \(p = a ...
- Python中eval函数的作用
eval eval函数就是实现list.dict.tuple与str之间的转化str函数把list,dict,tuple转为为字符串# 字符串转换成列表a = "[[1,2], [3,4], ...
- Zabbix 监控触发器设置
简述 在生产环境中,有一台mysql的备份服务器,上面运行着三个数据库实例的从库,也在做日志的同步工作,为了实现对该备份服务器的监控,当出现从库实例不为3或者日志同步进程不为3的时候,产生告警通知,生 ...
- redis基础知识思维导图
看到一张redis的基础知识思维导图,比较清晰, 但是没有标明来源,希望知道的给个地址,我也好说明来源 图大小有1M多.在博客上看比较模糊,可以先下载下来查看,或者在浏览器新标签中打开图片查看,就比较 ...
- 把xml数据直接插入到sqlserver数据库
存储过程: ALTER proc [ali].[ins_冻结金额表] @xmldoc varchar(max), ) as declare @idoc int exec sp_xml_prepared ...
- CMakeList.txt(3): 一个cmake实例
介绍一个比较实用的例子,即包含生成静态库又包含引入外部头文件和链接库的cmake demo. 先按照工程规范建立工程目录,并编写代码,以下面的工程目录为例进行解释这个例子,工程的目录结构为: 1. 编 ...
- mac-redis安装与使用
安装: brew install redis --------------- 使用: 启动redis-server: sudo redis-server 连接:./redis-cli -h 127.0 ...
- kubernetes之flannel
kubernetes网络通信 容器间的通信 pod内的容器通信(lo) Pod之间的通信 pod IP <-----> pod IP Pod与Service之间的通信 podIP ...
- 【SQL】ROW_NUMBER() OVER(partition by 分组列 order by 排序列)用法详解+经典实例
#用法说明 select row_number() over(partition by A order by B ) as rowIndex from table A :为分组字段 B:为分组后的排序 ...