Menu
CoddyTech

工厂函数

本课属于 Coddy Lua 学习旅程的“面向对象编程”单元。第 62 课,共 70 课。

在整个课程中,你一直通过直接调用构造函数来创建对象:Circle:new()、Rectangle:new(),等等。但如果你想根据某个条件创建不同类型的对象,同时又不想让调用代码知道要使用哪个具体的类,该怎么办?

这就是工厂模式发挥作用的地方。工厂就是一个创建并返回对象的函数。它的主要好处是,调用方不需要了解对象创建的细节,只需向工厂提出所需对象即可。

local function createShape(shapeType)
    if shapeType == "circle" then
        return Circle:new(10)
    elseif shapeType == "square" then
        return Square:new(5)
    end
end

-- 调用方不需要了解 Circle 类或 Square 类。
local myShape = createShape("circle")
print(myShape:area())

工厂函数接收一个字符串参数,并决定要实例化哪个类。这样就能把对象创建逻辑集中在一个地方。如果你之后添加新的形状类型,只需修改工厂函数,而不必修改每一处创建形状的代码。

当对象的创建过程涉及复杂的设置、你想隐藏实现细节,或者对象的具体类型取决于用户输入或配置文件等运行时条件时,工厂尤其有用。

challenge icon

挑战

简单

让我们来构建一个宠物工厂!你不用直接调用每个类的构造函数来创建宠物,而是创建一个工厂函数,根据简单的字符串参数生成合适类型的宠物。

你会把代码分成 4 个文件:

  • Dog.lua:创建一个 Dog 类,其中包含一个 :new(name) 构造函数,用于存储宠物的名字。添加一个 :speak() 方法,返回字符串 "{name} says: Woof!"(其中 {name} 是狗的名字)。
  • Cat.lua:创建一个与 Dog 结构相同的 Cat 类,其中包含一个 :new(name) 构造函数和一个 :speak() 方法,后者返回 "{name} says: Meow!"。
  • PetFactory.lua:工厂模式在这里大显身手!创建一个 createPet(petType, name) 函数,它接受两个参数:一个表示宠物类型的字符串("dog" 或 "cat")和宠物的名字。函数应返回合适的宠物对象。如果类型是 "dog",就返回一个新的 Dog;如果是 "cat",就返回一个新的 Cat。
  • main.lua:引入 PetFactory 模块。读取两个输入:宠物类型和宠物的名字。使用工厂函数创建宠物,然后调用它的 :speak() 方法并打印结果。

工厂模式的妙处在于,主代码不需要直接引入 Dog 或 Cat。它只需要知道工厂即可。由工厂负责处理实例化哪个类的所有细节。

你会收到两个输入:

  1. 宠物类型(可以是 "dog" 或 "cat")
  2. 宠物名字(一个字符串)

例如,如果输入是 dog 和 Buddy,输出应为:

Buddy says: Woof!

如果输入是 cat 和 Whiskers,输出应为:

Whiskers says: Meow!

亲手试试

-- main.lua
-- 使用 PetFactory 创建宠物

local PetFactory = require('PetFactory')

-- 读取输入
local petType = io.read()
local petName = io.read()

-- TODO: 使用 PetFactory.createPet 创建宠物
-- TODO: 调用宠物的 :speak() 方法并打印结果
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Lua 在线编译器