首页 > 其他分享 >设计模式——工厂模式

设计模式——工厂模式

时间:2024-12-19 12:28:42浏览次数:5  
标签:use Product 模式 工厂 具体 产品 设计模式 public

设计模式——工厂模式

目录

介绍

工厂模式(Factory Pattern)是 Java 设计模式中的一种创建型模式,它提供了一种创建对象的方式,而不需要指定具体的类。工厂模式通过引入工厂类来创建对象,将对象的创建过程从具体的类中分离出来,从而提高了代码的灵活性和可扩展性。

实现

简单工厂模式

首先来看简单工厂模式(这个从严格意义上说并不属于23中设计模式中的一种,因为这样设计违反了 开闭原则

结构

  • 工厂类(Factory):负责创建不同类型的产品对象。
  • 产品接口(Product):定义产品的基本功能。
  • 具体产品(ConcreteProduct):实现了产品接口,定义具体的产品功能。

示例代码:

// 产品接口
public interface Product {
    void use();
}

// 具体产品
public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using Product A");
    }
}

public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using Product B");
    }
}

// 工厂类
public class SimpleFactory {
    public Product createProduct(String type) {
        if (type.equals("A")) {
            return new ConcreteProductA();
        } else if (type.equals("B")) {
            return new ConcreteProductB();
        }
        return null;
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        SimpleFactory factory = new SimpleFactory();
        Product productA = factory.createProduct("A");
        productA.use();
        Product productB = factory.createProduct("B");
        productB.use();
    }
}

优缺点

  • 优点:
    • 客户端代码只需要依赖工厂类,不需要关心产品的具体实现。
    • 可以集中管理和创建对象的逻辑,便于扩展。
  • 缺点:
    • 违反了单一职责原则,工厂类的职责过重。
    • 当产品种类增加时,工厂类需要修改,违背了开闭原则。

适用场景

  • 产品种类固定且较少时使用简单工厂模式比较合适。

这里简单补充一下 开闭原则

开闭原则(Open/Closed Principle,OCP) 是面向对象设计中的五大基本原则之一,也是 SOLID 原则中的第二个原则。开闭原则的核心思想是:

“软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。”

简单来说,开闭原则要求我们在软件开发过程中,通过增加新代码来扩展系统功能,而不是修改现有的代码。这样做的目的是减少对已有功能的影响,避免引入新的错误,并提高代码的可维护性和可扩展性。

显然,上面的简单工厂模式就违背了开闭原则:比如,当我们新增产品 C 时,工厂中的逻辑代码则需要进行修改,而不是保障原有的代码不变,新增代码,所以违背了开闭原则

工厂方法模式

工厂方法模式将简单工厂模式中的工厂类的职责分散到各个子类中,每个子类负责创建一种具体产品。客户端只需要知道具体工厂类,而不需要知道具体的产品类。

结构

  • 抽象工厂类(Creator):声明一个工厂方法,返回一个产品对象。
  • 具体工厂类(ConcreteCreator):实现工厂方法,返回具体的产品对象。
  • 产品接口(Product):定义产品的基本功能。
  • 具体产品类(ConcreteProduct):实现产品接口,定义具体的产品功能

示例代码:

// 产品接口
public interface Product {
    void use();
}

// 具体产品A
public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using Product A");
    }
}

// 具体产品B
public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using Product B");
    }
}

// 抽象工厂类
public abstract class Creator {
    public abstract Product factoryMethod();
}

// 具体工厂A
public class ConcreteCreatorA extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductA();
    }
}

// 具体工厂B
public class ConcreteCreatorB extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductB();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Creator creatorA = new ConcreteCreatorA();
        Product productA = creatorA.factoryMethod();
        productA.use();

        Creator creatorB = new ConcreteCreatorB();
        Product productB = creatorB.factoryMethod();
        productB.use();
    }
}

这里我们可以清晰的看到,每个具体的产品都有一个具体的工厂,需要哪种具体的实例,只需要找到对应的具体的工厂获取即可。但是,同时也会有一个问题:如果有大量的具体产品类,那么就需要大量的具体工厂类,可能会导致 “类的爆炸”(这里只是形象的表述一下,但它可以被理解为由于类的数量过多而导致的代码库复杂性增加和维护难度加大的问题)

优缺点

  • 优点:
    • 客户端只需要知道工厂方法,而不需要了解产品的具体类。
    • 符合开闭原则,当需要添加新的产品时,只需要增加新的工厂类和产品类,不需要修改现有代码。
  • 缺点:
    • 当产品种类非常多时,可能需要创建大量的具体工厂类。

适用场景

  • 需要通过子类决定产品的创建方式时,适合使用工厂方法模式。
  • 当产品种类比较多,且需要对不同产品使用不同的创建方式时,工厂方法模式会更加灵活。

抽象工厂模式

抽象工厂模式提供了一个接口,用于创建一系列相关或相互依赖的对象。每个具体工厂类都可以创建一组相关的产品,但它们的具体产品是不同的。抽象工厂模式适用于创建多个相关产品族的情况。

结构

  • 抽象工厂接口(AbstractFactory):声明创建一组产品的方法。
  • 具体工厂类(ConcreteFactory):实现抽象工厂接口,创建一组具体产品。
  • 抽象产品接口(AbstractProduct):声明产品的基本功能。
  • 具体产品类(ConcreteProduct):实现抽象产品接口,定义具体的产品功能。

示例代码:

// 抽象产品A
public interface AbstractProductA {
    void use();
}

// 抽象产品B
public interface AbstractProductB {
    void use();
}

// 具体产品A1
public class ConcreteProductA1 implements AbstractProductA {
    @Override
    public void use() {
        System.out.println("Using ConcreteProductA1");
    }
}

// 具体产品A2
public class ConcreteProductA2 implements AbstractProductA {
    @Override
    public void use() {
        System.out.println("Using ConcreteProductA2");
    }
}

// 具体产品B1
public class ConcreteProductB1 implements AbstractProductB {
    @Override
    public void use() {
        System.out.println("Using ConcreteProductB1");
    }
}

// 具体产品B2
public class ConcreteProductB2 implements AbstractProductB {
    @Override
    public void use() {
        System.out.println("Using ConcreteProductB2");
    }
}

// 抽象工厂
public interface AbstractFactory {
    AbstractProductA createProductA();
    AbstractProductB createProductB();
}

// 具体工厂1
public class ConcreteFactory1 implements AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA1();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ConcreteProductB1();
    }
}

// 具体工厂2
public class ConcreteFactory2 implements AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA2();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ConcreteProductB2();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        AbstractFactory factory1 = new ConcreteFactory1();
        AbstractProductA productA1 = factory1.createProductA();
        productA1.use();
        AbstractProductB productB1 = factory1.createProductB();
        productB1.use();

        AbstractFactory factory2 = new ConcreteFactory2();
        AbstractProductA productA2 = factory2.createProductA();
        productA2.use();
        AbstractProductB productB2 = factory2.createProductB();
        productB2.use();
    }
}

简单解读一下:

我们有产品A和产品B两个大类,产品A中又有两个A系列的产品 A1 和 A2,产品B中又有B系列的产品 B1 和 B2,如果按照前面说工厂方法模式,就需要创建四个具体产品类工厂,未免有些麻烦。仔细看一看,这几个产品都是有关系的,由于产品都有 1号 和 2号 两个不同型号的产品,所以我们可以设计两个工厂(当然,需要先设计一个抽象工厂,这里就不多说了),一个主要生产 A1 和 B1 产品的工厂,一个主要生产 A2 和 B2 产品的工厂,这样设计看着就比较合理了。
其实我个人认为,由于具体产品之间有着某种关系,借助这种关系,我们可以将工厂方法模式进而改造成这种抽象工厂模式(个人见解,可能有些许错误,望某位大佬指点一下)

优缺点

  • 优点:
    • 客户端可以通过抽象工厂接口创建一系列相关的产品对象,避免了对具体类的依赖。
    • 符合开闭原则,能够很容易扩展新的产品族。
  • 缺点:
    • 增加了类的数量和复杂度。
    • 当需要扩展产品种类时,可能需要修改多个工厂类和产品类。

适用场景

  • 当系统需要提供多个产品族,并且每个产品族中的产品需要一起使用时,适合使用抽象工厂模式。
  • 当系统中有多个系列的产品需要创建,且这些产品之间有依赖关系时,抽象工厂模式是非常有用的。

总结

三个工厂模式对比如下

在使用的时候,应当结合具体情况,选择最为合适的工厂模式进行设计

image-20241217182825098

标签:use,Product,模式,工厂,具体,产品,设计模式,public
From: https://blog.csdn.net/AIAIAIXIAO_/article/details/144541908

相关文章

  • Z-BlogPHP 调试模式的作用是什么?
    在Z-BlogPHP中,调试模式(DebugMode)是一个非常有用的工具,它可以帮助开发者和管理员诊断和解决网站程序中的各种问题。以下是调试模式的主要作用和使用方法:显示详细的错误信息:当调试模式开启时,Z-BlogPHP会显示详细的错误信息,包括错误类型、错误消息、发生错误的文件和行号。......
  • 【设计模式与体系结构】创建型模式-工厂模式
    简介工厂方法模式是一种创建对象的设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法把实例化操作推迟到子类中实现。工厂方法模式的角色抽象工厂类:声明工厂方法,负责创建产品对象具体工厂类:实现抽象工厂类,负责创建具体的产品对象抽象产品类/接口:定......
  • 责任链模式
    ​责任链(ChainofResponsibility)模式属于行为型模式的一种。责任链模式是一种处理请求的模式,它让多个处理器都有机会处理该请求,直到其中某个处理成功为止。每个处理器都包含对下一个处理器的引用,从而形成链式结构。责任链模式把多个处理器串成链,然后让请求在链上进行传递。财务......
  • “上四休三”VS“混合模式”办公,如何安排工作时间实现高效办公
    前言最近日本东京颁布了“上四休三”的工作制,2025年4月开始启动。日本东京都政府将允许其员工每周工作4天,以扭转日本的低出生率。此制度规定只要雇员在4周内累计的工作时长达到155个小时,就可以自由安排休息时间。比如在周一至周四每天工作约为9.7小时,则可以选择在周五休息。......
  • 学霸带你游戏化训练批判性阅读打破传统思维模式
    高效的阅读技巧在面对海量信息时,提高阅读效率和准确性至关重要。批判性阅读不仅要求我们具备深入分析的能力,还需要有效管理阅读的时间和精力。通过提升阅读技巧,我们能够快速抓住关键信息,并高效完成信息筛选与处理。提升扫描与浏览技巧批判性阅读中,快速扫描和浏览能帮助我们......
  • 快消品 B2B 困境与破局:基于 2+1 链动模式与 S2B2C 商城小程序的思考
    摘要:本文深入剖析了快消品B2B行业面临的困境,包括诸多平台的衰落以及在用户端、品牌商、中间商和零售小店多方面遭遇的阻碍,揭示其脱离C端用户、缺乏各方支持而陷入“姥姥不疼,舅舅不爱”的尴尬处境。在此基础上,探讨2+1链动模式与S2B2C商城小程序在快消品B2B领域的应用......
  • C# 23种设计模式(5)命令模式(Command Pattern)
    一、命令模式介绍命令模式(CommandPattern)是一种行为设计模式,它将一个请求封装为一个对象,从而允许用户用不同的请求、队列请求、记录请求日志,以及支持可撤销的操作等。命令模式的主要目的是将请求的执行者和请求的接收者解耦,使得请求发送者和接收者之间不必直接交互。 命令......
  • 能源互联网的主要商业模式
    能源服务提供商模式基础服务:能源互联网企业作为能源服务提供商,为用户提供包括电力、热力、燃气等多种能源的供应服务。例如,整合分布式能源资源(如太阳能光伏发电、小型风力发电等)和传统能源供应,根据用户的能源需求进行统一调配。像一些社区能源服务公司,会收集社区内分布式太阳能......
  • 适配器模式应用~获取IP地址时想起了适配器
    获取IP地址信息时,一般我们需要一个HttpServletRequest对象,然后从请求头里获取x-forwarded-for的值,而当我们使用dubbo+netty开发rest接口时,如果希望获取IP地址,HttpServletRequest是用不了的,你需要使用netty中的NettyRequestFacade对象,这时,你之前的获取IP地址的方法需要扩展,加一个只......
  • 八大设计模式
    设计模式在日常软件开发中的重要性目录单例模式工厂模式策略模式代理模式观察者模式装饰器模式模板方法模式建造者模式总结单例模式单例模式确保一个类只有一个实例,通常用于管理共享资源,如配置、缓存、线程池等。代码实现:双重检查锁publicclassSingleton{pr......