工厂方法模式-Factory Method Pattern

工厂方法模式是一种类创建型设计模式,允许子类决定实例化哪个类。它定义了一个创建对象的接口,由具体工厂类决定创建哪个具体产品类的对象,从而实现职责的分离。此模式在扩展时只需添加新的具体产品和具体工厂,符合开闭原则。通过Java示例展示了如何实现工厂方法模式,包括抽象产品、具体产品、抽象工厂和具体工厂的角色。同时,利用XML配置文件和反射机制,可以在运行时动态创建工厂对象,提高了系统的灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

工厂方法模式-Factory Method Pattern

工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类创建型模式

这是它的结构图:

在这里插入图片描述
它包含四个角色:

● Product(抽象产品):它是定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。

● ConcreteProduct(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。

● Factory(抽象工厂):在抽象工厂类中,声明了工厂方法(Factory Method),用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。

● ConcreteFactory(具体工厂):它是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实例。

完整解决方案

开发人员决定使用工厂方法模式来设计日志记录器,其基本结构如图所示:

在这里插入图片描述

//日志记录器接口:抽象产品
   interface Logger {
   public void writeLog();
   }
   
   //数据库日志记录器:具体产品
   class DatabaseLogger implements Logger {
   public void writeLog() {
   System.out.println("数据库日志记录。");
   }
   }
   //文件日志记录器:具体产品
    class FileLogger implements Logger {
    public void writeLog() {
    System.out.println("文件日志记录。");
    }
    }
    //日志记录器工厂接口:抽象工厂
    interface LoggerFactory {
    public Logger createLogger();
    }
   //数据库日志记录器工厂类:具体工厂
    class DatabaseLoggerFactory implements LoggerFactory {
    public Logger createLogger() {
    //连接数据库,代码省略
    //创建数据库日志记录器对象
    Logger logger = new DatabaseLogger();
    //初始化数据库日志记录器,代码省略
    return logger;
    }
    }
    //文件日志记录器工厂类:具体工厂
   class FileLoggerFactory implements LoggerFactory {
   public Logger createLogger() {
   //创建文件日志记录器对象
   Logger logger = new FileLogger();
   //创建文件,代码省略
   return logger;
   }
   }
   //客户端代码

class Client {
   public static void main(String args[]) {
   LoggerFactory factory;
   Logger logger;
   factory = new FileLoggerFactory(); //可引入配置文件实现
   logger = factory.createLogger();
   logger.writeLog();
   }
   }

我们可以通过Java的反射机制和xml完成创建工厂对象

先来个config.xml的代码

   <!— config.xml -->
   <?xml version="1.0"?>
   <config>
   <className>FileLoggerFactory</className>
   </config>

再来个xml读取工具类 XMLUtil

//工具类XMLUtil.java
   import javax.xml.parsers.*;
   import org.w3c.dom.*;
   import org.xml.sax.SAXException;
   import java.io.*;
  
   public class XMLUtil {
   //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
   public static Object getBean() {
    try {
    //创建DOM文档对象
    DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = dFactory.newDocumentBuilder();
    Document doc;
    doc = builder.parse(new File("config.xml"));
   
    //获取包含类名的文本节点
    NodeList nl = doc.getElementsByTagName("className");
    Node classNode=nl.item(0).getFirstChild();
    String cName=classNode.getNodeValue();
   
    //通过类名生成实例对象并将其返回
    Class c=Class.forName(cName);
    Object obj=c.newInstance();
    return obj;
    }
    catch(Exception e) {
    e.printStackTrace();
   return null;
    }
    }
    }

客户端代码如下:

class Client {
   public static void main(String args[]) {
   LoggerFactory factory;
   Logger logger;
   factory = (LoggerFactory)XMLUtil.getBean(); //getBean()的返回类型为Object,需要进行强制类型转换
   logger = factory.createLogger();
   logger.writeLog();
   }
   }

也可以直接向客户端隐藏了工厂的方法

在这里插入图片描述
工厂类把logger的创建内置:

//改为抽象类
   abstract class LoggerFactory {
   //在工厂类中直接调用日志记录器类的业务方法writeLog()
   public void writeLog() {
   Logger logger = this.createLogger();
   logger.writeLog();
   }
  
   public abstract Logger createLogger();
   }

工厂方法模式-Factory Method Pattern优缺点

优点:

(1) 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。

(2) 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够让工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,就正是因为所有的具体工厂类都具有同一抽象父类。

(3) 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

缺点:

(1) 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。

(2) 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值