【简单工厂模式】

80 阅读3分钟

简介

简单工厂模式是一种创建对象的设计模式,简单工厂模式由一个工厂类根据传入的参数决定创建出哪一种产品类的实例,从而使对象的创建和使用分离。

业务

以下是一个在 Java 业务场景中的例子:假设你正在开发一个电商系统,其中有不同类型的支付方式,如微信支付、支付宝支付和银行卡支付。在这种情况下,可以使用简单工厂模式来创建支付对象。

类图

classDiagram
    
    class Payment {
        +pay()
    }
    class WeChatPayment {
        +pay()
    }
    class AlipayPayment {
        +pay()
    }
    class BankCardPayment {
        +pay()
    }
    class PaymentFactory {
        +createPayment(String paymentType): Payment
    }

    PaymentFactory ..> WeChatPayment
    PaymentFactory ..> AlipayPayment
    PaymentFactory ..> BankCardPayment
    WeChatPayment ..|> Payment
    AlipayPayment ..|> Payment
    BankCardPayment ..|> Payment   

具体代码

首先,定义一个支付接口,该接口包含支付的方法:

public interface Payment {
    void pay();
}

然后,实现不同的支付方式类:

public class WeChatPayment implements Payment {
    @Override
    public void pay() {
        System.out.println("使用微信支付");
    }
}

public class AlipayPayment implements Payment {
    @Override
    public void pay() {
        System.out.println("使用支付宝支付");
    }
}

public class BankCardPayment implements Payment {
    @Override
    public void pay() {
        System.out.println("使用银行卡支付");
    }
}

接下来,创建一个支付工厂类,用于根据不同的支付方式创建相应的支付对象

public class PaymentFactory {
    public static Payment createPayment(String paymentType) {
        if (paymentType.equalsIgnoreCase("wechat")) {
            return new WeChatPayment();
        } else if (paymentType.equalsIgnoreCase("alipay")) {
            return new AlipayPayment();
        } else if (paymentType.equalsIgnoreCase("bankcard")) {
            return new BankCardPayment();
        } else {
            throw new IllegalArgumentException("不支持的支付方式");
        }
    }
}

在业务代码中,可以使用支付工厂来创建支付对象:

public class Main {
    public static void main(String[] args) {
        Payment payment = PaymentFactory.createPayment("wechat");
        payment.pay();
    }
}

优点

  1. 实现了对象创建和使用的分离。客户端只需要知道支付接口,而不需要了解具体支付方式的实现细节,通过支付工厂来创建支付对象。
  2. 易于维护。如果需要添加新的支付方式,只需要在支付工厂类中添加相应的代码,而不会影响到客户端代码。

缺点

  1. 不符合开闭原则。如果需要添加新的支付方式,需要修改支付工厂类的代码。

在框架中的使用

mybatis

在 MyBatis 框架中,简单工厂模式也有一定的体现。 例如,SqlSessionFactory的创建过程可以看作是简单工厂模式的一种应用。SqlSessionFactoryBuilder根据不同的输入(如 XML 配置文件、Java 代码中的配置对象等)来创建SqlSessionFactory对象。

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisExample {
    public static void main(String[] args) {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 使用 SqlSession 进行数据库操作
            sqlSession.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

spring

在 Spring 框架中,简单工厂模式的应用相对比较隐晦。

例如,BeanFactory在创建 Bean 的过程中,可以看作是一种广义上的简单工厂模式的体现。当你通过BeanFactory获取一个特定的 Bean 时,BeanFactory会根据配置信息和需求创建相应的对象并返回给调用者。

比如在以下场景中:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringExample {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        MyService myService = context.getBean(MyService.class);
        myService.doSomething();
    }
}

class MyService {
    public void doSomething() {
        System.out.println("执行 MyService 的方法。");
    }
}

Logback

Logback为例,当你配置好日志环境后,在代码中获取日志记录器Logger时,实际上是通过一个工厂方法来创建的,通过loggerContext.getLogger()方法获取Logger对象,这个过程可以看作是一个简单工厂方法的调用。它根据传入的类信息创建了一个特定的日志记录器对象。

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.FileAppender;

public class LogbackExample {
    public static void main(String[] args) {
        LoggerContext loggerContext = new LoggerContext();
        Logger logger = loggerContext.getLogger(LogbackExample.class);

        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        encoder.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n");
        encoder.start();

        FileAppender<ILoggingEvent> fileAppender = new FileAppender<>();
        fileAppender.setContext(loggerContext);
        fileAppender.setEncoder(encoder);
        fileAppender.setFile("application.log");
        fileAppender.start();

        logger.addAppender(fileAppender);

        logger.info("这是一条日志信息。");
    }
}

总结

总的来说,简单工厂模式适用于创建对象的逻辑比较简单的场景,可以提高代码的可维护性和可扩展性。但在复杂的业务场景中,可能需要使用更复杂的设计模式,如工厂方法模式或抽象工厂模式。