软件设计模式系列之三———工厂方法模式

软件设计,模式,系列,之三,工厂,方法 · 浏览次数 : 225

小编点评

**6.1 UI控件的创建使用工厂方法模式** 工厂方法模式可用于创建跨平台的UI控件,并支持不同的UI库。通过创建一个工厂类,可以将UI控件的创建过程封装在工厂中,并客户端代码只需使用工厂接口来创建 UI控件对象。 **6.3 日志记录器** 工厂方法模式可用于创建多个日志记录器,并支持不同的日志记录方式。通过创建一个工厂类,可以将日志记录器的创建过程封装在工厂中,并客户端代码只需使用工厂接口来创建日志记录器对象。 **6.4 游戏中不同角色的创建使用工厂方法模式** 工厂方法模式可用于创建游戏中的不同角色,并支持不同的游戏引擎。通过创建一个工厂类,可以将角色的创建过程封装在工厂中,并客户端代码只需使用工厂接口来创建角色对象。 **7.优缺点工厂方法模式** **优点:** *松耦合 *可扩展性 *多态性 **缺点:** *类的数量增加 *复杂性增加 **8.类似模式** *抽象工厂模式 *简单工厂模式 **9.小结** 工厂方法模式是一种常用的设计模式,可用于创建跨平台的UI控件,并支持不同的UI库。通过创建一个工厂类,可以将UI控件的创建过程封装在工厂中,并客户端代码只需使用工厂接口来创建 UI控件对象。

正文

1 模式的定义

工厂方法模式是一种常见的设计模式,属于创建型设计模式之一,它在软件工程中用于对象的创建。该模式的主要思想是将对象的创建过程抽象化,将具体对象的实例化延迟到子类中完成,以便在不同情况下可以创建不同类型的对象,而客户端代码不需要知道实际创建的对象类型。

2 举例说明

小米和华为都生产自己的手机,就符合工厂方法模式。小米和华为都是手机制造商,而手机则是产品。每家公司都有自己的生产流程和标准,但它们都需要生产手机以满足市场需求。

工厂方法模式中,每家公司都有一个具体的工厂(小米工厂和华为工厂),这些工厂实现了一个共同的抽象工厂接口。抽象工厂定义了一个方法用于生产手机,但具体的手机生产过程由每家公司的工厂来实现。

客户端代码可以根据需要选择使用小米工厂或华为工厂来生产手机。这种方式下,客户端代码无需关心手机的具体制造过程,只需知道如何与抽象工厂交互即可。

工厂方法模式的优点在于它实现了对象的创建和客户端代码的解耦,使得不同的工厂可以独立扩展,适用于多样化的产品生产场景。小米和华为手机的制造就是一个生动的示例,其中工厂方法模式为不同公司的手机生产提供了一种灵活的、可扩展的解决方案

3 结构

工厂方法模式的结构包括以下几个关键角色:

  • 抽象工厂接口(Factory):这是工厂方法模式的核心部分,它定义了一个或多个工厂方法的接口,这些方法用于创建具体产品对象。通常,这个接口中会包含多个方法,每个方法用于创建不同类型的产品。客户端代码通过调用这些工厂方法来获取产品对象。
  • 具体工厂类(Concrete Factory):这是实现抽象工厂接口的具体类,每个具体工厂类负责创建一类具体产品。它实现了工厂方法,根据客户端的需求创建具体的产品对象。每个具体工厂类通常对应一个特定的产品族。
  • 抽象产品接口(Product):这个接口定义了产品对象的通用属性和方法,所有具体产品类都必须实现这个接口。客户端代码将与抽象产品接口进行交互,而不直接与具体产品类进行交互。
  • 具体产品类(Concrete Product):这些是实际的产品类,它们实现了抽象产品接口,定义了具体产品的属性和行为。每个具体产品类对应一个具体工厂类。
  • 客户端(Client):客户端代码需要创建产品对象,但它不直接与具体产品类或具体工厂类交互。客户端通过调用抽象工厂接口中的工厂方法来创建产品对象,从而实现了解耦的目的。

工厂方法模式的结构允许在不修改客户端代码的情况下引入新的具体产品类和具体工厂类,从而增加系统的可扩展性。客户端只需要知道抽象工厂接口和抽象产品接口,而不需要关心具体的产品类和工厂类,这使得系统更易于维护和扩展。

总结来说,工厂方法模式的结构包括抽象工厂接口、具体工厂类、抽象产品接口、具体产品类以及客户端。这个模式通过将对象的创建委托给具体工厂类来实现对象的创建和客户端与产品之间的解耦。

4 实现步骤

工厂方法模式的实现步骤通常包括以下几个关键步骤:

  • 定义抽象产品接口(Product):定义一个抽象产品接口,它声明了产品对象的通用属性和方法。所有具体产品类都必须实现这个接口。
  • 创建具体产品类(Concrete Product):实现抽象产品接口的具体产品类。每个具体产品类表示一种具体的产品。
  • 定义抽象工厂接口(Factory):创建一个抽象工厂接口,该接口声明了工厂方法,用于创建产品对象。
  • 创建具体工厂类(Concrete Factory):实现抽象工厂接口的具体工厂类,每个具体工厂类负责创建特定类型的产品。在客户端中使用工厂方法:
  • 客户端代码通过具体工厂类的工厂方法来创建产品对象,而不直接实例化具体产品类。

通过上述步骤,您就可以实现工厂方法模式。这种模式允许客户端根据需要选择合适的具体工厂来创建产品,从而实现了解耦和可扩展性。如果需要添加新的产品类型,只需创建新的具体产品类和对应的具体工厂类,而不需要修改现有的客户端代码。

5 代码实现

以下是使用工厂方法模式实现抽象工厂(AbstractFactory)、具体工厂(XiaomiFactoryHuaweiFactory)、抽象产品(AbstractMobile)和具体产品(XiaomiMobileHuaweiMobile)的Java代码示例:

// 抽象产品接口
interface AbstractMobile {
    void displayInfo();
}

// 具体产品类 - 小米手机
class XiaomiMobile implements AbstractMobile {
    @Override
    public void displayInfo() {
        System.out.println("这是小米手机。");
    }
}

// 具体产品类 - 华为手机
class HuaweiMobile implements AbstractMobile {
    @Override
    public void displayInfo() {
        System.out.println("这是华为手机。");
    }
}

// 抽象工厂接口
interface AbstractFactory {
    AbstractMobile createMobile();
}

// 具体工厂类 - 小米工厂
class XiaomiFactory implements AbstractFactory {
    @Override
    public AbstractMobile createMobile() {
        return new XiaomiMobile();
    }
}

// 具体工厂类 - 华为工厂
class HuaweiFactory implements AbstractFactory {
    @Override
    public AbstractMobile createMobile() {
        return new HuaweiMobile();
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        // 使用具体工厂创建具体产品
        AbstractFactory xiaomiFactory = new XiaomiFactory();
        AbstractMobile xiaomiMobile = xiaomiFactory.createMobile();
        xiaomiMobile.displayInfo();

    AbstractFactory huaweiFactory = new HuaweiFactory();
        AbstractMobile huaweiMobile = huaweiFactory.createMobile();
        huaweiMobile.displayInfo();
    }
}


在这个代码示例中,我们定义了抽象产品接口 AbstractMobile 和两个具体产品类 XiaomiMobileHuaweiMobile。然后,我们定义了抽象工厂接口 AbstractFactory,其中包含了一个工厂方法 createMobile(),用于创建手机产品。

接下来,我们创建了两个具体工厂类 XiaomiFactoryHuaweiFactory,分别实现了 AbstractFactory 接口,并在其中实现了工厂方法,分别用于创建小米手机和华为手机。

最后,在客户端代码中,我们使用不同的具体工厂来创建不同的手机产品,从而实现了工厂方法模式,客户端代码不需要知道具体产品的细节,只需要知道如何使用抽象工厂来创建产品

6 典型应用场景

6.1 数据库驱动程序的创建

使用工厂方法模式来进行数据库驱动程序创建的场景是在软件开发中需要连接不同类型的数据库(例如MySQL、PostgreSQL、Oracle等)时。通过工厂方法模式,可以将不同数据库的连接对象的创建过程封装在各自的工厂类中,客户端代码无需关心具体的数据库驱动程序实现,只需使用相应的工厂来创建数据库连接对象,从而实现了灵活性和可扩展性,能够轻松地切换和添加新的数据库驱动程序,而不影响现有的代码。这种模式在多数据库支持和数据库连接的抽象化方面非常有用。

6.1 UI控件的创建

使用工厂方法模式进行UI控件创建的场景是在图形用户界面(GUI)开发中。不同操作系统或界面库(如Windows、macOS、Android等)可能使用不同的UI控件(如按钮)。通过工厂方法模式,可以将每种UI控件的创建过程封装在各自的工厂类中,客户端代码无需关心具体的控件实现,只需使用相应的工厂来创建控件对象,从而实现了跨平台和可扩展性,使得应用程序能够在不同的操作系统或界面库下创建合适的UI控件,而不需要重写整个界面代码。这种模式在多平台UI开发和UI组件的抽象化方面非常有用。

6.3 日志记录器

在应用程序中需要记录日志以进行调试、故障排除和性能监测时。不同的日志记录方式(如文件日志、数据库日志、控制台日志等)可能需要使用不同的日志记录器。通过工厂方法模式,可以将每种日志记录器的创建过程封装在各自的工厂类中,客户端代码无需关心具体的日志记录器实现,只需使用相应的工厂来创建日志记录器对象,从而实现了灵活性和可扩展性,使得应用程序可以根据需求选择不同的日志记录方式,而不需要修改主要的应用逻辑。这种模式在日志记录方式的切换和定制化日志记录方面非常有用。

6.4 游戏中不同角色的创建

使用工厂方法模式来创建游戏中不同角色的场景是在游戏开发中。在游戏中,有各种不同类型的角色(如玩家、敌人、道具、NPC等),每个角色都有自己独特的属性和行为。通过工厂方法模式,可以将每种角色的创建过程封装在各自的工厂类中,客户端代码无需关心具体的角色实现,只需使用相应的工厂来创建角色对象,从而实现了游戏角色的动态创建和管理。这种模式在游戏中角色的扩展和多样化方面非常有用,使得游戏开发人员可以轻松地添加新的角色类型,而不需要修改游戏引擎或核心逻辑。

7 优缺点

工厂方法模式是一种常用的设计模式,它具有一些优点和缺点:

优点:

松耦合 :工厂方法模式将对象的创建过程封装在工厂类中,客户端代码与具体产品类解耦。客户端代码只需要关心抽象工厂和产品接口,无需了解具体产品的细节。

可扩展性 :通过添加新的具体工厂类和具体产品类,可以轻松扩展系统以支持新的产品类型,而不需要修改现有的代码。这使得系统更容易维护和扩展。

多态性 :工厂方法模式利用了多态性,使得客户端可以根据需要创建不同类型的产品对象,而无需改变客户端代码。

符合开闭原则 :工厂方法模式遵循开闭原则,对修改关闭,对扩展开放。添加新的产品类型只需要添加新的具体工厂类和具体产品类,而不需要修改现有代码。

缺点:

类的数量增加 :引入工厂方法模式会增加类的数量,每个具体产品类都需要一个对应的具体工厂类。对于一些简单的情况,可能会使代码变得复杂。

复杂性增加 :在有多层继承结构的情况下,可能会引入更多的层次,增加代码的复杂性。

不适用于单例 :工厂方法模式通常用于创建多个对象,不适用于创建单例对象。对于单例模式,通常使用其他模式,如单例模式或者静态工厂方法。

增加代码复杂度 :在简单情况下,使用工厂方法模式可能会增加不必要的复杂性,不如直接实例化对象来得简单。

总之,工厂方法模式在实现对象的创建和客户端代码解耦方面有很多优点,但也需要谨慎使用,根据具体情况来决定是否使用该模式,以确保代码的可维护性和扩展性。

8 类似模式

工厂方法模式、抽象工厂模式和简单工厂模式都是创建型设计模式,用于对象的创建,但它们在关注点和应用场景上存在差异。

简单工厂模式是一种简化对象创建的方法,不是 GoF(Gang of Four)的正式设计模式。简单工厂适用于创建少量的对象,但不符合开闭原则,不支持扩展新的产品类型。

工厂方法模式是一种正式的设计模式,定义了一个创建对象的接口,具体的对象创建延迟到子类中完成。用于创建单一产品等级结构。

抽象工厂模式也是一种正式的设计模式,提供一个接口,用于创建一系列相关或依赖的对象,不需要指定具体的类。每个具体工厂类可以创建一组相关的产品,用于创建多个相关的产品等级结构或整个产品族。

它们都以不同的方式提供了对象创建的灵活性和可扩展性,根据需求选择合适的模式。

9 小结

工厂方法模式是一种常用的设计模式,属于创建型设计模式,其核心思想是将对象的创建延迟到子类中去完成。特别适合在需要创建多个相关但不同类型的对象时,以提高代码的可维护性和可扩展性。它将对象的创建过程进行了抽象,使得客户端代码更加灵活,可以根据需要选择不同的具体工厂来创建对象。

与软件设计模式系列之三———工厂方法模式相似的内容:

软件设计模式系列之三———工厂方法模式

工厂方法模式是一种常见的设计模式,属于创建型设计模式之一,它在软件工程中用于对象的创建。该模式的主要思想是将对象的创建过程抽象化,将具体对象的实例化延迟到子类中完成,以便在不同情况下可以创建不同类型的对象,而客户端代码不需要知道实际创建的对象类型。

软件设计模式系列之二———抽象工厂模式

抽象工厂模式是一种创建型设计模式,它提供了一种创建一组相关或相互依赖对象的方式,而无需指定它们的具体类。该模式以一组抽象接口为核心,包括抽象工厂接口和一组抽象产品接口,每个具体工厂类负责创建特定产品家族,保证这些产品之间的兼容性。客户端代码通过与抽象工厂和抽象产品接口交互,可以轻松地切换不同工厂来创建不同系列的产品。

软件设计模式系列之四——简单工厂模式

简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,用于对象的创建,它属于工厂模式的一种。简单工厂模式的主要目标是封装对象的创建过程,使客户端代码与具体类的实例化解耦,从而提高代码的可维护性和可扩展性。

软件设计模式系列之八——适配器模式

适配器模式(Adapter Pattern)是一种结构性设计模式,它允许将一个类的接口转换成客户端希望的另一个接口。适配器模式通常用于解决两个不兼容接口之间的兼容性问题,使得不同接口的类可以一起工作。这个模式涉及一个称为适配器的类,它充当两个不同接口之间的桥梁,使得它们可以协同工作。

从零做软件开发项目系列之五——系统开发过程

在软件项目的设计开发过程中,除了前期的用户需求调研确认,系统设计、数据库设计等工作之外,还有一些重要的工作需要考虑,比如软件开发模式,如何制定开发计划,如何协调开发人员开展开发工作等。

软件设计模式系列之六——单例模式

单例模式(Singleton Pattern)是一种常见的创建型设计模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点来获取该实例。这意味着无论何时何地,只要需要该类的实例,都会返回同一个实例,而不是创建多个相同的实例。

软件设计模式系列之十一——装饰模式

装饰模式属于结构型设计模式,它通过将对象包装在装饰器类中来动态地添加额外的行为,而不需要修改原始对象的代码。这个模式以透明的方式向对象添加功能,从而使您可以根据需要组合各种功能。

软件设计模式系列之十二——外观模式

外观模式是一种结构型设计模式,它提供了一个简化的接口,用于访问系统中的一组相关接口,以隐藏系统的复杂性。外观模式的主要目标是简化客户端与子系统之间的交互,同时降低了系统的耦合度。它允许客户端通过一个统一的入口点来与系统进行通信,而不需要了解系统内部的具体细节和复杂性

软件设计模式系列之十三——享元模式

享元模式(Flyweight Pattern)是一种结构型设计模式,它旨在减少内存占用或计算开销,通过共享大量细粒度对象来提高系统的性能。这种模式适用于存在大量相似对象实例,但它们的状态可以外部化(extrinsic),并且可以在多个对象之间共享的情况。

软件设计模式系列之十四——代理模式

代理模式是一种结构型设计模式,它允许一个对象(代理)充当另一个对象的接口,以控制对该对象的访问。代理模式通常用于控制对真实对象的访问,以实现一些额外的功能,例如延迟加载、权限控制、日志记录等。这种模式属于结构型设计模式,因为它关注对象之间的组合,以形成更大的结构。