策略者模式(代码实践C++/Java/Python)————设计模式学习笔记

news2025/6/7 18:07:16

文章目录

  • 1 设计目标
  • 2 Java
    • 2.1 涉及知识点
    • 2.2 实现
      • 2.2.1 实现两个接口飞行为和叫行为
      • 2.2.2 实现Duck抽象基类(把行为接口作为类成员)
      • 2.2.3 实现接口飞行为和叫行为的具体行为
      • 2.2.4 具体实现鸭子
      • 2.2.5 模型调用
  • 3 C++(用到了大量C++2.0的知识)
    • 3.1 涉及知识点
    • 3.2 实现
      • 3.2.1 实现飞行为和叫行为接口
      • 3.2.2 实现Duck基类(使用委托/组合,把指向抽象接口类的指针作为类成员)
      • 3.2.3 实现接口类的飞行为和叫行为
      • 3.2.4 实现具体的鸭子行为
      • 3.2.5 具体调用
  • 4 Python实现
    • 4.1 涉及知识点
    • 4.2 实现代码
      • 4.2.1 实现两个接口飞行为和叫行为
      • 4.2.2 实现Duck抽象基类(把行为接口作为类成员)
      • 4.2.3 实现接口飞行为和叫行为的具体行为
      • 4.2.4 具体实现鸭子
      • 4.2.5 模型调用
  • 5 完整代码
  • 6 其他知识阅读(快速入门)

1 设计目标

此篇为实现篇下,如果对策略者模式不熟,可以看知识点篇上。
在这里插入图片描述
实现要求:鸭子共有三种行为,游泳行为(所有鸭子都会),飞行行为(能飞/不能飞/具有火箭动力的飞行),叫声行为(嘎嘎叫/吱吱叫/什么都不会叫),不同具体鸭子(绿头鸭/模型鸭/…)飞行行为和叫声行为可能不一样。

2 Java

2.1 涉及知识点

  • 接口(interface):定义一种方法约束
  • 继承(extend):子类会具有父类的一般特性也会具有自身的特性,提高代码复用性。

区别:

修饰符不同:接口使用interface修饰,继承使用extends修饰。
多继承方式不同:接口支持多继承,继承只支持单继承。
定义方式不同:接口只能定义全局常量和抽象方法,继承可以定义属性、方法、变量、常量等。
作用不同:接口是一种约束,类实现接口就一定要实现它所有的方法;继承是一种扩展,继承了类,它的私有成员以外的成员变量和成员方法子类都将拥有。
  • 组合(委托):把A类作为B类的成员变量,具体实现在A类中,B类对外暴露调用接口,解耦合。
  • 抽象基类:不能实例化,只能作为类模版,子类需要实现起抽象方法。
  • 构造函数:类的初始化方法。

2.2 实现

2.2.1 实现两个接口飞行为和叫行为

public interface FlyBehavior {
    public void fly();
}

public interface QuackBehavior {
    public void quack();
}

2.2.2 实现Duck抽象基类(把行为接口作为类成员)

package com.jiangxue.strategy;

public abstract class Duck {
    //组合(委托):策略类作为抽象基类的成员变量
    QuackBehavior quackBehavior;
    FlyBehavior flyBehavior;
    //定义抽象方法:子类必须要实现
    public abstract void display();
    //调用类成员的方法
    public void performQuack(){
        quackBehavior.quack();;
    }
    public void performFly(){
        flyBehavior.fly();
    }
    //所有子类都有的共有行为
    public void swim(){
        System.out.println("All ducks float, even decoys");
    }
    //setter方法设置鸭子行为(运行时改变行为)
    public void setFlyBehavior(FlyBehavior fb){
        flyBehavior = fb;
    }

    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
}

2.2.3 实现接口飞行为和叫行为的具体行为

  • 具体实现飞行为接口:
public class FlyWithWings implements FlyBehavior{
    @Override
    public void fly(){
        System.out.println("I'm flying");
    }
}

public class FlyNoWay implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("I can't fly");
    }
}

public class FlyRocketPowered implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("I'm fly with rocket!");
    }
}
  • 具体实现叫行为接口:
public class Quack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Quack");
    }
}

public class MuteQuack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("<<Silence>>");
    }
}

public class Squeak implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Squack");
    }
}

2.2.4 具体实现鸭子

  • 实现绿头鸭
public class MallardDuck extends Duck{
    //重新构造函数
    public MallardDuck(){
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }
    public void display(){
        System.out.println("I'm a real Mallard duck");
    }
}

  • 实现模型鸭:
public class ModelDuck extends Duck{
    public ModelDuck(){
        flyBehavior = new FlyNoWay();
        quackBehavior = new Quack();
    }

    @Override
    public void display() {
        System.out.println("I'm a model duck");
    }
}

2.2.5 模型调用

public class Test {

    public static void main(String[] args) {
        //示例1
        Duck mallardDuck = new MallardDuck();
        mallardDuck.performQuack();
        mallardDuck.performFly();
        //示例2
        Duck model = new ModelDuck();
        model.performFly();
        //改变飞行行为
        model.setFlyBehavior(new FlyRocketPowered());
        model.performFly();

;    }
}

3 C++(用到了大量C++2.0的知识)

3.1 涉及知识点

  • 纯虚函数(用于实现接口)【virtua和= 0】:在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。有纯虚函数的类是抽象类,不能生成对象,只能派生。
  • virtual析构函数:当父类指针指向子类对象时,执行释放操作,子类对象也会被释放掉。
  • explicit:该构造函数只能显式调用,禁止隐式转换。
  • &&(右值引用):结合了移动语义和完美转发;可以绑定到临时对象。
    • 移动语义:不复制对象,而只是让新的对象名指向原对象名所指对象,并且将原对象所指的置空。
    • 完美转发:可以撰写接受任意参数的函数模版,并将其转发到其他函数,目标函数会接受与其转发函数所接受的完全相同的参数。
  • std::move(把实参强制转换为右值):无条件地右值类型的强制类型转换;
  • std::forward:仅对绑定到右值的引用实施向右值类型的强制转换。
    • 针对右值引用实施std::move,万能引用实施std::forward
  • 智能指针unique_ptr:独占对象,不允许复制;动态管理分配对象的生命周期。
  • make_unique函数:动态分配指定类型的内存,并返回一个指向分配内存的唯一指针。
  • 子类继承父类的构造:不能直接从初始化列表初始化基类成员,应该使用父类的构造函数。
  • 公有继承:基类的公有成员和保护成员的访问属性在派生类中不变

3.2 实现

3.2.1 实现飞行为和叫行为接口

class QuackBehavior{
public:
    //纯虚函数只有函数的名字而不具备函数的功能,不能被调用,要求任何派生类都要定义自己的实现方法
    //有纯虚函数的类是抽象类,不能生成对象,只能派生。
    virtual void quack() const = 0;
    //virtual析构函数好处:当父类指针指向子类对象时,执行释放操作,子类对象也会被释放掉
    virtual ~QuackBehavior() =default;
};

class FlyBehavior{
public:
    virtual void fly() const = 0;
    virtual ~FlyBehavior() = default;
};

3.2.2 实现Duck基类(使用委托/组合,把指向抽象接口类的指针作为类成员)

#include <memory>
#include "FlyBehavior.h"
#include "QuackBehavior.h"
#include <iostream>

class Duck {
protected:
    //智能指针unique_ptr:独占对象,不允许复制;动态管理分配对象的生命周期
    std::unique_ptr<FlyBehavior> _flyBehavior;
    std::unique_ptr<QuackBehavior> _quackBehavior;
public:
    //explicit表示该构造函数只能显式调用,禁止隐式转换。
    /*
     * 移动语义:不复制对象,而只是让新的对象名指向原对象名所指对象,并且将原对象所指的置空。
     * 完美转发:可以撰写接受任意参数的函数模版,并将其转发到其他函数,目标函数会接受与其转发函数所接受的完全相同的参数。
     * &&(右值引用):结合了移动语义和完美转发;可以绑定到临时对象。
     * std::move(把实参强制转换为右值):无条件地右值类型的强制类型转换;
     * std::forward:仅对绑定到右值的引用实施向右值类型的强制转换。
     * 针对右值引用实施std::move,万能引用实施std::forward
    */
    explicit Duck(std::unique_ptr<FlyBehavior> &&flyBehavior ={},
                  std::unique_ptr<QuackBehavior> &&quackBehavior={})
                  :_flyBehavior(std::move(flyBehavior))
                  ,_quackBehavior(std::move(quackBehavior)){

    }
    //上下文允许在运行时替换策略对象。
    void setFlyBehavior(std::unique_ptr<FlyBehavior>&&flyBehavior){
        _flyBehavior = std::move(flyBehavior);
    }

    void setQuackBehavior(std::unique_ptr<QuackBehavior>&&quackBehavior){
        _quackBehavior = std::move(quackBehavior);
    }
    //执行飞
    void performFly() const{
        _flyBehavior->fly();
    }
    //执行叫
    void performQuack() const{
        _quackBehavior->quack();
    }
    void swim() const{
        std::cout<<"All ducks float, even decoys"<<std::endl;
    }

    virtual void display() const = 0;

};

3.2.3 实现接口类的飞行为和叫行为

  • 实现飞行为:
#include <iostream>
#include "FlyBehavior.h"

//公有继承:基类的公有成员和保护成员的访问属性在派生类中不变
class FlyWithWings: public FlyBehavior{
public:
    void fly() const override{
        std::cout<<"I'm flying"<<std::endl;
    }
};

class FlyNoWay: public FlyBehavior{
public:
    void fly() const override{
        std::cout<<"I can't fly"<<std::endl;
    }
};

class FlyRocketPowered : public FlyBehavior{
public:
    void fly() const override{
        std::cout<<"I'm fly with rocket!"<<std::endl;
    }
};


  • 实现叫行为:
#include "QuackBehavior.h"
#include <iostream>

class Quack: public QuackBehavior{
    void quack() const override{
        std::cout<<"quack"<<std::endl;
    }
};

class MuteQuack : public QuackBehavior{
public:
    void quack() const override{
        std::cout<<"<<Silence>>"<<std::endl;
    }
};

class Squeak: public QuackBehavior{
    void quack() const override{
        std::cout<<"Squack"<<std::endl;
    }
};

3.2.4 实现具体的鸭子行为

  • 绿头鸭
#include "Duck.h"
#include "Quack.h"
#include "FlyWithWings.h"
#include <iostream>

class MallardDuck : public Duck{
public:
    //子类继承父类的构造
    //不能直接从初始化列表初始化基类成员,应该使用父类的构造函数
    explicit MallardDuck(std::unique_ptr<FlyWithWings>&& flyWithWings ={},
                         std::unique_ptr<Quack>&& quack={})
                         : Duck(std::move(flyWithWings), std::move(quack)){

    }
    //虚函数方法重写
    void display() const override{
        std::cout<<"I'm a real Mallard duck"<<std::endl;
    }

};
  • 模型鸭
#include "Duck.h"
#include "FlyNoWay.h"
#include "Quack.h"


class ModelDuck :public Duck{
public:
    explicit ModelDuck(std::unique_ptr<FlyNoWay>&& flyNoWay,
                       std::unique_ptr<Quack>&& quack)
                       : Duck(std::move(flyNoWay), std::move(quack)){

    }
    void display() const override{
        std::cout<<"I'm a model duck"<<std::endl;
    }

};

3.2.5 具体调用

#include "MallardDuck.h"
#include "ModelDuck.h"
#include "FlyRocketPowered.h"

void testCode() {
    //make_unique函数:动态分配指定类型的内存,并返回一个指向分配内存的唯一指针
    MallardDuck mallardDuck(std::make_unique<FlyWithWings>(),
            std::make_unique<Quack>());
    mallardDuck.performQuack();
    mallardDuck.performFly();

    ModelDuck modelDuck(std::make_unique<FlyNoWay>(),
            std::make_unique<Quack>());
    modelDuck.performFly();
    modelDuck.setFlyBehavior(std::make_unique<FlyRocketPowered>());
    modelDuck.performFly();


}

int main() {
    testCode();
    return 0;
}

4 Python实现

4.1 涉及知识点

  • 抽象基类(继承ABC):不能被实例化,只能被继承。
  • 抽象方法(@abstractmethod):继承的子类必须实现的方法。
  • 属性(@property,@flyBehavior.setter):调用时不需要加(),为的是提供更加友好访问类数据的方式。
  • 构造函数(def __init__):初始化类成员变量。
  • 继承(super().__init__):继承父类的属性。
  • from __future__ import annotations:允许你在程序中声明变量或函数的类型,并由编译器或其他工具来检查代码的类型是否正确。有助于提高代码的可读性,并且有助于发现类型错误。

4.2 实现代码

4.2.1 实现两个接口飞行为和叫行为

from abc import ABC, abstractmethod

# 抽象基类
class FlyBehavior(ABC):
    # 抽象方法
    @abstractmethod
    def fly(self):
        pass

class QuackBehavior(ABC):
    @abstractmethod
    def quack(self):
        pass

4.2.2 实现Duck抽象基类(把行为接口作为类成员)

class Duck(ABC):
    def __init__(self, flyBehavior: FlyBehavior, quackBehavior: QuackBehavior) -> None:
        self._flyBehavior = flyBehavior
        self._quackBehavior = quackBehavior

    @abstractmethod
    def perform(self) -> None:
        pass

    def performFly(self) -> None:
        return self._flyBehavior.fly()

    def performQuack(self) -> None:
        return self._quackBehavior.quack()

    @property
    def flyBehavior(self) -> FlyBehavior:
        return self._flyBehavior

    @property
    def quackBehavior(self) -> QuackBehavior:
        return self._quackBehavior

    @flyBehavior.setter
    def flyBehavior(self, fly: FlyBehavior) -> None:
        self._flyBehavior = fly

    @quackBehavior.setter
    def quackBehavior(self, quack: QuackBehavior) -> None:
        self._quackBehavior = quack

    def swim(self) -> None:
        print("All ducks float, even decoys")

4.2.3 实现接口飞行为和叫行为的具体行为

  • 具体实现飞行为接口:
class FlyWithWings(FlyBehavior):
    def fly(self) -> None:
        print("I'm flying")

class FlyNoWay(FlyBehavior):
    def fly(self) -> None:
        print("I can't fly")

class FlyRocketPowered(FlyBehavior):
    def fly(self) -> None:
        print("I'm fly with rocket!")
  • 具体实现叫行为接口:
class Quack(QuackBehavior):
    def quack(self) -> None:
        print("Quack")

class Square(QuackBehavior):
    def quack(self) -> None:
        print("Squack")

class MuteQuack(QuackBehavior):
    def quack(self) -> None:
        print("<<Silence>>")

4.2.4 具体实现鸭子

  • 实现绿头鸭
class ModelDuck(Duck):
    def __init__(self, flyBehavior: FlyNoWay, quackBehavior: Quack) -> None:
        super().__init__(flyBehavior, quackBehavior)
        # 下面的初始化方法,并不能继承父类的属性
        # _flyBehavior = flyBehavior
        # _quackBehavior = quackBehavior

    def perform(self) -> None:
        print("I'm a model duck")

  • 实现模型鸭:
class MallardDuck(Duck):
    def __int__(self, flyBehavior: FlyWithWings, quackBehavior: Quack) -> None:
        super().__init__(flyBehavior, quackBehavior)

    def perform(self) -> None:
        print("I'm a real Mallard duck")

4.2.5 模型调用

# import sys , os
# base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# sys.path.append(base_dir)
# 没有把当前项目加入到PYTHONPATH环境变量

from Strategy.duck import *

if __name__ == "__main__":
    mallardDuck = MallardDuck(FlyWithWings(), Quack())
    mallardDuck.performQuack()
    mallardDuck.performFly()

    modelDuck = ModelDuck(FlyNoWay(), Quack())
    modelDuck.performFly()
    modelDuck.flyBehavior = FlyRocketPowered()
    modelDuck.performFly()

5 完整代码

完整的实现代码,见Gitee仓库。如果对您有用的话,欢迎留下star,谢谢。

6 其他知识阅读(快速入门)

Java快速入门
Python快速入门
深入了解C++2.0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1592767.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言-详解内存函数

文章目录 1.memcpy使用和模拟实现1.1 memcpy函数的使用规则1.2 memcpy函数的使用1.2 模拟实现memcpy函数 2.memmove 函数的使用和模拟实现2.1 memmove 函数使用规则2.2 memmove函数的使用2.3 模拟实现memmove函数2.3.1 从后往前移2.3.2 从前往后移 2.4 算法实现2.4.1 从前往后移…

C# 图形化的导航界面的设计方法

目录 一、涉及到的知识点 1、BackColor属性 2、FlatStyle属性 3、TextlmageRelation属性 4、其它共性设计 二、设计实例 1、 Resources.Designer.cs 2、Form1.Designer.cs 3、Form1.cs 4、运行结果 图形化导航用于代替文字导航&#xff0c;比如对Button控件 进行图形…

NzN的数据结构--归并排序及计数排序

篇接上文&#xff0c;今天要学习的是归并排序以及非比较排序--计数排序。这么励志的日更博主&#xff0c;你怎么能不三连一下呢&#xff1f; 目录 一、归并排序 1. 递归实现 2. 非递归实现 3. 特性总结 二、非比较排序--计数排序 三、排序算法复杂度及稳定性分析 一、归并…

vue3+element plus图片预览点击按钮直接显示图片的预览形式

1 需求 直接上需求&#xff1a; 我想要直接点击下面这个“预览”按钮&#xff0c;然后呈现出预览图片的形式 ok&#xff0c;需求知道了&#xff0c;下面让我们来看看如何实现吧 ~ 2 实现 template部分 <el-buttontype"primary"size"small"click&qu…

DRF多表关联的序列化和反序列化

DRF多表关联的序列化和反序列化 目录 DRF多表关联的序列化和反序列化序列化定制字段source一对多的序列化 多表关联的序列化方式1&#xff1a;在表模型中定义方法方式2&#xff1a;定制返回格式SerializerMethodField方式3&#xff1a;子序列化 多表关联的反序列化反序列化保存…

Ubuntu 上配置静态IP地址

Ubuntu 上配置静态IP地址编辑网络配置文件配置静态IP地址应用配置更改 Ubuntu 上配置静态IP地址 在终端中&#xff0c;运行以下命令来编辑网络配置文件 编辑网络配置文件 sudo cat /etc/netplan/01-netcfg.yaml在编辑器中&#xff0c;找到用于您的网络接口的配置部分。例如…

使用阿里云试用Elasticsearch学习:创建仪表板pivot、搜索discover和仪表板dashboard

文档&#xff1a;https://www.elastic.co/guide/en/elasticsearch/reference/current/transform-examples.html#example-clientips 在kibana左栏打开Transforms&#xff0c;并创建Transforms&#xff08;转换&#xff09; Management > Stack Management > Data > T…

【Qt】界面优化

目录 一、QSS 1.1 基本语法 1.2 QSS设置方法 1.2.1 指定控件样式设置 1.2.2 全局样式设置 1.2.3 从文件加载样式表 1.2.4 使用Qt Designer编辑样式 1.3 选择器 1.3.1 介绍 1.3.2 子控件选择器 1.3.3 伪类选择器 1.4 样式属性(盒模型) 1.5 代码示例(登录界面) 二、…

自动化测试之httprunner框架hook函数实操

本篇介绍httprunner中hook函数的使用&#xff0c;以及通过编程能力实现建设自动化测试更全面的场景覆盖 前置&#xff1a; 互联网时代让我们更快的学习到什么是Httprunner 正文&#xff1a; 经过上文了解到这个框架怎么使用之后&#xff0c;我们开始来探讨一下我们为什么要用…

SecureCRT通过USB-Servial ch340串口无法连接单片机

通过USB To TTL连线 STM32F103-PRO&#xff0c;烧制程序到单片机上&#xff0c;通过SecureCRT通过USB-Servial ch340串口无法链接RS232升USB转TTL连接正确 开发板连接正确 问题&#xff1a;SecureCRT串口连接没有反应 问题分析&#xff1a;1、检查ch340串口驱动 查看设备管…

海洋信息管理系统:守护蓝色星球,促进海洋经济新发展

海洋&#xff0c;覆盖地球表面超过七成的广阔水域&#xff0c;是生命之源&#xff0c;也是经济发展的重要空间。然而&#xff0c;随着人类活动的增加&#xff0c;海洋生态环境面临严峻挑战&#xff0c;海洋资源的可持续利用成为全球关注的焦点。在这样的背景下&#xff0c;构建…

openssl 如何从pfx格式证书 获取证书序列号信息

已知&#xff1a;一个个人证书文件 test.pfx 求&#xff1a;如何通过openssl查看其对应证书的序列号信息&#xff1f; 踩坑之&#xff1a;unable to load certificate! openssl x509 -in xxx.cert -noout -serial 命令可查看证书序列号&#xff0c;但是这个-in 的输入必须是私…

一步一步学习使用 MediaSource 实现动态媒体流

学习前的参考 为什么视频网站的视频链接地址是blob&#xff1f; - 掘金 MediaSource - Web API 接口参考 | MDN 在示例中前往下载源代码&#xff1a; netfix/demo/bufferWhenNeeded.html at gh-pages nickdesaulniers/netfix GitHub 下载 demo 目录&#xff0c;对 bufferW…

量子信息产业生态研究(一):关于《量子技术公司营销指南(2023)》的讨论

写在前面。量子行业媒体量子内参&#xff08;Quantum Insider&#xff09;编制的《量子技术公司营销指南》是一本实用的英文手册&#xff0c;它旨在帮助量子科技公司建立有效的营销策略&#xff0c;同时了解如何将自己定位成各自的行业专家。本文对这篇指南的主要内容进行了翻译…

C语言中的编译和链接

系列文章目录 文章目录 ​编辑 系列文章目录 文章目录 前言 一、 翻译环境和运行环境 二、 翻译环境 2.1 编译 2.1.1 预处理 2.1.2 编译 2.1.2.1 词法分析 : 2.1.2.2 语法分析 2.1.2.3 语义分析 2.1.3 汇编 2.2 链接 三、运行环境 前言 在我们平常的写代码时&#xff0c;我们很…

set 类 和 map 类

1. 关联式容器 关联式容器也是用来存储数据的&#xff0c;与序列式容器不同的是&#xff0c;其里面存储的是<key, value>结构的 键值对&#xff0c;在数据检索时比序列式容器效率更高 2. 键值对 用来表示具有一一对应关系的一种结构&#xff0c;该结构中一般只包含…

你的系统是如何跟MySQL打交道的

1、Java 工程师眼中的数据库是什么东西? 从今天开始&#xff0c;我们将要开始一个MySQL的专栏&#xff0c;一起来研究MySQL数据库的底层原理和各种实践案例&#xff0c;以及互联网公司的技术方案。 现在我们先来看看&#xff0c;在一个Java工程师眼中的数据库是什么东西? 平时…

开源 Ruo-Yi 项目引入 Mybatis-Plus:3.5.3 报错ClassNotFoundException:

开源 Ruo-Yi 项目引入 Mybatis-Plus:3.5.3 报错ClassNotFoundException&#xff1a; Caused by: java.lang.ClassNotFoundException: com.baomidou.mybatisplus.extension.plugins.MybatisPlusInter1 分析问题 控制台报错说明我们引入的 mybatis-plus 的依赖里找不到com.baom…

怎么恢复删除的回收站数据?分享多种恢复方法

在日常使用电脑的过程中&#xff0c;回收站是我们经常打交道的一个功能。它帮助我们管理不再需要的文件&#xff0c;但有时候&#xff0c;我们可能会不小心删除了重要文件&#xff0c;或者误清空了回收站。那么&#xff0c;面对这种情况&#xff0c;我们该如何恢复删除的回收站…

小程序面试题之性能优化提高10道

1.你使用过哪些方法&#xff0c;来提高微信小程序的应用速度&#xff1f; 提高页面加载速度 用户行为预测 减少默认data的大小 组件化方案 控制包的大小 压缩代码&#xff0c;清理无用代码 采用分包策略 启用本地缓存 参考地址&#xff1a;https://blog.csdn.net/wu_xianqiang/…