261-模式的秘密---工厂模式
系列课程:模式宗师养成宝典之Java版
http://www.imooc.com/learn/261
简介:工厂模式和抽象工厂模式是在日常开发中使用非常广泛的设计模式。主要用于实现将对象的实例化部分取出来,进而优化系统架构,增强系统的扩展性。本课程即将讲解Java中的工厂模式和抽象工厂模式的应用。
目录
第1章 工厂模式概述
本章主要介绍工厂模式的基本概念。
1-1 工厂模式概述 (10:29)
什么是设计模式?
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结
应用设计模式的好处?
设计模式是优秀的使用案例
使用设计模式可提高代码的重用性
让代码更容易被他人理解
保证代码可靠性
重点内容
- 工厂模式的概念
- 工厂模式的意图
- 工厂模式的应用场景
- 工厂模式的设计思想
- 工厂模式的好处
工厂模式的概念
实例化对象,用工厂方法代替new操作
工厂模式包括工厂方法模式和抽象工厂模式
抽象工厂模式是工厂方法模式的扩展
工厂模式的意图
定义一个接口来创建对象,但是让子类来决定哪些类需要被实例化
工厂方法把实例化的工作推迟到子类中去实现
什么情况下适合工厂模式
有一组类似的对象需要创建
在编码时不能预见需要创建哪种类的实例
系统需要考虑扩展性,不应依赖于产品类实例如何被创建、组合和表达的细节
项目中的现状
在软件系统中经常面临着“对象”的创建工作,由于需求的变化,这个对象可能随之也会发生变化,但它却拥有比较稳定的接口。为此,我们需要提供一种封装机制来隔离出这个易变对象的变化,从而保证系统中其他依赖该对象的对象不随着需求变化而变化。
基于项目现状将代码进行如下设计
- 尽量松耦合,一个对象的依赖对象的变化与本身无关
- 具体产品与客户端剥离,责任分割
工厂方法模式类图

抽象工厂模式类图


第2章 工厂模式应用
本章通过案例演示工厂模式的应用。
2-1 工厂模式应用 (22:18)
发型接口HairInterface.java
public interface HairInterface { // 画发型 void draw(); }
左偏分发型LeftHair.java
public class LeftHair implements HairInterface { @Override public void draw() { System.out.println("左偏分发型"); } }
右偏分发型RightHair.java
public class RightHair implements HairInterface { @Override public void draw() { System.out.println("右偏分发型"); } }
中分发型InHair.java
public class InHair implements HairInterface { @Override public void draw() { System.out.println("中分发型"); } }
配置文件application.properties
left=com.tuyrk.hair.impl.LeftHair right=com.tuyrk.hair.impl.RightHair in=com.tuyrk.hair.impl.InHair
properties文件的读取工具类PropertiesReader.java
public class PropertiesReader { // 获取配置文件的属性 public static Map<String, String> getProperties() { Map<String, String> map = new HashMap<>(); try { Resource resource = new ClassPathResource("application.properties"); Properties props = PropertiesLoaderUtils.loadProperties(resource); Enumeration<?> en = props.propertyNames(); while (en.hasMoreElements()) { String key = (String) en.nextElement(); String property = props.getProperty(key); map.put(key, property); } } catch (IOException e) {} return map; } }
发型工厂HairFactory.java
public class HairFactory { /** * 根据类型来创建对象 * @param key 发型种类 * @return 发型实例 */ public HairInterface getHair(String key) { if ("left".equals(key)) { return new LeftHair(); } else if ("right".equals(key)) { return new RightHair(); } return null; } /** * 根据类的名称来生产对象 * @param className 类名 * @return 发型实例 */ public HairInterface getHairByClass(String className) { try { return (HairInterface) Class.forName(className).newInstance(); } catch (Exception e) {} return null; } /** * 根据类的名称来生产对象 * @param key 类名对应名称 * @return 发型实例 */ public HairInterface getHairByClassKey(String key) { try { Map<String, String> map = PropertiesReader.getProperties(); return (HairInterface) Class.forName(map.get(key)).newInstance(); } catch (Exception e) {} return null; } }
测试类Test.java
public class Test { public static void main(String[] args) { // 每需要创建一个发型都需要重新new,并且调用draw() /*HairInterface left = new LeftHair(); left.draw(); HairInterface right = new RightHair(); right.draw();*/ // if-else实现 /*HairFactory factory = new HairFactory(); HairInterface left = factory.getHair("left"); left.draw();*/ // className实现 /*HairFactory factory = new HairFactory(); *//*HairInterface left = factory.getHairByClass("com.tuyrk.hair.impl.LeftHair");*//* HairInterface left = factory.getHairByClass(LeftHair.class.getName()); left.draw();*/ // 读取properties实现 HairFactory factory = new HairFactory(); HairInterface hair = factory.getHairByClassKey("in"); hair.draw(); } }
第3章 抽象工厂模式应用
本章通过案例演示抽象工厂模式的应用
3-1 抽象工厂模式应用 (12:34)
男孩Boy.java
public interface Boy { void drawMan(); }
女孩Girl.java
public interface Girl { void drawWomen(); }
新年系列的男孩HNBoy.java
public class HNBoy implements Boy { @Override public void drawMan() { System.out.println("新年男孩"); } }
新年系列的女孩HNGirl.java
public class HNGirl implements Girl { @Override public void drawWomen() { System.out.println("新年女孩"); } }
圣诞系列的男孩MCBoy.java
public class MCBoy implements Boy { @Override public void drawMan() { System.out.println("圣诞男孩"); } }
圣诞系列的女孩MCGirl.java
public class MCGirl implements Girl { @Override public void drawWomen() { System.out.println("圣诞女孩"); } }
人物的实现接口PersonFactory.java
public interface PersonFactory { // 男孩接口 Boy getBoy(); // 女孩接口 Girl getGirl(); }
新年系列工厂HNFactory.java
public class HNFactory implements PersonFactory { @Override public Boy getBoy() { return new HNBoy(); } @Override public Girl getGirl() { return new HNGirl(); } }
圣诞系列工厂MCFactory.java
public class MCFactory implements PersonFactory { @Override public Boy getBoy() { return new MCBoy(); } @Override public Girl getGirl() { return new MCGirl(); } }
测试类Test.java
public class Test { public static void main(String[] args) { // 圣诞女孩 PersonFactory mcFactory = new MCFactory(); Girl girl = mcFactory.getGirl(); girl.drawWomen();// 圣诞女孩 // 新年男孩 PersonFactory hnFactory = new HNFactory(); Boy boy = hnFactory.getBoy(); boy.drawMan();// 新年男孩 } }
第4章 总结
总结工厂模式和抽象工厂模式的应用。
4-1 总结 (06:06)
场景应用
JDBC
是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成
Spring BeanFactory
BeanFactory,作为Spring基础的IoC容器,是Spring的一个Bean工厂。如果单从工厂模式的角度思考,他就是用来“生产Bean”,然后提供给客户端。
Bean的实例化过程如下:
- 调用Bean的默认构造方法,或指定的构造方法,生成bean实例(暂称为instance1)
- 如果Bean的配置文件中注入了Bean属性值,则在instance1基础上进行属性注入形成instance2,这种注入是覆盖性的。
- 如果Bean实现了InitializingBean接口,则调用afterPropertiesSet()方法,来改变或操作instance2,得到instance3
- 如果Bean的配置文件中指定了init-method=”init”属性,则会调用指定的初始化方法,则在instance3的基础上调用初始化方法init(),将对象最终初始化为instance4;当然,这个初始化的名字是任意的。
工厂方法模式和抽象工厂模式对比
工厂模式是一种极端情况下的抽象工厂模式,而抽象工厂模式可以看成是工厂模式的推广。
工厂模式用来创建一个产品的等级结构,而抽象工厂模式是用来创建多个产品的等级结构
工厂模式只有一个抽象产品类,而抽象工厂模式有多个抽象产品类
工厂模式的实现帮助我们
系统可以在不修改具体工厂角色的情况下引进新的产品
客户端不必关心对象如何创建,明确了职责
更好的理解面向对象的原则。面向接口编程,而不要面向实现编程
工厂模式适用于哪些场景
一个系统应当不依赖于产品类实例被创立,组成和表示的细节。这对所有形态的工厂模式都是重要的
这个系统的产品有至少一个的产品族
同属于一个产品族的产品是设计成在一起使用的。这个约束必须得在系统的设计中体现出来
不同的产品以一系列的接口的面貌出现,从而使系统不依赖于接口实现的细节
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 tuyrk@qq.com
文章标题:261-模式的秘密---工厂模式
文章字数:2.1k
本文作者:神秘的小岛岛
发布时间:2019-12-15, 11:57:46
最后更新:2020-01-05, 14:33:25
原始链接:https://www.tuyrk.cn/imooc/261-factory-mode/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。