在软件设计中,对象的创建和管理是一个关键问题。工厂模式是一种设计模式,旨在将对象的创建与使用分离,提供一种灵活而强大的对象创建方式。本文将深入介绍工厂模式的概念、分类以及在实际开发中的应用,同时结合实际代码示例和工厂模式的应用案例,让我们更好地理解这个强大的设计模式。
工厂模式概述
工厂模式是一种创建型设计模式,它通过将对象的创建抽象化,使客户端代码不直接依赖于具体的类实例化过程。通过工厂模式,我们可以实现对象的解耦和复用,提高代码的可维护性和扩展性。
简单工厂模式
简单工厂模式是工厂模式的一种最简单形式,通过一个工厂类来负责创建各种不同类型的对象。我们将深入探讨简单工厂模式的实现方式、优缺点以及适用场景。
class SimpleFactory {
public Product createProduct(String type) {
if ("A".equals(type)) {
return new ConcreteProductA();
} else if ("B".equals(type)) {
return new ConcreteProductB();
} else {
throw new IllegalArgumentException("Unknown product type");
}
}
}
工厂方法模式
工厂方法模式是工厂模式的扩展,它将具体对象的创建交给子类来实现。通过工厂方法模式,我们可以实现更好的可扩展性,使得新增类型的对象创建不影响现有代码。
interface Factory {
Product createProduct();
}
class ConcreteFactoryA implements Factory {
public Product createProduct() {
return new ConcreteProductA();
}
}
class ConcreteFactoryB implements Factory {
public Product createProduct() {
return new ConcreteProductB();
}
}
抽象工厂模式
抽象工厂模式是一种更高层次的工厂模式,它允许我们创建一系列相关或相互依赖的对象。抽象工厂模式将一组对象的创建封装在一个工厂接口中,不同的工厂实现可以创建不同的产品族。
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
class ConcreteFactory1 implements AbstractFactory {
public ProductA createProductA() {
return new ConcreteProductA1();
}
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
class ConcreteFactory2 implements AbstractFactory {
public ProductA createProductA() {
return new ConcreteProductA2();
}
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
工厂模式在Spring中的应用
开源框架Spring广泛地应用了工厂模式。通过IoC容器和Bean工厂,Spring允许我们通过配置来管理对象的创建和依赖关系。
@Component
class SpringService {
// By the way, Spring 容器本身就是一个超级工厂,其顶级接口BeanFactory 通过 getBean 方法可以创建各种各样不同的实例
private final Factory factory;
@Autowired
public SpringService(Factory factory) {
this.factory = factory;
}
// 使用factory创建对象
public Product createProduct() {
return factory.createProduct();
}
}
实际应用案例:工厂模式在Web开发中的应用
我们将以一个实际的Web开发场景为例,展示如何使用工厂模式来创建不同类型的支付方式。
interface Payment {
void pay();
}
class Alipay implements Payment {
public void pay() {
System.out.println("Using Alipay for payment");
}
}
class WeChatPay implements Payment {
public void pay() {
System.out.println("Using WeChat Pay for payment");
}
}
class PaymentFactory {
public Payment createPayment(String type) {
if ("Alipay".equals(type)) {
return new Alipay();
} else if ("WeChatPay".equals(type)) {
return new WeChatPay();
} else {
throw new IllegalArgumentException("Unknown payment type");
}
}
}
在工厂模式中的进一步应用
除了对象的创建,工厂模式还可以在其他方面进行应用,比如我主导的开源框架 Remote 当中就应用了工厂模式,就像上文所展示那样,其不仅仅应用的单例模式还应用的工厂模式,其工厂方法能够创建出单例对象出来。
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class RemoteLifeCycleHandlerFactory {
private static final Logger log = LoggerFactory.getLogger(RemoteLifeCycleHandlerFactory.class);
// RemoteLifeCycleHandlerFactory 采用饿汉式的单例模式,类加载的时候就实例化
public static final RemoteLifeCycleHandlerFactory FACTORY = new RemoteLifeCycleHandlerFactory();
// 饿汉式地提供一个实例容器用于保存需要的实例
private static final Map<Class<? extends RemoteLifeCycle.LifeCycleHandler<?>>, RemoteLifeCycle.LifeCycleHandler<?>> INSTANCE_CACHE = new ConcurrentHashMap<>();
// 根据类型获取单例实例
// 单例的工厂方法
// 通过传入要创建的实例对象类型,获取或者创建单例的实例对象
// 类似与 Sring 的 BeanFactory#getBean(Class<?> beanClass);
public RemoteLifeCycle.LifeCycleHandler<?> singletonHandler(Class<? extends RemoteLifeCycle.LifeCycleHandler<?>> clazz){
RemoteLifeCycle.LifeCycleHandler<?> handler = INSTANCE_CACHE.get(clazz);
// 如果存在实例则直接返回
if (Objects.nonNull(handler))
return handler;
// 锁定资源
synchronized (INSTANCE_CACHE){
handler = INSTANCE_CACHE.get(clazz);
// 双重检查,是否存在实例, 如果存在则直接返回
if (Objects.nonNull(handler))
return handler;
// 创建实例
Constructor<?> constructor = Arrays.stream(clazz.getConstructors()).filter(item -> item.getParameterCount() == 0).findFirst().orElseThrow(() -> new RuntimeException("RemoteLifeCycleHandler [" + clazz.getName() + "] can not found default constructor..."));
try {
if (Modifier.PUBLIC != constructor.getModifiers())
throw new IllegalArgumentException("Default Constructor of Class<" + clazz.getName() + "> must be public");
handler = (RemoteLifeCycle.LifeCycleHandler<?>) constructor.newInstance();
} catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
// 添加错误日志
log.warn("Cannot construct instance for class: {}, Exception: {}", clazz.getName(),e.getMessage(),e);
}
// 将实例放入缓存,并返回实例
INSTANCE_CACHE.put(clazz, handler);
return handler;
}
}
}
singletonHandler
方法:这是工厂模式的核心方法。它接受一个 Class
对象作为参数,然后尝试从缓存中获取该类对应的实例,如果实例不存在,则使用反射创建实例。这种方法确保每个类只有一个实例,并且在需要的时候进行创建,从而提供了对象的单例管理。
总的来说,这段代码利用工厂模式将对象的创建和管理进行了封装。它通过缓存已创建的实例,避免了重复创建实例,从而提高了性能。此外,工厂还提供了添加处理器和生命周期的方法,使得管理更加灵活。通过单例模式,它确保了每个处理器类的实例唯一性,并且在需要时进行延迟创建。
请注意,虽然这段代码使用了工厂模式的思想,但其中的实现略显复杂,涉及到了反射和线程安全的考虑。如果您在实际项目中使用类似的模式,建议进行充分的测试和验证,确保其正确性和性能。
总结与展望
工厂模式是一种非常有用的设计模式,它可以帮助我们更灵活地管理对象的创建过程。通过深入的介绍和实际示例,我们更好地理解了工厂模式的概念、应用和好处。通过学习工厂模式,我们可以提高代码的可维护性、可扩展性和复用性。在实际项目中,选择合适的工厂模式可以极大地简化代码,提高开发效率。希望通过这篇文章,您能够对工厂模式有更深刻的认识。