【设计模式精讲】创建型模式之工厂方法模式(简单工厂、工厂方法)

文章目录

  • 第四章 创建型模式
    • 4.2 工厂方法模式
      • 4.2.1 需求: 模拟发放奖品业务
      • 4.2.2 原始开发方式
      • 4.2.3 简单工厂模式
        • 4.2.3.1 简单工厂模式介绍
        • 4.2.3.2 简单工厂原理
        • 4.2.3.3 简单工厂模式重构代码
        • 4.2.3.4 简单工厂模式总结
      • 4.2.4 工厂方法模式
        • 4.2.4.1 工厂方法模式介绍
        • 4.2.4.2 工厂方法模式原理
        • 4.2.4.3 工厂方法模式重构代码
        • 4.2.4.4 工厂方法模式总结

在这里插入图片描述
个人主页:道友老李
欢迎加入社区:道友老李的学习社区

第四章 创建型模式

4.2 工厂方法模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

  • 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

《设计模式》一书中,工厂模式被分为了三种:简单工厂、工厂方法和抽象工厂。(不过,在书中作者将简单工厂模式看作是工厂方法模式的一种特例。)

接下来我会介绍三种工厂模式的原理及使用

  • 简单工厂模式(不属于GOF的23种经典设计模式)
  • 工厂方法模式
  • 抽象工厂模式

4.2.1 需求: 模拟发放奖品业务

需求: 为了让我们的案例更加贴近实际开发, 这里我们来模拟一下互联网电商中促销拉新下的业务场景, 新用户注册立即参与抽奖活动 ,奖品的种类有: 打折券, 免费优酷会员,小礼品.

4.2.2 原始开发方式

不考虑设计原则,不使用设计模式的方式进行开发

在不考虑任何代码的可扩展性的前提下,只为了尽快满足需求.我们可以这样去设计这个业务的代码结构:

1) 实体类

名称描述
AwardInfo获奖信息对应实体类
DiscountInfo打折券信息对应实体类
YouKuMember优酷会员对应实体类
SmallGiftInfo小礼品信息对应实体类
DiscountResult打折券操作响应结果封装类
public class AwardInfo {private String uid; //用户唯一IDprivate Integer awardType; //奖品类型: 1 打折券 ,2 优酷会员,3 小礼品private String awardNumber; //奖品编号Map<String, String> extMap; //额外信息}public class DiscountInfo {//属性信息省略......
}public class YouKuMember {//属性信息省略......
}public class SmallGiftInfo {private String userName;              // 用户姓名private String userPhone;             // 用户手机private String orderId;               // 订单IDprivate String relAddress;            // 收货地址}public class DiscountResult {private String status; // 状态码private String message; // 信息
}

2) 服务层

名称功能描述
DiscountServiceDiscountResult sendDiscount(String uid,String number)模拟打折券服务
YouKuMemberServicevoid openMember(String bindMobile , String number)模拟赠送优酷会员服务
SmallGiftServiceBoolean giveSmallGift(SmallGiftInfo smallGiftInfo)模拟礼品服务
public class DiscountService {public DiscountResult sendDiscount(String uid, String number){System.out.println("向用户发放打折券一张: " + uid + " , " + number);return new DiscountResult("200","发放打折券成功");}
}public class YouKuMemberService {public void openMember(String bindMobile , String number){System.out.println("发放优酷会员: " + bindMobile + " , " + number);}
}public class SmallGiftService {public Boolean giveSmallGift(SmallGiftInfo smallGiftInfo){System.out.println("小礼品已发货,获奖用户注意查收! " + JSON.toJSON(smallGiftInfo));return true;}
}

3) 控制层

名称功能描述
DeliverControllerResponseResult awardToUser(AwardInfo awardInfo)按照类型的不同发放商品
奖品类型: 1 打折券 ,2 优酷会员,3 小礼品
public class DeliverController {/*** 按照类型的不同发放商品*     奖品类型: 1 打折券 ,2 优酷会员,3 小礼品*/public void awardToUser(AwardInfo awardInfo){if(awardInfo.getAwardType() == 1){ //打折券DiscountService discountService = new DiscountService();DiscountResult result = discountService.sendDiscount(awardInfo.getUid(), awardInfo.getAwardNumber());System.out.println("打折券发放成功!"+ JSON.toJSON(result));}else if(awardInfo.getAwardType() == 2){ //优酷会员//获取用户手机号String bindMobile = awardInfo.getExtMap().get("phone");//调用serviceYouKuMemberService youKuMemberService = new YouKuMemberService();youKuMemberService.openMember(bindMobile,awardInfo.getAwardNumber());System.out.println("优酷会员发放成功!");}else if(awardInfo.getAwardType() == 3){ /*小礼品封装收货用户信息*/SmallGiftInfo smallGiftInfo = new SmallGiftInfo();smallGiftInfo.setUserName(awardInfo.getExtMap().get("username"));smallGiftInfo.setOrderId(UUID.randomUUID().toString());smallGiftInfo.setRelAddress(awardInfo.getExtMap().get("adderss"));SmallGiftService smallGiftService = new SmallGiftService();Boolean isSuccess = smallGiftService.giveSmallGift(smallGiftInfo);System.out.println("小礼品发放成功!" + isSuccess);}}}

4) 测试

通过单元测试,来对上面的接口进行测试,验证代码质量.

public class TestApi01 {//测试发放奖品接口@Testpublic void test01(){DeliverController deliverController = new DeliverController();//1. 发放打折券优惠AwardInfo info1 = new AwardInfo();info1.setUid("1001");info1.setAwardType(1);info1.setAwardNumber("DEL12345");deliverController.awardToUser(info1);//2. 发放优酷会员AwardInfo info2 = new AwardInfo();info2.setUid("1002");info2.setAwardType(2);info2.setAwardNumber("DW12345");Map<String,String> map = new HashMap<>();map.put("phone","13512341234");info2.setExtMap(map);deliverController.awardToUser(info2);//2. 发放小礼品AwardInfo info3 = new AwardInfo();info3.setUid("1003");info3.setAwardType(3);info3.setAwardNumber("SM12345");Map<String,String> map2 = new HashMap<>();map2.put("username","大远");map2.put("phone","13512341234");map2.put("address","北京天安门");info3.setExtMap(map2);deliverController.awardToUser(info3);}
}

对于上面的实现方式,如果我们有想要添加的新的奖品时,势必要改动DeliverController的代码,违反开闭原则.而且如果有的抽奖接口出现问题,那么对其进行重构的成本会非常高.

除此之外代码中有一组if分支判断逻辑,现在看起来还可以,但是如果经历几次迭代和拓展,后续ifelse肯定还会增加.到时候接手这段代码的研发将会十分痛苦.

4.2.3 简单工厂模式

4.2.3.1 简单工厂模式介绍

简单工厂不是一种设计模式,反而比较像是一种编程习惯。简单工厂模式又叫做静态工厂方法模式(static Factory Method pattern),它是通过使用静态方法接收不同的参数来返回不同的实例对象.

实现方式:

​ 定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。

适用场景:
  (1)需要创建的对象较少。
  (2)客户端不关心对象的创建过程。

4.2.3.2 简单工厂原理

简单工厂包含如下角色:

  • 抽象产品 :定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品 :实现或者继承抽象产品的子类
  • 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。

在这里插入图片描述

4.2.3.3 简单工厂模式重构代码

1) service

/*** 免费商品发放接口**/
public interface IFreeGoods {ResponseResult sendFreeGoods(AwardInfo awardInfo);}
/*** 模拟打折券服务**/
public class DiscountFreeGoods implements IFreeGoods {@Overridepublic ResponseResult sendFreeGoods(AwardInfo awardInfo) {System.out.println("向用户发放一张打折券: " + awardInfo.getUid() + " , " + awardInfo.getAwardNumber());return new ResponseResult("200","打折券发放成功!");}
}/*** 小礼品发放服务**/
public class SmallGiftFreeGoods implements IFreeGoods {@Overridepublic ResponseResult sendFreeGoods(AwardInfo awardInfo) {SmallGiftInfo smallGiftInfo = new SmallGiftInfo();smallGiftInfo.setUserPhone(awardInfo.getExtMap().get("phone"));smallGiftInfo.setUserName(awardInfo.getExtMap().get("username"));smallGiftInfo.setAddress(awardInfo.getExtMap().get("address"));smallGiftInfo.setOrderId(UUID.randomUUID().toString());System.out.println("小礼品发放成,请注意查收: " + JSON.toJSON(smallGiftInfo));return new ResponseResult("200","小礼品发送成功",smallGiftInfo);}
}/*** 优酷 会员服务**/
public class YouKuMemberFreeGoods implements IFreeGoods {@Overridepublic ResponseResult sendFreeGoods(AwardInfo awardInfo) {String phone = awardInfo.getExtMap().get("phone");System.out.println("发放优酷会员成功,绑定手机号: " + phone);return new ResponseResult("200","优酷会员发放成功!");}
}

2) factory

/*** 具体工厂: 生成免费商品**/
public class FreeGoodsFactory {public static IFreeGoods getInstance(Integer awardType){IFreeGoods iFreeGoods = null;if(awardType == 1){  //打折券iFreeGoods = new DiscountFreeGoods();}else if(awardType == 2){ //优酷会员iFreeGoods = new YouKuMemberFreeGoods();}else if(awardType == 3){ //小礼品iFreeGoods = new SmallGiftFreeGoods();}return iFreeGoods;}
}

3)controller

public class DeliverController {//发放奖品public ResponseResult awardToUser(AwardInfo awardInfo){try {IFreeGoods freeGoods = FreeGoodsFactory.getInstance(awardInfo.getAwardTypes());ResponseResult responseResult = freeGoods.sendFreeGoods(awardInfo);return responseResult;} catch (Exception e) {e.printStackTrace();return new ResponseResult("201","奖品发放失败!");}}
}

4) 测试

通过单元测试,来对上面的接口进行测试,验证代码质量.

public class TestApi02 {DeliverController deliverController = new DeliverController();@Testpublic void test01(){//1. 发放打折券优惠AwardInfo info1 = new AwardInfo();info1.setUid("1001");info1.setAwardTypes(1);info1.setAwardNumber("DEL12345");ResponseResult result = deliverController.awardToUser(info1);System.out.println(result);}@Testpublic void test02(){//2. 发放优酷会员AwardInfo info2 = new AwardInfo();info2.setUid("1002");info2.setAwardTypes(2);info2.setAwardNumber("DW12345");Map<String,String> map = new HashMap<>();map.put("phone","13512341234");info2.setExtMap(map);ResponseResult result1 = deliverController.awardToUser(info2);System.out.println(result1);}@Testpublic void test03(){//3. 发放小礼品AwardInfo info3 = new AwardInfo();info3.setUid("1003");info3.setAwardTypes(3);info3.setAwardNumber("SM12345");Map<String,String> map2 = new HashMap<>();map2.put("username","大远");map2.put("phone","13512341234");map2.put("address","北京天安门");info3.setExtMap(map2);ResponseResult result2 = deliverController.awardToUser(info3);System.out.println(result2);}
}
4.2.3.4 简单工厂模式总结

优点:

封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。

缺点:

增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”。

4.2.4 工厂方法模式

4.2.4.1 工厂方法模式介绍

工厂方法模式 Factory Method pattern,属于创建型模式.

概念: 定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。

4.2.4.2 工厂方法模式原理

工厂方法模式的目的很简单,就是封装对象创建的过程,提升创建对象方法的可复用性

工厂方法模式的主要角色:

  • 抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
  • 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品:定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

我们直接来看看工厂方法模式的 UML 图:

在这里插入图片描述

4.2.4.3 工厂方法模式重构代码

为了提高代码扩展性,我们需要将简单工厂中的if分支逻辑去掉,通过增加抽象工厂(生产工厂的工厂)的方式,让具体工厂去进行实现,由具体工厂来决定实例化哪一个具体的产品对象.

抽象工厂

public interface FreeGoodsFactory {IFreeGoods getInstance();
}

具体工厂

public class DiscountFreeGoodsFactory implements FreeGoodsFactory {@Overridepublic IFreeGoods getInstance() {return new DiscountFreeGoods();}
}public class SmallGiftFreeGoodsFactory implements FreeGoodsFactory {@Overridepublic IFreeGoods getInstance() {return new SmallGiftFreeGoods();}
}

Controller

public class DeliverController {/*** 按照类型的不同发放商品*/public ResponseResult awardToUser(AwardInfo awardInfo){FreeGoodsFactory freeGoodsFactory = null;if(awardInfo.getAwardType() == 1){freeGoodsFactory = new DiscountFreeGoodsFactory();}else if(awardInfo.getAwardType() == 2){freeGoodsFactory = new SmallGiftFreeGoodsFactory();}IFreeGoods freeGoods = freeGoodsFactory.getInstance();System.out.println("=====工厂方法模式========");ResponseResult result = freeGoods.sendFreeGoods(awardInfo);return result;}}

从上面的代码实现来看,工厂类对象的创建逻辑又耦合进了 awardToUser() 方法中,跟我们最初的代码版本非常相似,引入工厂方法非但没有解决问题,反倒让设计变得更加复杂了。

那怎么 来解决这个问题呢?

我们可以为工厂类再创建一个简单工厂,也就是工厂的工厂,用来创建工厂类对象。

/*** 用简单方法模式实现: 工厂的工厂,作用是不需要每次创建新的工厂对象**/
public class FreeGoodsFactoryMap {private static final Map<Integer,FreeGoodsFactory> cachedFactories = new HashMap<>();static{cachedFactories.put(1, new DiscountFreeGoodsFactory());cachedFactories.put(2, new SmallGiftFreeGoodsFactory());}public static FreeGoodsFactory getParserFactory(Integer type){if(type == 1){FreeGoodsFactory freeGoodsFactory = cachedFactories.get(1);return freeGoodsFactory;}else if(type ==2){FreeGoodsFactory freeGoodsFactory = cachedFactories.get(2);return freeGoodsFactory;}return null;}
}

Controller

/*** 发放奖品接口**/
public class DeliverController {/*** 按照类型的不同发放商品*/public ResponseResult awardToUser(AwardInfo awardInfo){//根据类型获取工厂FreeGoodsFactory goodsFactory = FreeGoodsFactoryMap.getParserFactory(awardInfo.getAwardType());//从工厂中获取对应实例IFreeGoods freeGoods = goodsFactory.getInstance();System.out.println("=====工厂方法模式========");ResponseResult result = freeGoods.sendFreeGoods(awardInfo);return result;}
}

现在我们的代码已经基本上符合了开闭原则,当有新增的产品时,我们需要做的事情包括:

  1. 创建新的产品类,并且让该产品实现抽象产品接口
  2. 创建产品类对应的具体工厂,并让具体工厂实现抽象工厂
  3. 将新的具体工厂对象,添加到FreeGoodsFactoryMap的cachedFactories中即可,需要改动的代码改动的非常少.
4.2.4.4 工厂方法模式总结

工厂方法模优缺点

优点:

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;

缺点:

  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

什么时候使用工厂方法模式

  • 需要使用很多重复代码创建对象时,比如,DAO 层的数据对象、API 层的 VO 对象等。
  • 创建对象要访问外部信息或资源时,比如,读取数据库字段,获取访问授权 token 信息,配置文件等。
  • 创建需要统一管理生命周期的对象时,比如,会话信息、用户网页浏览轨迹对象等。
  • 创建池化对象时,比如,连接池对象、线程池对象、日志对象等。这些对象的特性是:有限、可重用,使用工厂方法模式可以有效节约资源。
  • 希望隐藏对象的真实类型时,比如,不希望使用者知道对象的真实构造函数参数等。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】指针(5)

前言&#xff1a;上篇文章的末尾我们使用了转移表来解决代码冗余的问题&#xff0c;那我们还有没有什么办法解决代码冗余呢&#xff1f;有的这就是接下来要说的回调函数。 往期文章: 指针1 指针2 指针3 指针4 文章目录 一&#xff0c;回调函数二&#xff0c;qsort实现快速排序1…

SpringBoot:SSL证书部署+SpringBoot实现HTTPS安全访问

一、前言 SSL协议介于TCP/IP协议栈的第四层&#xff08;传输层&#xff09;和第七层&#xff08;应用层&#xff09;之间&#xff0c;为基于TCP的应用层协议&#xff08;如HTTP&#xff09;提供安全连接。它通过在客户端和服务器之间建立一个加密的通道&#xff0c;确保数据在传…

嵌入式 lwip http server makefsdata

背景&#xff1a; 基于君正X2000 MCU Freertoslwip架构 实现HTTP server服务&#xff0c;MCU作为HTTP服务器通过网口进行数据包的传输&#xff0c;提供网页服务。其中设计到LWIP提供的工具makefsdata&#xff0c;常用于将文件或目录结构转换为适合嵌入到固件中的二进制格式。 …

论文笔记-WSDM2025-ColdLLM

论文笔记-WSDM2025-Large Language Model Simulator for Cold-Start Recommendation ColdLLM&#xff1a;用于冷启动推荐的大语言模型模拟器摘要1.引言2.前言3.方法3.1整体框架3.1.1行为模拟3.1.2嵌入优化 3.2耦合漏斗ColdLLM3.2.1过滤模拟3.2.2精炼模拟 3.3模拟器训练3.3.1LLM…

《DeepSeek-V3:人工智能大语言模型》

《DeepSeek-V3:人工智能大语言模型》 1. 引言 我们介绍了 DeepSeek-V3,这是一个强大的专家混合 (MoE) 语言模型,总共有 671B 个参数,每个令牌激活了 37B。 为了实现高效的推理和具有成本效益的训练,DeepSeek-V3 采用了多头潜在注意力 (MLA) 和 DeepSeekMoE 架构,这些…

手机控制电脑远程关机

远程看看软件兼容iOS和Android设备&#xff0c;该软件除了能通过电脑远程关闭另一台电脑外&#xff0c;您还可以通过它在手机上远程关闭公司的电脑。您可以按照以下步骤进行操作以实现电脑远程关机&#xff1a; 步骤1.在手机应用商店搜索“远程看看”进行软件安装&#xff0c;…

Aseprite绘画流程案例(1)——画相机图标

原图&#xff1a; 步骤一&#xff1a;打开需要参照的图标 步骤二&#xff1a;将参照的图片拖放到右边&#xff0c;作为参考 步骤三&#xff1a;新建24x24的画布&#xff0c;背景为白色的画布 步骤四&#xff1a;点击菜单栏——视图——显示——像素网格&#xff08;如果画布已经…

The Heliosphere 日球层

转自 The Heliosphere - NASA This is an artists concept of our Heliosphere as it travels through our galaxy with the major features labeled. Termination Shock: Blowing outward billions of kilometers from the Sun is the solar wind, a thin stream of electrica…

使用API有效率地管理Dynadot域名,为域名部署DNS安全拓展(DNSSEC)

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

vsan数据恢复—vsan缓存盘故障导致虚拟磁盘文件丢失的数据恢复案例

vsan数据恢复环境&故障&#xff1a; VMware vsan架构采用21模式。每台设备只有一个磁盘组&#xff08;71&#xff09;&#xff0c;缓存盘的大小为240GB&#xff0c;容量盘的大小为1.2TB。 由于其中一台主机&#xff08;0号组设备&#xff09;的缓存盘出现故障&#xff0c;导…

匹配算法:向下就近原则,向下没有就向上

匹配算法&#xff1a;向下就近原则&#xff0c;向下没有就向上 实现方式一实现方式二总结 实现方式一 private static List<Integer> findMatches(List<Integer> sourceList, List<Integer> searchValues) {List<Integer> sortedList sourceList.stre…

AI客服-接入deepseek大模型到微信(本地部署deepseek集成微信自动收发消息)

1.本地部署 1.1 ollama Ollama软件通过其高度优化的推理引擎和先进的内存管理机制&#xff0c;显著提升了大型语言模型在本地设备上的运行效率。其核心采用了量化技术&#xff08;Quantization&#xff09;以降低模型的计算复杂度和存储需求&#xff0c;同时结合张量并行计算&…

Python VsCode DeepSeek接入

Python VsCode DeepSeek接入 创建API key 首先进入DeepSeek官网&#xff0c;https://www.deepseek.com/ 点击左侧“API Keys”&#xff0c;创建API key&#xff0c;输出名称为“AI” 点击“创建"&#xff0c;将API key保存&#xff0c;复制在其它地方。 在VsCode中下载…

【python】网页批量转PDF

安装wkhtmltopdf 网站&#xff1a;wkhtmltopdf wkhtmltopdf http://www.baidu.com/ D:website1.pdf 安装pdfkit库 pip install pdfkit 批量转换代码 import os import pdfkit path_wkthmltopdf rE:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe config pdfkit.configu…

架构师面试(三):订阅模型

问题 对【注册中心】【配置中心】【消息队列】和【IM】进行分析和抽象&#xff0c;可归纳出一个完整的业务模型单元&#xff0c;即【订阅系统】&#xff0c;下面关于实现订阅系统的几种模型的相关描述中&#xff0c;说法正确的有哪几项&#xff1f; A. 信箱模型&#xff0c;即…

数据结构:算法的时间复杂度和空间复杂度

1.算法效率 1.1 如何衡量一个算法的好坏 如何衡量一个算法的好坏呢&#xff1f; 比如对于以下斐波那契数列&#xff1a; long long Fib(int N) {if(N < 3)return 1;return Fib(N-1) Fib(N-2); }斐波那契数列的递归实现方式非常简洁&#xff0c;但简洁一定好吗&#xff…

linux下pip下载项目失败

想下载CLIP的项目复现代码的时候&#xff0c;出现问题如下&#xff1a; 于是手动使用 Git 克隆仓库&#xff0c; git clone https://github.com/openai/CLIP.git cd CLIP pip install .ls查看文件如下&#xff1a;(手动克隆git项目成功)

Redis文档总结

文档&#xff1a;https://redis.com.cn/topics/why-use-redis.html 1.我们为什么一定要用 Redis 呢&#xff1f; 速度快&#xff0c;完全基于内存&#xff0c;使用 C 语言实现&#xff0c;网络层使用 epoll 解决高并发问题&#xff0c;单线程模型避免了不必要的上下文切换及竞争…

【前端框架】Vue3 面试题深度解析

本文详细讲解了VUE3相关的面试题&#xff0c;从基础到进阶到高级&#xff0c;分别都有涉及&#xff0c;希望对你有所帮助&#xff01; 基础题目 1. 简述 Vue3 与 Vue2 相比有哪些主要变化&#xff1f; 答案&#xff1a; 响应式系统&#xff1a;Vue2 使用 Object.definePrope…

Django+Vue3全栈开发实战:从零搭建博客系统

文章目录 1. 开发环境准备2. 创建Django项目与配置3. 设计数据模型与API4. 使用DRF创建RESTful API5. 创建Vue3项目与配置6. 前端页面开发与组件设计7. 前后端交互与Axios集成8. 项目优化与调试9. 部署上线10. 总结与扩展10.1 项目总结10.1.1 技术栈回顾10.1.2 项目亮点 10.2 扩…