随着编程技术的不断发展,面向对象语言和面向对象程序设计逐渐成为主流。这就不可避免地涉及到了对象的建立。建立一个对象,并使用已经定义好的方法,看起来也很清晰和简单。有的时候,在不一样的状况下须要不一样子类的对象,如何下降耦合度、方便地进行切换,而不须要将全部实例化该对象的地方都进行修改,则涉及到了模式。java
下面将依次介绍简单工厂模式、工厂方法模式、抽象工厂模式,说明他们是如何实现建立对象这一功能的。(后文将三者统称为工厂模式。)编程
一个很简单的作法,既然你说可能要使用不一样的对象,那我将全部建立对象的操做都集中起来,只在一个地方进行对象的建立,其余地方都经过这里来建立对象。之后即使要修改,也只须要改一处地方不就能够了。设计模式
以生产鼠标为例,咱们须要有线鼠标和无线鼠标。则大体的代码以下:less
abstract class Mouse {
}
class WiredMouse : Mouse {
}
class WirelessMouse : Mouse {
}
class SimpleFactory_1 {
public Mouse createMouse(String type) {
if ("wired".equals(type)) {
return new WiredMouse();
} else if ("wireless".equals(type)) {
return new WirelessMouse();
} else {
// unknown type !
return null;
}
}
}
复制代码
简单工厂模式十分简单直观,代码量也不多。这份代码的一个改进之处是将 createMouse 的参数从 String 类型改为枚举类型,以避免使用时拼写错误,也能更好地对参数进行限制。spa
简单工厂模式的缺点是,若是咱们须要增长新的鼠标,那么咱们就必须修改 createMouse 方法,增长 if/else 语句。这样就破坏了"对修改封闭"的原则。设计
简单工厂模式能够定义成静态方法,也能够定义成实例方法。他们的特色以下:code
更进一步,假设有 A、B 两家公司都生产有线和无线鼠标,他们的鼠标定义以下:对象
// A 的鼠标
class AWiredMouse : WiredMouse {
}
class AWirelessMouse : WirelessMouse {
}
// B 的鼠标
class BWiredMouse : WiredMouse {
}
class BWirelessMouse : WirelessMouse {
}
复制代码
对应的简单工厂模式代码以下:继承
class SimpleFactory_2 {
public Mouse createMouse(String factory, String type) {
if ("A".equeals(factory)) {
if ("wired".equals(type)) {
return new AWiredMouse();
} else if ("wireless".equals(type)) {
return new AWirelessMouse();
} else {
// unknown type !
return null;
}
} else if ("B".equals(factory)) {
if ("wired".equals(type)) {
return new BWiredMouse();
} else if ("wireless".equals(type)) {
return new BWirelessMouse();
} else {
// unknown type !
return null;
}
} else {
// unknown factory !
return null;
}
}
}
复制代码
能够看到代码开始复杂起来了,若是还有更多公司 C、D 也在生产鼠标,或者有更多的鼠标类型,那么这个工厂类将会更将复杂。开发
下面咱们就来看看工厂方法模式是如何处理这种问题。
abstract class Factory {
public Mouse CreateMouse(String type);
}
class AFactory_2 : Factory {
public Mouse CreateMouse(String type) {
if ("wired".equals(type)) {
return new AWiredMouse();
} else if ("wireless".equals(type)) {
return new AWirelessMouse();
} else {
// unknown type !
return null;
}
}
}
class BFactory_2 : Factory {
public Mouse CreateMouse(String type) {
if ("wired".equals(type)) {
return new BWiredMouse();
} else if ("wireless".equals(type)) {
return new BWirelessMouse();
} else {
// unknown type !
return null;
}
}
}
复制代码
能够看到,工厂方法模式中,定义了多个工厂类分别对应各自的公司,每一个类只负责建立本身的鼠标,而不用管其余公司的。
若是还有更多的公司,则定义新的工厂类便可,不须要修改已有的代码。
若是须要生产更多类型的鼠标,则须要对工厂都作修改,增长相应的 if/else 语句来处理。这一点与简单工厂模式相似。
工厂方法模式,体现了"对扩展开发,对修改封闭"。
这里为了说明使用工厂方法模式相比简单工厂模式的优势,特地给鼠标增长了公司(A、B)和类型(有线、无线)这两个纬度,以便说明工厂方法模式对代码职责进行划分。
实际上,对应简单工厂 SimpleFactory_1 也能够改为工厂方法模式,代码以下:
abstract class Factory {
public Mouse CreateMouse();
}
class WiredFactory_1 : Factory {
public Mouse CreateMouse() {
return new AWiredMouse();
}
}
class WirelessFactory_1 : Factory {
public Mouse CreateMouse() {
return new AWirelessMouse();
}
}
复制代码
这些公司除了生产鼠标外,还会生产键盘等产品。键盘的定义以下:
abstract class Keyboard {
}
class WiredKeyboard : Keyboard {
}
class WirelessKeyboard : Keyboard {
}
// A
class AWiredKeyboard : WiredKeyboard {
}
class AWirelessKeyboard : WirelessKeyboard {
}
// B
class BWiredKeyboard : WiredKeyboard {
}
class BWirelessKeyboard : WirelessKeyboard {
}
复制代码
对应的抽象工厂模式以下:
abstract class Factory {
public Mouse createMouse(String type);
public Keyboard createKeyboard(String type);
}
class AFactory_2 : Factory {
public Mouse createMouse(String type) {
// 与以前一致
}
public Keyboard createKeyboard(String type) {
if ("wired".equals(type)) {
return new AWiredKeyboard();
} else if ("wireless".equals(type)) {
return new AWirelessKeyboard();
} else {
// unknown type !
return null;
}
}
}
class BFactory_2 : Factory {
public Mouse createMouse(String type) {
// 与以前一致
}
public Keyboard createKeyboard(String type) {
if ("wired".equals(type)) {
return new BWiredKeyboard();
} else if ("wireless".equals(type)) {
return new BWirelessKeyboard();
} else {
// unknown type !
return null;
}
}
}
复制代码
能够看到:如今一个工厂会负责生产鼠标、键盘等多种产品,而且每一个工厂只负责本身的部分。
若是还有新的公司也能够生成鼠标、键盘这些产品,则只须要添加新的工厂类便可,无需修改已有的类。
若是还要生产更多的产品好比显示器等,则须要修改全部的工厂类。
这里的例子,工厂方法也能够拆成抽象工厂来表示。。
简单工厂模式的重点在于将建立产品的代码统一在一处,方便管理。
工厂方法模式、抽象工厂模式除了将建立产品的代码统一在一处,还提供了一种便捷地更换产品系列的能力——当我须要 A 公司的产品,那么就使用 AAFactory;当我须要 B 公司的产品,那么就使用 BFactory;只须要修改使用的工厂便可实现将全部的产品都改为对应的产品,大大下降了耦合度和修改的成本。
不少时候,咱们只须要用到简单工厂模式就足够了。但这并非工厂方法模式、抽象工厂模式没有用,而是不少时候没有这种需求——咱们只须要一种类型的产品就足够了,并不须要同时支持多种产品;在这种状况下,使用简单工厂模式的确会更加简单。
然而,一旦咱们同时须要不一样类型的产品,那么简单工厂模式就很容易使得方法体快速膨胀,使用工厂方法模式和抽象工厂模式能够更好地对代码和职责进行划分。
工厂方法模式只生产一种产品,而抽象工厂模式则是生产一系列产品(,一般这些产品之间有必定联系的)。抽象工厂模式生产其中的每一个产品时,一般使用工厂方法模式。
《Head First 设计模式》
《设计模式 可复用面向对象软件的基础》