起因:今天在找资料的过程中,发现了“工厂模式(Factory pattern)被用于各种不可变的类如 Boolean,像Boolean.valueOf”这样的一句话,想到自己之前面试的时候让讲过工厂模式没有讲出来,决定以此为出发点,去研究一下工厂模式。
设计模式 工厂设计模式
1 分类
工厂模式:简单工厂模式,工厂方法模式,抽象工厂模式 三种
2 简单工厂模式
工厂方法(FactoryMethod)模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。
这满足创建型模式中所要求的“创建与使用相分离”的特点。
工厂模式的核心在于 创建与使用相分离
2.1 简单工厂模式 概述
简单工厂模式,把相关创建类的方法进行抽象,或者说是提取出来,在工厂中实现。
如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。
简单工厂模式的主要优点有:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
其缺点是:
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
2.2 简单工厂模式 模式结构
工厂方法模式的主要角色如下。
- 简单工厂(SimpleFactory):简单工厂模式的核心,负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
- 抽象产品(Product):简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口。
- 具体产品(ConcreteProduct):简单工厂模式的创建目标。
2.3 简单工厂模式 代码实现
package com.factory;
/**
* @ClassName Client
* @Description TODO
* @Author liulinfang
* @Date 2020/11/11 14:14
* @Version 1.0
*/
public class Client {
public static void main(String[] args) {
Product product = SimpleFactory.getProduct(Const.Product_A);
product.show();
}
interface Product {
void show();
}
static class ConcreteProductA implements Product {
@Override
public void show() {
System.out.println("这是方法1");
}
}
static class ConcreteProductB implements Product {
@Override
public void show() {
System.out.println("这是方法2");
}
}
final class Const {
final static int Product_A = 0;
final static int Product_B = 1;
final static int Product_C = 2;
}
static class SimpleFactory {
public static Product getProduct(int kind) {
switch (kind) {
case Const.Product_A:
return new ConcreteProductA();
case Const.Product_B:
return new ConcreteProductB();
}
return null;
}
}
}
3 工厂方法模式
简单工厂模式违背了开闭原则,而“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
3.1 工厂方法模式 概述
在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,
这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
工厂方法模式的主要优点有:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
- 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
- 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
其缺点是:
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
- 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。
3.2 工厂方法模式 模式结构
工厂方法模式的主要角色如下。
- 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
- 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
- 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
3.3 工厂方法模式 代码实现
测试代码如下:
package com.factory;
public class AbstractFactoryTest {
public static void main(String[] args) {
try {
AbstractFactory af= (AbstractFactory) ReadXML1.getObject();
assert af != null;
Product a = af.newProduct();
a.show();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
//抽象产品:提供了产品的接口
interface Product {
public void show();
}
//具体产品1:实现抽象产品中的抽象方法
class ConcreteProduct1 implements Product {
public void show() {
System.out.println("具体产品1显示...");
}
}
//具体产品2:实现抽象产品中的抽象方法
class ConcreteProduct2 implements Product {
public void show() {
System.out.println("具体产品2显示...");
}
}
//抽象工厂:提供了厂品的生成方法
interface AbstractFactory {
public Product newProduct();
}
//具体工厂1:实现了厂品的生成方法耦合
class ConcreteFactory1 implements AbstractFactory {
public Product newProduct() {
System.out.println("具体工厂1生成-->具体产品1...");
return new ConcreteProduct1();
}
}
//具体工厂2:实现了厂品的生成方法
class ConcreteFactory2 implements AbstractFactory {
public Product newProduct() {
System.out.println("具体工厂2生成-->具体产品2...");
return new ConcreteProduct2();
}
}
XML解析代码如下:
package com.factory;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
class ReadXML1 {
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
public static Object getObject() {
try {
//创建文档对象
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File("mall-portal/src/test/java/com/factory/config1.xml"));
//获取包含类名的文本节点
NodeList nl = doc.getElementsByTagName("className");
Node classNode = nl.item(0).getFirstChild();
String cName = "com.factory." + classNode.getNodeValue();
//System.out.println("新类名:"+cName);
//通过类名生成实例对象并将其返回
Class<?> c = Class.forName(cName);
Object obj = c.newInstance();
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
XML代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>ConcreteFactory1</className>
</config>
4 抽象工厂模式
是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
4.1 抽象工厂模式 概述
使用抽象工厂模式一般要满足以下条件。
- 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
- 系统一次只可能消费其中某一族产品,即同族的产品一起使用。
抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。
- 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
- 当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品组。
- 抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则。
其缺点是:
- 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。增加了系统的抽象性和理解难度。
4.2 抽象工厂模式 模式结构
工厂方法模式的主要角色如下。
- 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
- 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
- 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
- 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。
4.3 抽象工厂模式 代码实现
interface AbstractFactory {
public Product1 newProduct1();
public Product2 newProduct2();
}
class ConcreteFactory1 implements AbstractFactory {
public Product1 newProduct1() {
System.out.println("具体工厂 1 生成-->具体产品 11...");
return new ConcreteProduct11();
}
public Product2 newProduct2() {
System.out.println("具体工厂 1 生成-->具体产品 21...");
return new ConcreteProduct21();
}
}
抽象工厂,在工厂方法中,添加产品族和产品等级的概念。也需要已知想要的产品
抽象工厂模式的扩展有一定的“开闭原则”倾斜性:
- 当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。
- 当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则。
不要以为每天把功能完成了就行了,这种思想是要不得的,互勉~!