# 工厂模式创建对象以及实现继承
# 课程目标
- 编写一个返回对象的工厂方法。
- 描述私有函数和变量如何有用。
- 使用工厂模式在对象中使用继承。
- 掌握模块模式基础知识
# 使用工厂模式创建对象
工厂模式是一种众所周知的设计模式,广泛应用与软件工程领域,用于抽象创建特定对象的过程。
先看下在这种设计模式下,应该如何组织我们的代码,例如,我们可能会想要对象来描述一个人,并封装这个人可以做的所有事情
const Person = (name, age) => {
return {
name,
age,
birthday() {
console.log(`${name}长大了一岁`);
this.age++;
},
eat() {
console.log(`${name}正在吃饭`);
},
};
};
//创建了两个人
const person1 = Person("Jack", 32);
const person2 = Person("Lisa", 5);
console.log(person1.name); //"Jack"
console.log(person2.age); //"5"
person2.birthday(); //"Lisa 长大了一岁"
console.log(person2.age); //"6"
阅读下面材料学习深入工厂模式
- Factory Functions in JavaScript (opens new window)
- JavaScript 是如何工作的:工厂设计模式 + 4 个用例 (opens new window)
# 使用工厂模式实现继承
现在我们来看看如何在工厂模式下实现继承。比如我们希望再封装一个学生对象,学生对象应当继承于人
const Student = (name, age, job) => {
const prototype = Person(name, age); //继承 Person 对象
return Object.assign({}, prototype, {
job,
study() {
console.log(`${name}正在学习`);
},
});
};
//创建一个学生
const student1 = Student("Jennie", 18, "student");
console.log(student1.name); //"Jennie"
console.log(student1.age); //"18"
student1.birthday(); //"Jennie 长大了一岁"
student1.study(); //"Jennie 正在学习"
由上可见对象 Student 继承了对象 Person 的属性:name,age 和方法: birthday,还具有自己的属性:job,以及方法:study
工厂模式很棒,因为它允许您选择要包含在新对象中的功能,比如,如果你只想继承对象 Person 的 eat 方法,不想继承 birthday 方法,您可以这样做:
const Student = (name, age, job) => {
const { eat } = Person(name, age); //只继承了 eat 方法
return Object.assign(
{},
{ eat },
{
job,
study() {
console.log(`${name}正在学习`);
},
}
);
};
const student2 = Student("Penny", 16, "student");
console.log(student2.name); //"Penny"
console.log(student2.age); //"18"
student2.eat(); //"Jennie 正在吃饭"
student2.birthday(); //报错 - Uncaught TypeError: student2.birthday is not a function
# 模块模式
模块模式实际上与工厂函数非常相似。主要区别在于它们的创建方式。
我们先来看一个模块:
const StringMethods = (() => {
const uppercase = (str) => str.toUpperCase();
const lowercase = (str) => str.toLowerCase();
const capitalize = (str) =>
str.slice(0, 1).toUpperCase() + str.slice(1).toLowerCase();
return {
uppercase,
lowercase,
capitalize,
};
})();
console.log(StringMethods.uppercase("css")); // CSS
console.log(StringMethods.lowercase("JAVAScript")); // javascript
console.log(StringMethods.capitalize("html")); // Html
然而,模块模式不是创建一个我们可以反复使用来创建多个对象的工厂,而是将工厂包装在一个 IIFE(立即调用函数表达式)中,只暴露出我们需要调用的方法。
上一节我们学习了 IIFE,忘记的同学可以去回顾一下
阅读下面材料,学习模块模式基础知识
# 任务
现在你需要开发一个表单生成器,需要做到表单元素的自动生成。请你采用工厂模式来创建表单元素对象。
实现以 JavaScript 对象的方式定义表单及验证规则 表单配置参考示例如下:(不需要一致,仅为参考)
{
label: '名称', // 表单标签
type: 'input', // 表单类型
validator: function () {...}, // 表单验证规
rules: '必填,长度为4-16个字符', // 填写规则提示
success: '格式正确', // 验证通过提示
fail: '名称不能为空' // 验证失败提示
}
- 基于该配置项,实现一套逻辑,可以自动生成表单的展现、交互、验证
- 使用你制作的表单工厂,在一个页面上创建两套样式不同的表单
注意事项
- 实现中,尽可能考虑代码的可读性和可复用性
- 尽量时表单配置、生成、样式、验证几个逻辑之间的耦合度足够低
- 请注意代码风格的整齐、优雅
- 代码中含有必要的注释
- 不允许借助任何第三方组件库实现