1-简单工厂模式

简单工厂模式

创建型模式

  1. 关注对象的创建过程

  2. 对类的实例化过程进行了抽象,将软件模块中对象的创建和对象的使用分离

  3. 描述如何将对象的创建和使用分离

java创建对象方法:

  1. new关键字直接创建
  2. 工厂创建对象——工厂模式
  3. 克隆创建对象——原型模式
  4. 通过反射创建对象
创建型模式一览表
image-20221116191204763

单例模式是唯一一个自己创建自己的模式

简单工厂模式(参数化工厂模式)只有一个工厂

  1. 存在问题:单个工厂负责所有产品的生产,可能会任务过重——违反单一职责原则

  2. 增加新产品时需要修改源代码——违反开闭原则

简单工厂模式-基本实现流程:

  1. 具体产品类:将需要创建的各种不同产品对象的相关代码封装到具体产品类中

  2. 抽象产品类:将具体产品类公共的代码进行抽象和提取后封装在一个抽象产品类中

  3. 工厂类:提供一个工厂类用于创建各种产品,在工厂类中提供一个创建产品的工厂方法,该方法可以根据所传入参数的不同创建不同的具体产品对象

  4. 客户端:只需调用工厂类的工厂方法并传入相应的参数即可得到一个产品对象

简单工厂模式定义

image-20221116192710871

在具体的FactoryPatternDemo 类中将类对象作为局部变量,因此是依赖关系而不是关联关系

  1. 在简单工厂模式中用于创建实例的方法通常是静态(static)方法,又被称为静态工厂方法(Static Factory Method)模式

  2. 要点:如果需要什么,只需要传入一个正确的参数,就可以获取所需要的对象,而无须知道其创建细节

  3. 简单工厂模式也称为Parameterized Factory Methods(参数化工厂模式)

image-20221116195324477
1
2
3
4
5
6
7
A a;
a=new A1();
a.
/**
*问:此时通过a.能够看到哪些方法?
*答:只能看到父类A的m1()和m2()方法,因为a首先是单独被类A声明的,而不是在声明a的时候就同时用A1()实例化,因*此只能看到类A的两个方法,而无法看到类A1的m3()方法
*/

在java中static会导致丧失多态性

子类不能够覆盖父类的静态(static)方法

简单工厂模式结构
image-20221116194350957

工厂类(Factory)中创建产品的方法是static方法\textcolor{red}{工厂类(Factory)中创建产品的方法是static方法}

简单工厂模式包含以下3个角色
  1. Factory(工厂角色)

  2. Product(抽象产品角色)

    • 如果抽象父类不需要实现具体的方法,则使用接口实现
    • 如果抽象父类需要实现一些具体的方法,则使用类实现
  3. ConcreteProduct(具体产品角色)

典型的抽象产品类代码
1
2
3
4
5
6
7
8
9
public abstract class Product {
//所有产品类的公共业务方法
public void methodSame() {
//公共方法的实现
}
 
//声明抽象业务方法
public abstract void methodDiff();
}
典型的具体产品类代码
1
2
3
4
5
6
public class ConcreteProduct extends Product{
//实现业务方法
public void methodDiff() {
//业务方法的实现
}
}
典型的工厂类代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Factory {
//静态工厂方法
public static Product getProduct(String arg) {
Product product = null;
if (arg.equalsIgnoreCase("A")) {
product = new ConcreteProductA();
//初始化设置product
}
else if (arg.equalsIgnoreCase("B")) {
product = new ConcreteProductB();
//初始化设置product
}
return product;
}
}
典型的客户端代码
1
2
3
4
5
6
7
8
public class Client {
public static void main(String args[]) {
Product product;
product = Factory.getProduct("A"); //通过工厂类创建产品对象
product.methodSame();
product.methodDiff();
}
}
实例类图1:
image-20221116200747782
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class FactoryPatternDemo {

public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();

//获取 Circle 的对象,并调用它的 draw 方法
Shape shape1 = shapeFactory.getShape("CIRCLE");

//调用 Circle 的 draw 方法
shape1.draw();
}

}
/**
* 在以上代码中如果要更改生成的产品就必须要修改源代码,违反了开闭原则,所以将改变的部分放到XML配置文件中
*/

加载/解析配置文件:

  1. DOM加载配置文件
    • 一次性读取全部内容到内存
    • 相对于SAX来说内存占用多,但是速度快
  2. SAX加载配置文件
    • 逐行扫描文档,一边扫描一边解析
    • 内存占用少

java涉及到文件读取和外部操作时一般都要用try-catch作异常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//xml文件
<?xml version="1.0"?>
<config>
<chartType>histogram</chartType>
</config>
/**
* chartType可以有多个元素
*/

//加载xml文件
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
 
public class XMLUtil {
//该方法用于从XML配置文件中提取图表类型,并返回类型名
public static String getChartType() {
try {
//创建文档对象——调用DOM固有方法
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File("src//designpatterns//simplefactory//config.xml"));

//获取包含图表类型的文本结点
NodeList nl = doc.getElementsByTagName("chartType");
Node classNode = nl.item(0).getFirstChild();
String chartType = classNode.getNodeValue().trim();
return chartType;
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
}

引入配置文件:

image-20221116202058610
1
2
3
4
5
……
Chart chart;
String type = XMLUtil.getChartType(); //读取配置文件中的参数
chart = ChartFactory.getChart(type); //创建产品对象
……
实例类图2:
image-20221116203043356
工厂类多创建方法:

针对构造函数的参数重载在工厂中定义不同的create方法(Rectangle是抽象产品类)

image-20221116203724278
简单工厂模式的优点:
image-20221116203111937
  1. 对象创建和使用的分离

  2. 客户端无须知道所创建的具体产品类的类名

  3. 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类

所有模式都实现了对象创建和使用的分离

模式的缺点:
  1. 工厂类集中了所有产品的创建逻辑,职责过重

  2. 增加了系统中类的个数

  3. 系统扩展困难,一旦添加新产品不得不修改工厂逻辑(即,修改源代码)

  4. 由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构

    • 子类不能覆盖父类的静态方法

模式适用环境⭐️

  1. 工厂类负责创建的对象比较少,对象的类型比较稳定

  2. 客户端只知道传入工厂类的参数,对于如何创建对象并不关心扩展

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2023-2024 Guijie Wang
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信