工厂方法模式设计实验

news/2024/10/11 13:26:28/

【实验内容】

楚锋软件公司欲开发一个系统运行日志记录器(Logger)。该记录器可以通过多种途径保存系统的运行日志:例如通过文件记录或数据库记录,用户可以通过修改配置文件灵活地更换日志记录方式。在设计各类日志记录器时,楚锋软件公司的开发人员发现需要对日志记录器进行一些初始化工作,初始化参数的设置过程较为复杂,而且某些参数的设置有严格的先后次序,否则可能会发生记录失败。如何封装记录器的初始化过程并保证多种记录器切换的灵活性是楚锋软件公司开发人员面临的一个难题。

楚锋软件公司的开发人员通过对该需求进行分析,发现该日志记录器有两个设计要点:

(1)需要封装日志记录器的初始化过程,这些初始化工作较为复杂,例如需要初始化其他相关的类,还有可能需要配置工作环境(例如连接数据库或创建文件),导致代码较长,如果将它们都写在构造函数中,会导致构造函数庞大,不利于代码的修改和维护。

(2)用户可能需要更换日志记录方式,在客户端代码中需要提供一种灵活的方式来选择日志记录器,尽量在不修改源代码的基础上更换或者增加日志记录方式。

楚锋软件公司发人员最初使用简单工厂模式对日志记录器进行了设计,初始结构如下图所示。

在上图所示的设计中:

LoggerFactory 充当创建日志记录器的工厂,提供了工厂方法 createLogger() 用于创建日志记录器,Logger 是抽象日志记录器接口,其子类为具体日志记录器。上面设计对应的代码如下:

  

 

为了突出设计重点,上述代码进行了简化,省略了具体日志记录器类的初始化代码。在 LoggerFactory 类中提供了静态工厂方法 createLogger() ,用于根据所传入的参数创建各种不同类型的日志记录器。通过使用简单工厂模式,将日志记录器对象的创建和使用分离,客户端只需使用由工厂类创建的日志记录器对象即可,无须关心对象的创建过程但是,虽然简单工厂模式实现了对象的创建和使用分离,仍然存在以下两个问题:

(1)工厂类过于庞大,包含了大量的 if···ese··· 代码,导致维护和测试难度增大

(2)系统扩展不灵活,如果增加新类型的日志记录器,必须修改静态工厂方法的业务逻辑,违反了开闭原则。

【实验要求】

使用工厂模式重构上面的设计,解决上面两个问题。给出设计类图,以及对应的 Java 代码

【实验答案参考】

UML设计类图:

Java代码:

java">public interface LoggerFactory {public Logger createLogger();}public class FileLoggerFactory implements LoggerFactory {public Logger createLogger(){        //创建文件日志记录器对象Logger logger = new FileLogger();//创建文件,代码省略return logger;}}public class DatabaseLoggerFactory implements LoggerFactory {public Logger createLogger(){//连接数据库,代码省略//创建数据库日志记录器对象Logger logger = new DatabaseLogger();//初始化数据库日志记录器,代码省略return logger;}}public class Client {public static void main(String args[]){        LoggerFactory factory;Logger logger;//下面也可以通过引入配置文件实线类工厂的指定factory=new FileLoggerFactory();logger=factory.createLogger();logger.writeLog();}}


http://www.ppmy.cn/news/1434551.html

相关文章

【ZZULIOJ】1078: a+b(多实例测试1)(Java)

目录 题目描述 输入 输出 样例输入 Copy 样例输出 Copy 提示 code 题目描述 计算AB 输入 输入第1行为一个整数n(1≤n≤10),代表测试的组数。 下面有n组测试数据,每组1行,为2个整数,为A, B。 输出 对每行输入&#xff…

【Java】文件操作(一)

文章目录 ✍一、文件的基本认识1.文件是什么?2.文本文件和二进制文件3.文件权限4.相对路径和绝对路径1.1绝对路径1.2相对路径 ✍二、文件的基本操作1.FIle的属性2.File的构造方法3.File类的方法3.1File类的获取操作3.2File类的判断操作3.3文件创建和删除3.4其他的常…

SQL超详细解析

目录 SQL通用语法 SQL分类 DDL-数据库定义语言 1、DDL-数据库操作-查询 查询所有数据库 查询当前数据库 2、DDL-数据库操作-创建 创建数据库 3、DDL-数据库操作-删除 4、DDL-数据库操作-使用 5、DDL-表操作-查询: 查看当前数据库的所有表名称 查询当前表…

C++的初步知识——命名空间,缺省参数,重载函数

C 首先写一段代码&#xff1a; #include <stdio.h>int main() {printf("Hello world\n");return 0; }这段C语言代码在cpp文件中仍可运行。我们了解C是兼容C语言的&#xff0c;C的关键字中就包含了C语言的关键字和自身的关键字。关于关键字&#xff0c;我们简…

问题:react函数中的state是上一次的值

场景 有一个聊天输入框组件&#xff0c;输入框上面有表情包组件。 通过redux创建了store&#xff0c;存储一个message的状态&#xff0c;用于表情包和输入框共享状态。 输入框通过设置value和onClick做了一个简单双向绑定&#xff0c;其中value的值为store里的message。 impor…

在android 源代码中 使用gradlew 编译android 模块

gradle 编译子模块 在Gradle中编译子模块通常涉及到以下步骤&#xff1a; 1、确保你的项目结构是模块化的&#xff0c;每个子模块都是一个独立的目录2、在项目的根目录下的setting.gradle文件中&#xff0c;包含需要编译的子模块。例如&#xff1a;include ‘:submodule-name…

ctfshow web入门 web180--web185

web180 import requests import recom re.compile("admin") def repisTrue(char):url f"http://自己环境的网址/api/?id1%27and%27{char}%27%27{char}&page1&limit10"res requests.get(url)w com.search(res.text)if w is not None:return T…

(delphi11最新学习资料) Object Pascal 学习笔记---第10章第1节(属性的代码补全)

10.1.3 属性的代码补全 ​ 给类添加属性是一项繁琐的工作&#xff0c;IDE的编辑器可以让你在编写属性声明的初始部分&#xff08;在类内部&#xff09;时轻松自动完成属性&#xff0c;如下所示&#xff1a; typeTMyClass classpublicproperty Month : Integer;end;​ 在光标…