设计模式学习之工厂方法模式

文章介绍了在面对产品数量增多和多维度需求时,如何从简单工厂模式过渡到工厂方法模式。在简单工厂模式适用于产品数量较少的情况,而当产品和平台等多因素需要考虑时,工厂方法模式提供了解决方案,通过创建者类的工厂方法创建不同类型的实现类对象,适应不同平台的UI组件需求。

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

设计模式系列往期文章

  1. 设计模式学习之策略模式
  2. 设计模式学习之策略模式在前端的应用
  3. 设计模式学习之简单工厂模式

在上一篇文章中我们学习了简单工厂模式——这是工厂模式中最简单的一种模式,通过工厂类提供的方法创建类(可以类比为产品),将对象创建的具体逻辑屏蔽了起来。在需求比较简单,产品的数量比较少的情况下,简单工厂模式已经能够满足业务需要了,但是如果当产品数量非常多的时候(如几十上百个),使用简单工厂就有些捉襟见肘了。

以下图为例,我们需要开发一个跨平台的UI工具库,该工具库至少能够在Windows应用和网页端运行,很明显同一个组件(如Button)在这两个平台的实现代码是不一样的,在这种情况下使用简单工厂模式进行实现就有些麻烦了,因为现在有两个维度:平台和组件,那么应该怎么做呢?
在这里插入图片描述
我们先试着将这个问题简化:如果现在不考虑跨平台应用,只支持HTML进行组件的绘制就可以,这个时候就可以使用简单工厂了,代码如下:

interface Element {
	void render();
	void onClick();
}

class Button implements Element {
	public void render() {
        System.out.println("<button>Test Button</button>");
        onClick();
    }

    public void onClick() {
        System.out.println("Click! Button says - 'Hello World!'");
    }
}

class Text implements Element {
	public void render() {
        System.out.println("<p>Test Text</p>");
        onClick();
    }

    public void onClick() {
        System.out.println("Click! Text says - 'Hello World!'");
    }
}

class ElementFactory {
	public static Element createElement(String type) {
		switch(type) {
			case "Button":
				return new Button();
			case "Text":
				return new Text();
			default:
				return null;
		}
	}
}

之所以可以这么写,是因为产品数量比较少并且工厂产出的数据都是同一个维度的。对于多维度的数据的时候就需要请出工厂方法模式了,对应的实现思路就如上图所示的那样:

  • 将Button看做工厂生产的产品接口
  • 将WindowButton和HTMLButton看做具体的产品实现类
  • 将WindowDialog和WebDialog看做具体的工厂实现类,由他们负责生产出对应的产品
  • 将Dialog看做工厂类的抽象接口

上面的类的实现伪代码如下:

// 创建者类声明的工厂方法必须返回一个产品类的对象。创建者的子类通常会提供
// 该方法的实现。
class Dialog is
    // 创建者还可提供一些工厂方法的默认实现。
    abstract method createButton():Button

    // 请注意,创建者的主要职责并非是创建产品。其中通常会包含一些核心业务
    // 逻辑,这些逻辑依赖于由工厂方法返回的产品对象。子类可通过重写工厂方
    // 法并使其返回不同类型的产品来间接修改业务逻辑。
    method render() is
        // 调用工厂方法创建一个产品对象。
        Button okButton = createButton()
        // 现在使用产品。
        okButton.onClick(closeDialog)
        okButton.render()


// 具体创建者将重写工厂方法以改变其所返回的产品类型。
class WindowsDialog extends Dialog is
    method createButton():Button is
        return new WindowsButton()

class WebDialog extends Dialog is
    method createButton():Button is
        return new HTMLButton()


// 产品接口中将声明所有具体产品都必须实现的操作。
interface Button is
    method render()
    method onClick(f)

// 具体产品需提供产品接口的各种实现。
class WindowsButton implements Button is
    method render(a, b) is
        // 根据 Windows 样式渲染按钮。
    method onClick(f) is
        // 绑定本地操作系统点击事件。

class HTMLButton implements Button is
    method render(a, b) is
        // 返回一个按钮的 HTML 表述。
    method onClick(f) is
        // 绑定网络浏览器的点击事件。


class Application is
    field dialog: Dialog

    // 程序根据当前配置或环境设定选择创建者的类型。
    method initialize() is
        config = readApplicationConfigFile()

        if (config.OS == "Windows") then
            dialog = new WindowsDialog()
        else if (config.OS == "Web") then
            dialog = new WebDialog()
        else
            throw new Exception("错误!未知的操作系统。")

    // 当前客户端代码会与具体创建者的实例进行交互,但是必须通过其基本接口
    // 进行。只要客户端通过基本接口与创建者进行交互,你就可将任何创建者子
    // 类传递给客户端。
    method main() is
        this.initialize()
        dialog.render()

类图

工厂方法模式的UML图如下
在这里插入图片描述

对应UML语言:

@startuml

skinparam linetype ortho

package "Factory Method" <<Frame>> {
  interface ProductIntf {
    + method()
  }

  interface FactoryIntf {
    + createProduct()
  }

  class AProduct {
    + method()
  }

  class BProduct {
    + method()
  }

  class AFactory {
    + createProduct()
  }

  class BFactory {
    + createProduct()
  }

  class Client {
  }

  ProductIntf <|.. AProduct
  ProductIntf <|.. BProduct

  FactoryIntf <|.. AFactory
  FactoryIntf <|.. BFactory

  AProduct <.. AFactory
  BProduct <.. BFactory

  Client ..> FactoryIntf
}
@enduml
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值