工厂函数
本课属于 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())
工厂函数接收一个字符串参数,并决定要实例化哪个类。这样就能把对象创建逻辑集中在一个地方。如果你之后添加新的形状类型,只需修改工厂函数,而不必修改每一处创建形状的代码。
当对象的创建过程涉及复杂的设置、你想隐藏实现细节,或者对象的具体类型取决于用户输入或配置文件等运行时条件时,工厂尤其有用。
挑战
简单让我们来构建一个宠物工厂!你不用直接调用每个类的构造函数来创建宠物,而是创建一个工厂函数,根据简单的字符串参数生成合适类型的宠物。
你会把代码分成 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。它只需要知道工厂即可。由工厂负责处理实例化哪个类的所有细节。
你会收到两个输入:
- 宠物类型(可以是
"dog"或"cat") - 宠物名字(一个字符串)
例如,如果输入是 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() 方法并打印结果
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Lua 在线编译器