• js构造函数之工厂模式(学习笔记1)


    目录

    一、简单工厂

    1、存储一个用户信息

    2、存储N个用户信息

    3、存储N个用户信息+不同年龄用户有不同美食的搭配方案【简单工厂模式】

    二、抽象工厂模式

    1、抽象工厂(AbstractFactory)

    2、具体工厂(ConcreteFactory)

    3、生产新款手机

    4、总结


    本文是小编阅读《JavaScript 设计模式核心原理与应用实践》这本书,记录的学习笔记,更多详细知识可以直接阅读原文

    JavaScript 设计模式核心原理与应用实践——掘金小册icon-default.png?t=N7T8https://juejin.cn/book/6844733790204461070/section/6844733790246404109首要任务:认识哪些是变与不变


    一、简单工厂

    通过实现用户需求举例

    1、存储一个用户信息

    1. // 原始对象
    2. const obj = {
    3. id:1,
    4. name:'sxx',
    5. age:19,
    6. sex:1
    7. }
    8. console.log(obj);

    2、存储N个用户信息

    1. // 简单构造器
    2. class User{
    3. constructor(id,name,age,sex){
    4. this.id = id
    5. this.name = name
    6. this.age = age
    7. this.sex = sex
    8. }
    9. }
    10. // 调用简单构造器
    11. const me = new User(1,'sxx',19,1);
    12. const you = new User(2,'张三',66,0);
    13. console.log(me,you);

    在创建一个user过程中,谁变了,谁不变?

    很明显,变的是每个user的姓名、年龄这些值,这是用户的个性,不变的是每个员工都具备姓名、年龄、工种这些属性,这是用户的共性

    3、存储N个用户信息+不同年龄用户有不同美食的搭配方案【简单工厂模式】

    (1)笨方法

    1. // 一个一个构建构造器【笨方法】
    2. class Young{
    3. constructor(id,name,sex){
    4. this.id = id
    5. this.name = name
    6. this.age = 19
    7. this.sex = sex
    8. this.food = ['汉堡','炸鸡','可乐']
    9. }
    10. }
    11. class Old{
    12. constructor(id,name,sex){
    13. this.id = id
    14. this.name = name
    15. this.age = 99
    16. this.sex = sex
    17. this.food = ['稀饭','青菜','荔枝肉']
    18. }
    19. }
    20. function Factory(id,name,age,sex){
    21. switch(age){
    22. case 19:
    23. return new Young(id,name,sex)
    24. case 99:
    25. return new Old(id,name,sex)
    26. }
    27. }
    28. const me = Factory(1,'sxx',19,1)
    29. const you = Factory(2,'张三',99,0)
    30. console.log(me,you);

    (2)灵活方法

    1. // 观察变与不变【灵活方法】
    2. class User{
    3. constructor(id,name,age,sex,food){
    4. this.id = id
    5. this.name = name
    6. this.age = age
    7. this.sex = sex
    8. this.food = food
    9. }
    10. }
    11. function Factory(id,name,age,sex){
    12. let food
    13. switch(age){
    14. case 3:
    15. food = ['奶粉','米糊']
    16. break
    17. case 19:
    18. food = ['汉堡','炸鸡','可乐']
    19. break
    20. case 99:
    21. food = ['稀饭','青菜','荔枝肉']
    22. break
    23. }
    24. return new User(id,name,age,sex,food)
    25. }
    26. console.log(Factory(1,'baby',3,0));
    27. console.log(Factory(2,'sxx',19,1));
    28. console.log(Factory(3,'张三',99,0));


    新的需求:

    ①推出普通、豪华、至尊等套餐,不同年龄用户能够自主选择套餐

    ②拓展功能:供服务员、厨师、老板等使用

    以上需求,每一次都要回去修改 Factory 的函数体,Factory会变得异常庞大——没有遵守开放封闭原则

    开放封闭原则:对拓展开放,对修改封闭。软件实体(类、模块、函数)可以扩展,但是不可修改


    二、抽象工厂模式

    举例:制造智能手机
    已知
            ①智能手机的基本组成操作系统和硬件
            ②二者条件兼顾才能实现量产
            ③二者不同的厂商并不知道下一个生产线具体要生产的设计
    解决措施
            写一个抽象类,约定某手机的基本组成

    1、抽象工厂(AbstractFactory)

    1. class MobilePhoneFactory {
    2. // 提供操作系统的接口
    3. createOS(){
    4. throw new Error("抽象工厂方法不允许直接调用,你需要将我重写!");
    5. }
    6. // 提供硬件的接口
    7. createHardWare(){
    8. throw new Error("抽象工厂方法不允许直接调用,你需要将我重写!");
    9. }
    10. }

    (1)以上类,除了约定手机流水线的通用能力之外,啥也不干。如果让它干点啥,比如 new 一个 MobilePhoneFactory 实例,并尝试调用它的实例方法,它将报错

    (2)在抽象工厂模式中,以上类就是食物链顶端最大的Boss

    2、具体工厂(ConcreteFactory)

    当明确了生产方案:抽象工厂不工作,具体工厂来工作
    举例:一个专门生产 Android 系统 + 高通硬件的手机(FakeStar)的生产线

    (1)定制一个具体工厂

    1. // 具体工厂继承自抽象工厂
    2. class FakeStarFactory extends MobilePhoneFactory {
    3. createOS() {
    4. // 调用AndroidOS()构造函数,提供安卓系统实例
    5. return new AndroidOS()
    6. }
    7. createHardWare() {
    8. // 调用QualcommHardWare()构造函数,提供高通硬件实例
    9. return new QualcommHardWare()
    10. }
    11. }

    ①两个构造函数:AndroidOS 和 QualcommHardWare,分别用于生成具体的操作系统和硬件实例像这种被用于 new 出具体对象的类,叫做具体产品类(ConcreteProduct)

    具体产品类往往不会孤立存在,不同的具体产品类往往有着共同的功能,比如安卓系统类和苹果系统类,它们都是操作系统,都有着可以操控手机硬件系统这样一个最基本的功能

    ③因此我们可以用一个抽象产品(AbstractProduct)类来声明这一类产品应该具有的基本功能

    (2)抽象产品类

    1. // 定义操作系统这类产品的抽象产品类
    2. class OS {
    3. controlHardWare() {
    4. throw new Error('抽象产品方法不允许直接调用,你需要将我重写!');
    5. }
    6. }
    7. // 定义具体操作系统的具体产品类
    8. class AndroidOS extends OS {
    9. controlHardWare() {
    10. console.log('我会用安卓的方式去操作硬件')
    11. }
    12. }
    13. class AppleOS extends OS {
    14. controlHardWare() {
    15. console.log('我会用🍎的方式去操作硬件')
    16. }
    17. }
    18. ...

    (3)硬件类产品

    1. // 定义手机硬件这类产品的抽象产品类
    2. class HardWare {
    3. // 手机硬件的共性方法,这里提取了“根据命令运转”这个共性
    4. operateByOrder() {
    5. throw new Error('抽象产品方法不允许直接调用,你需要将我重写!');
    6. }
    7. }
    8. // 定义具体硬件的具体产品类
    9. class QualcommHardWare extends HardWare {
    10. operateByOrder() {
    11. console.log('我会用高通的方式去运转')
    12. }
    13. }
    14. class MiWare extends HardWare {
    15. operateByOrder() {
    16. console.log('我会用小米的方式去运转')
    17. }
    18. }
    19. ...

    (4)生产一台FakeStar手机

    1. // 这是我的手机
    2. const myPhone = new FakeStarFactory()
    3. // 让它拥有操作系统
    4. const myOS = myPhone.createOS()
    5. // 让它拥有硬件
    6. const myHardWare = myPhone.createHardWare()
    7. // 启动操作系统(输出‘我会用安卓的方式去操作硬件’)
    8. myOS.controlHardWare()
    9. // 唤醒硬件(输出‘我会用高通的方式去运转’)
    10. myHardWare.operateByOrder()

    3、生产新款手机

    此时我们不需要对抽象工厂MobilePhoneFactory做任何修改,只需要拓展它的种类
    这样对原有的系统不会造成任何潜在影响,即“对拓展开放,对修改封闭”

    1. class newStarFactory extends MobilePhoneFactory {
    2. createOS() {
    3. // 操作系统实现代码
    4. }
    5. createHardWare() {
    6. // 硬件实现代码
    7. }
    8. }

    4、总结

    (1)抽象工厂和简单工厂有哪些异同?

    ①共同点:尝试去分离一个系统中变与不变的部分
    ②不同点:场景的复杂度

    简单工厂:处理容易抽离的类

        逻辑本身比较简单,故而不苛求代码可扩展性。

    抽象工厂:处理非常棘手、繁杂的类

        这些类中不仅能划分出门派,还能划分出等级,同时存在着千变万化的扩展可能性

        这使得我们必须对共性作更特别的处理、使用抽象类去降低扩展的成本,同时需要对类的性质作划分

    (2)四个关键角色

    • 抽象工厂(抽象类,不能被用于生成具体实例):  用于声明最终目标产品的共性。在一个系统里,抽象工厂可以有多个(大家可以想象我们的手机厂后来被一个更大的厂收购了,这个厂里除了手机抽象类,还有平板、游戏机抽象类等等),每一个抽象工厂对应的这一类的产品,被称为“产品族
    • 具体工厂(用于生成产品族里的一个具体的产品):  继承自抽象工厂、实现了抽象工厂里声明的那些方法,用于创建具体的产品的类
    • 抽象产品(抽象类,不能被用于生成具体实例):  上面我们看到,具体工厂里实现的接口,会依赖一些类,这些类对应到各种各样的具体的细粒度产品(比如操作系统、硬件等),这些具体产品类的共性各自抽离,便对应到了各自的抽象产品类
    • 具体产品(用于生成产品族里的一个具体的产品所依赖的更细粒度的产品):  比如我们上文中具体的一种操作系统、或具体的一种硬件等

    (3)学习注意点

    ①学会用 ES6 模拟 JAVA 中的抽象类

    ②了解抽象工厂模式中四个角色的定位与作用

    ③对“开放封闭原则”形成自己的理解,知道它好在哪,知道执行它的必要性

  • 相关阅读:
    循环(while do...while for)介绍
    【面试】对CSS预处理器的理解及与原生CSS的区别
    【C++】【Opencv】cv::GaussianBlur、cv::filter2D()函数详解和示例
    C3P Software 发布 Cast-Designer V7.7版本
    MHA高可用
    认识Vue中的路由
    使用LIMIT分页
    如何去图片水印?这些方法解决你的问题
    OpenHarmony 3.1 Beta版本关键特性解析——分布式DeviceProfile
    python经典百题之逐字写文件
  • 原文地址:https://blog.csdn.net/qq_51478745/article/details/134415727