Java 设计模式之工厂模式(二)
原文地址:Java 设计模式之工厂模式(二)
博客地址:http://www.extlight.com
一、背景
本篇内容是 Java 设计模式创建型模式的第二篇。上一篇主题为 《Java 设计模式之单例模式(一)》
二、简单介绍
在介绍工厂模式之前,我们需要了解设计模式中应该遵循的原则。
五大原则:
单一职责原则(SRP):就一个类而言,应该仅有一个引起它变化的原因。即一个类中应该只有一类逻辑。
开放-封闭原则(OCP):软件实体(类、模块、函数等等)应该可以扩展,但是不可修改。即开放扩展,封闭修改。
依赖倒转原则(DIP):高层模块不应该依赖底层模块。两个都应该依赖抽象;抽象不应该依赖细节。细节应该依赖抽象。即面向接口编程,而不是面向实现编程。
里氏代换原则(LSP):子类型必须能够替换掉他们的父类型。
合成/聚合复用原则(CARP):尽量使用合成/聚合,尽量不要使用类继承。
迪米特法则:如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一方法的话,可以通过第三者转发这个调用
三、实现方式
工厂模式有 3 种:简单工厂模式、工厂方法模式和抽象工厂模式。
本篇文章只讲解简单工厂模式、工厂方法模式。因为简单工厂模式和工厂方法模式是针对单独一类产品的创建方式,而抽象工厂模式是针对产品族考虑。
我们以创建轿车为例,未使用工厂模式:
public abstract class Car {
public abstract void run();
}
public class Benz extends Car {
@Override
public void run() {
System.out.println("开奔驰");
}
}
public class Bmw extends Car{
@Override
public void run() {
System.out.println("开宝马");
}
}
public class Client {
public static void main(String[] args) {
Car car1 = new Benz();
car1.run();
Car car2 = new Bmw();
car2.run();
}
}
在 Client 类中既有创建对象逻辑又有调用方法逻辑,且与多个类发生耦合。违背了单一职责原则和迪米特法则。
UML 类图表示如下:

3.1 简单工厂模式
简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
工厂类:
public class CarFactory {
public static Car createCar(String type) {
Car car = null;
switch (type) {
case "benz":
car = new Benz();
break;
case "bmw":
car = new Bmw();
break;
}
return car;
}
}
客户端调用:
public class Client {
public static void main(String[] args) {
Car car1 = CarFactory.createCar("benz");
car1.run();
Car car2 = CarFactory.createCar("bmw");
car2.run();
}
}
总结:Client 类与 Car 的子类解耦,它不需要知道 Car 实例具体创建细节,只需要通知工厂类需要怎样的实例。这样,减少了与外部类(Car 的子类)的通信,遵循了迪米特法则。
UML 类图表示如下:

3.2 工厂方法模式
简单工厂模式设计和使用非常简单。当我们需要新品牌的车子(如:奥迪)时,只需要在 CarFactory 的静态方法中添加一个判断即可。但是,这种写法违背了开放封闭原则,我们在编码是尽量不要修改业务代码。
为了解决这一问题,我们可以使用工厂方法模式。
工厂方法模式同样属于类的创建型模式又被称为多态工厂模式。工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。
创建父类工厂:
public interface CarFactory {
Car createCar();
}
工厂实现类:
public class BenzFactory implements CarFactory {
@Override
public Car createCar() {
return new Benz();
}
}
public class BmwFactory implements CarFactory {
@Override
public Car createCar() {
return new Bmw();
}
}
客户端调用:
public class Client {
public static void main(String[] args) {
CarFactory cf1 = new BenzFactory();
Car car1 = cf1.createCar();
car1.run();
CarFactory cf2 = new BmwFactory();
Car car2 = cf2.createCar();
car2.run();
}
}
当我们需要添加奥迪车时,创建 Audi 实体类继承 Car 和 AudiFactory 工厂类去实现 CarFactory 接口方法即可。
总结:不用修改业务代码,只需创建新的类即可实现功能扩展,遵循了开放封闭原则。但是,Client 类中出现创建对象逻辑,违背责任单一原则。每新增一类产品就需要创建 N 个类文件,增加项目结构的复杂度。
UML 类图表示如下:

Java 设计模式之工厂模式(二)的更多相关文章
- 浅析JAVA设计模式之工厂模式(二)
1 工厂方法模式简单介绍 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory),在这样的模式中,核心工厂不再是一个详细的类.而是一个抽象工厂,提 ...
- 浅析JAVA设计模式之工厂模式(一)
1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...
- Java设计模式之工厂模式(Factory模式)介绍(转载)
原文见:http://www.jb51.net/article/62068.htm 这篇文章主要介绍了Java设计模式之工厂模式(Factory模式)介绍,本文讲解了为何使用工厂模式.工厂方法.抽象工 ...
- java设计模式2————工厂模式
1.工厂模式介绍: 1.1.实现了创建者与调用者的分离 1.2.详细分类: 简单工厂模式 工厂方法模式 抽象工厂模式 1.3.所遵循的OOP原则: 开闭原则:对扩展开放,对修改关闭 依赖倒转原则:面向 ...
- java 设计模式之工厂模式与反射的结合
工厂模式: /** * @author Rollen-Holt 设计模式之 工厂模式 */ interface fruit{ public abstract void eat(); } ...
- Java设计模式之-----工厂模式(简单工厂,抽象工厂)
一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...
- Java设计模式之工厂模式(简单工厂模式+工厂方法模式)
摘自http://blog.csdn.net/jason0539/article/details/23020989 在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是 ...
- Java设计模式:工厂模式
问题提出 Java的工厂模式与现实生活中的工厂的模型是很相似的.工厂是用来做什么?当然是用来生成产品.因此在Java的工厂模式的关键点就是如何描述好产品和工厂这2个角色之间的关系. 下面来仔细描述一下 ...
- JAVA 设计模式之 工厂模式详解
一.简单工厂模式 简单工厂模式(Simple Factory Pattern)是指由一个工厂对象决定创建出哪一种产品类 的实例.属于创建型模式,但它不属于 GOF,23 种设计模式 (参考资料: ht ...
随机推荐
- 4.彻底理解synchronized
1. synchronized简介 在学习知识前,我们先来看一个现象: public class SynchronizedDemo implements Runnable { private s ...
- Ubuntu相关命令
此贴包含自己搭建网站以及自学Ubuntu遇到的相关命令,方便以后查看,故相关帖子整理记录在此! 用户切换 当前用户切换到root用户,只需要执行sudo su即可. root用户切回user用户,只需 ...
- PHP工作笔记:遍历文件夹返回文件数组
直接输入文件夹的路径,调用函数即可返回文件夹里面的文件数组,不返回文件夹 <?php function scanfiles($folder){ $folder = $folder."* ...
- gradle 删除指定目录中的文件和目录
// 删除bakAPk下的所有非母包文件 task deleTask(type: Delete){ FileTree tree = fileTree(dir: bakPath) tree.each { ...
- Spring报错:java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
感谢:http://blog.chinaunix.net/uid-20681545-id-184633.html提供的解决方案,非常棒 ! 问题说明: 新建一个Spring项目,新建一个Bean类:H ...
- ajaxFileUpload的data数据带pre标签
解决办法: var ret = jQuery.parseJSON(jQuery(data).text());
- functools 和 itertools
functools 补充 1 wraps 在编写装饰器时,在实现前加入 @functools.wraps(func) 可以保证装饰器不会对被装饰函数造成影响.wraps 保存被装饰函数的原信息 def ...
- asp.net button浏览器端事件和服务器端事件
OnClientClick:触发浏览器端的响应,OnClick触发服务器端响应; 在服务器aspx.cs脚本中设置按钮属性: this.btnTest.Attributes["OnClick ...
- 缺少所需的CD/DVD驱动器设备驱动程序
公司买了个服务器想把自带系统win10 改成windows server 2008 于是,我就用我的u盘做了个系统盘(用UltraISO或者别的,网上很多在此不在赘述) 然后改了启动项,进入到系统安装 ...
- 提高你的javascript代码逼格系列之函数与数组
不知道大家有没有一种感觉,那就是自己写的javascript代码虽然能完全解决工作上的需要,但是,一眼望去,too simple!!!简直就是一个傻子都能看懂的水平,于是,在工作之余,我开始去收集一些 ...