【利用AI让知识体系化】7种结构型模式

在这里插入图片描述

文章目录

  • 结构型模式
    • 简介
    • 适配器模式
    • 装饰器模式
    • 代理模式
    • 外观模式
    • 桥接模式
    • 组合模式
    • 享元模式

结构型模式

简介

在设计模式中,结构型模式用于描述如何将对象和类组装成较大的结构,并灵活地处理对象之间的关系。

结构型模式包括以下几种:

  1. 适配器模式:用于连接不兼容的接口,让它们能够一起工作。
  2. 装饰器模式:动态地给对象添加额外的职责。
  3. 代理模式:为其他对象提供一种代理以控制对这个对象的访问。
  4. 外观模式:为复杂系统提供简化的接口,让客户端能够更容易地使用系统。
  5. 桥接模式:将抽象和实现分离开来,使得它们可以独立地变化。
  6. 组合模式:将对象组合成树形结构以表示“整体-部分”关系,客户端可以像操作单个对象一样来操作组合对象。
  7. 享元模式:共享对象,以支持大量的细粒度对象的复用。

这些结构型模式都有助于提高系统的灵活性、可扩展性和可维护性。例如,适配器模式可以将不兼容的接口转换为兼容的接口,解决实际开发中对象之间接口不兼容的问题;装饰器模式可以动态地添加更多职责,而无需改变对象本身的代码;代理模式可以控制对对象的访问,从而实现访问权限控制等功能。

尽管结构型模式中的每个模式都是独立的,但它们也常常被组合使用。例如,装饰器模式的实现中常常会用到适配器模式,而桥接模式的实现也常常会包含组合模式的思想。熟悉结构型模式可以帮助开发者更好地理解一些经典的开源框架,并且在实际项目中设计和实现更好的软件架构。

适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的对象之间进行合作。适配器作为两个不兼容的对象之间的转换器,将一个对象的接口,转换成另一个对象需要的接口。通过适配器模式,我们可以将客户端代码与不同的对象解耦,从而提高了代码的复用性和灵活性。

一个简单的适配器模式的例子是:我们有一个圆孔和一个圆钉,但是我们需要将这个圆钉放进一个方孔里。我们可以使用一个方形适配器,将圆钉适配成方钉,使得它能够顺利地放进方孔中。

下面是使用 JavaScript 实现的简单的适配器模式的示例:

// 需要适配的类
class RoundPeg {
  constructor(radius) {
    this.radius = radius;
  }
  
  getRadius() {
    return this.radius;
  }
}

// 目标类
class SquareHole {
  constructor(width) {
    this.width = width;
  }
  
  getWidth() {
    return this.width;
  }
  
  fits(peg) {
    return this.getWidth() >= peg.getRadius() * Math.sqrt(2);
  }
}

// 适配器类
class SquarePegAdapter {
  constructor(peg) {
    this.peg = peg;
  }
  
  getWidth() {
    return this.peg.getRadius() * Math.sqrt(2);
  }
}

// 客户端代码
const roundPeg = new RoundPeg(5);
const squareHole = new SquareHole(10);

if(squareHole.fits(roundPeg)) {
  console.log('The round peg fits into the square hole!');
} else {
  const squarePegAdapter = new SquarePegAdapter(roundPeg);
  if(squareHole.fits(squarePegAdapter)) {
    console.log('The round peg fits into the square hole!');
  } else {
    console.log('The round peg does not fit into the square hole!');
  }
}

在这个示例中,我们定义了一个需要适配的圆钉类 RoundPeg 和一个目标方孔类 SquareHole。然后我们实现了一个适配器 SquarePegAdapter,将圆钉适配成一个方形钉。在客户端代码中,我们先试图将圆钉放进方孔中。如果适配成功则输出 “The round peg fits into the square hole!”,否则我们使用 SquarePegAdapter 来适配圆钉,然后再试图将适配后的方钉放进方孔中。如果适配成功则输出 “The round peg fits into the square hole!”,否则输出 “The round peg does not fit into the square hole!”。

装饰器模式

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许以动态的方式扩展对象的功能,同时还能保证不破坏对象原有的结构和功能。该模式使用方便的包装对象机制,就可以在运行时动态地添加、删除或更改对象的职责。

一个简单的装饰器模式的例子是:我们有一个餐厅,它提供各种餐点。我们可以为这些餐点添加各种配料,比如加入奶油、火腿等。这些配料不仅可以添加,还可以随时删除或更改。这就是装饰器模式的核心思想,它允许在运行时为对象添加功能,而不是在编译时。

下面是使用 JavaScript 实现的简单的装饰器模式的示例:

// 餐点类
class Meal {
  constructor() {
    this.price = 0;
  }
  
  getPrice() {
    return this.price;
  }
  
  setPrice(price) {
    this.price = price;
  }
  
  getDescription() {
    return '';
  }
}

// 配料装饰器类
class MealDecorator extends Meal {
  constructor(meal) {
    super();
    this.meal = meal;
  }
  
  getPrice() {
    return this.meal.getPrice() + this.price;
  }
  
  getDescription() {
    return this.meal.getDescription() + this.description;
  }
}

// 具体的餐点类
class Hamburger extends Meal {
  constructor() {
    super();
    this.setPrice(10);
    this.setDescription('Hamburger');
  }
}

class Pizza extends Meal {
  constructor() {
    super();
    this.setPrice(20);
    this.setDescription('Pizza');
  }
}

// 具体的配料装饰器类
class Cheese extends MealDecorator {
  constructor(meal) {
    super(meal);
    this.setPrice(5);
    this.description = ' + Cheese';
  }
}

class Bacon extends MealDecorator {
  constructor(meal) {
    super(meal);
    this.setPrice(8);
    this.description = ' + Bacon';
  }
}

// 客户端代码
let meal = new Hamburger();
console.log(meal.getDescription() + ' ' + meal.getPrice());

meal = new Cheese(meal);
console.log(meal.getDescription() + ' ' + meal.getPrice());

meal = new Bacon(meal);
console.log(meal.getDescription() + ' ' + meal.getPrice());

在这个示例中,我们定义了一个基础的餐点类 Meal 和一个装饰器类 MealDecorator。然后我们又定义了两个具体的餐点类 HamburgerPizza,以及具体的配料装饰器类 CheeseBacon。这些具体的类分别根据自己的需要来实现餐点类或者装饰器类。

在客户端代码中,我们先创建一个汉堡餐 Hamburger 的实例,然后添加一份芝士和一份培根,最后输出餐点的描述以及价格。首先输出的是 “Hamburger 10”,然后再添加芝士之后输出 “Hamburger + Cheese 15”,最后再添加培根之后输出 “Hamburger + Cheese + Bacon 23”。这样,我们就成功地使用了装饰器模式来为餐点添加配料。

代理模式

代理模式(Proxy Pattern)是一种结构型设计模式,它提供了一种代理对象来控制对另一个对象的访问。代理对象充当着客户端与另一个对象之间的中介隐藏了另一个对象的复杂性,并在不改变另一个对象的情况下,提供了一些额外的功能。

一个简单的代理模式的例子是:我们有一个图片加载类,它负责加载远程图片,并将其显示在页面中。但是,在某些情况下,我们不想直接将图片加载到页面中,而是想在用户浏览器中将它进行预加载,等到用户需要加载它时再将其显示在页面中。在这种情况下,我们可以使用代理模式来实现这一需求。

下面是使用 JavaScript 实现的简单的代理模式的示例:

// 图片加载类
class ImageLoader {
  constructor(url) {
    this.url = url;
    this.image = null;
  }
  
  loadImage() {
    if(!this.image) {
      this.image = new Image();
      this.image.src = this.url;
    }
    return this.image;
  }
}

// 图片预加载代理类
class ImagePreloader {
  constructor(url) {
    this.imageLoader = new ImageLoader(url);
  }
  
  preloadImage() {
    const image = this.imageLoader.loadImage();
    if(!image.complete) {
      image.addEventListener('load', (event) => {
        this.displayImage();
      });
    } else {
      this.displayImage();
    }
  }
  
  displayImage() {
    console.log('Image is ready to be displayed!');
    // 在这里将图片显示到页面中
  }
}

// 客户端代码
const imagePreloader = new ImagePreloader('http://www.example.com/image.jpg');
imagePreloader.preloadImage();

在这个示例中,我们定义了一个图片加载类 ImageLoader,它负责加载图片并返回图片对象。然后我们又定义了一个图片预加载代理类 ImagePreloader,它封装了 ImageLoader 类对象,并在图片没有完全加载时,使用 addEventListener() 方法监听 load 事件,等到图片加载完成后再将其显示到页面中。

在客户端代码中,我们创建了一个 ImagePreloader 类对象,并调用它的 preloadImage() 方法来预加载远程图片。当图片加载完成后,代理对象将自动调用 displayImage() 方法将其显示在页面中。这样,我们就成功地使用代理模式来延迟加载图片,提高了网页加载速度,提升了用户体验。

外观模式

外观模式(Facade Pattern)是一种结构型设计模式,它为复杂的子系统提供一个简单的接口,使得其易于使用。该模式隐藏了子系统的复杂性,让客户端只需要与一个简单的外观对象进行交互,而不用与子系统的每个组件进行交互,从而降低了客户端代码的复杂度和依赖性。

一个简单的外观模式的例子是:我们有一个DVD播放器,它由多个组件组成,包括电源、显示器、音频等。现在我们要设计一个外观对象,它可以控制DVD的开始、暂停和停止等操作。客户端只需要与这个简单的外观对象进行交互,而不用了解每个组件的具体实现细节。

下面是使用 JavaScript 实现的简单的外观模式的示例:

// DVD播放器电源组件类
class Power {
  constructor() {
    this.isTurnedOn = false;
  }
  
  turnOn() {
    this.isTurnedOn = true;
    console.log('Power is turned on');
  }
  
  turnOff() {
    this.isTurnedOn = false;
    console.log('Power is turned off');
  }
}

// DVD播放器显示器组件类
class Display {
  display(title) {
    console.log(`Displaying ${title}`);
  }
}

// DVD播放器音频组件类
class Audio {
  play() {
    console.log('Audio is playing');
  }
  
  pause() {
    console.log('Audio is paused');
  }
  
  stop() {
    console.log('Audio is stopped');
  }
}

// DVD播放器外观类
class DVDPlayerFacade {
  constructor() {
    this.power = new Power();
    this.display = new Display();
    this.audio = new Audio();
  }
  
  play(title) {
    this.power.turnOn();
    this.display.display(title);
    this.audio.play();
  }
  
  pause() {
    this.audio.pause();
  }
  
  stop() {
    this.audio.stop();
    this.power.turnOff();
  }
}

// 客户端代码
const dvdPlayer = new DVDPlayerFacade();
dvdPlayer.play('Star Wars: The Last Jedi');
dvdPlayer.pause();
dvdPlayer.stop();

在这个示例中,我们定义了一个DVD播放器的电源组件类 Power、显示器组件类 Display 和音频组件类 Audio。然后我们又定义了一个DVD播放器外观类 DVDPlayerFacade,它将这些组件进行组合,提供了一个简单的接口,使得客户端可以控制DVD的开始、暂停和停止等操作。

在客户端代码中,我们创建了一个DVD播放器外观类对象 DVDPlayerFacade,并分别调用它的 play()pause()stop() 方法来控制DVD的播放操作。这些操作对于客户端代码来说是透明的,它只需要了解这个简单的外观接口,而不需要了解具体的组件实现细节。这样,我们就成功地使用外观模式来简化了DVD播放器的操作,提高了客户端代码的可读性和可维护性。

桥接模式

桥接模式(Bridge Pattern)是一种结构型设计模式,它允许你将抽象部分与实现部分分离,使得它们可以独立地变化。在桥接模式中,我们将一个对象的实现与其抽象进行分离,从而使得它们可以单独进行变化,而不会相互影响。

一个简单的桥接模式的例子是:我们有一个电视机和多个遥控器,它们之间的关系是一对多的关系。我们可以使用桥接模式来将这个关系进行抽象,从而让一个电视机对象可以与多个遥控器对象进行关联,并且可以随时切换遥控器,而不会影响电视机对象的状态和行为。

下面是使用 JavaScript 实现的简单的桥接模式的示例:

// 抽象遥控器类
class RemoteControl {
  constructor(tv) {
    this.tv = tv;
  }
  
  on() {
    this.tv.on();
  }
  
  off() {
    this.tv.off();
  }
  
  setChannel(channel) {
    this.tv.setChannel(channel);
  }
}

// 具体遥控器类
class BasicRemoteControl extends RemoteControl {
  constructor(tv) {
    super(tv);
  }
}

class AdvancedRemoteControl extends RemoteControl {
  constructor(tv) {
    super(tv);
  }
  
  setVolume(volume) {
    this.tv.setVolume(volume);
  }
}

// 抽象电视机类
class TV {
  constructor() {}
  
  on() {}
  
  off() {}
  
  setChannel(channel) {}
}

// 具体电视机类
class SonyTV extends TV {
  constructor() {
    super();
    this.channel = 1;
  }
  
  on() {
    console.log('Sony TV is turned on');
  }
  
  off() {
    console.log('Sony TV is turned off');
  }
  
  setChannel(channel) {
    this.channel = channel;
    console.log(`Sony TV channel is set to ${channel}`);
  }
}

class SamsungTV extends TV {
  constructor() {
    super();
    this.channel = 1;
  }
  
  on() {
    console.log('Samsung TV is turned on');
  }
  
  off() {
    console.log('Samsung TV is turned off');
  }
  
  setChannel(channel) {
    this.channel = channel;
    console.log(`Samsung TV channel is set to ${channel}`);
  }
  
  setVolume(volume) {
    console.log(`Samsung TV volume is set to ${volume}`);
  }
}

// 客户端代码
const sonyTV = new SonyTV();
const samsungTV = new SamsungTV();

const basicRemote = new BasicRemoteControl(sonyTV);
basicRemote.on();
basicRemote.setChannel(4);
basicRemote.off();

const advancedRemote = new AdvancedRemoteControl(samsungTV);
advancedRemote.on();
advancedRemote.setChannel(7);
advancedRemote.setVolume(15);
advancedRemote.off();

在这个示例中,定义了一个抽象遥控器类 RemoteControl 和一个抽象电视机类 TV
然后又定义了两个具体遥控器类 BasicRemoteControlAdvancedRemoteControl,以及两个具体电视机类 SonyTVSamsungTV

组合模式

组合模式(Composite Pattern)是一种结构型设计模式,它能够将对象组合成树形结构,并且能像使用独立对象一样使用其中的任何一个对象。在组合模式中,我们可以将对象组合成树形结构以表示 “部分-整体” 的层次结构,同时还能让客户端以统一的方式对待单个对象和组合对象。

一个简单的组合模式的例子是:我们有一个组织机构,包括多个部门和员工。我们可以使用组合模式来表示这种 “部分-整体” 的层次结构,并且能够统一地对待部门和员工。

下面是使用 JavaScript 实现的简单的组合模式的示例:

// 抽象组件类
class OrganizationComponent {
  constructor(name) {
    this.name = name;
  }
  
  getName() {
    return this.name;
  }
  
  print() {}
}

// 具体部门类
class Department extends OrganizationComponent {
  constructor(name) {
    super(name);
    this.children = [];
  }
  
  add(component) {
    this.children.push(component);
  }
  
  remove(component) {
    const index = this.children.indexOf(component);
    if(index !== -1) {
      this.children.splice(index, 1);
    }
  }
  
  print() {
    console.log(`Department: ${this.getName()}`);
    for(let child of this.children) {
      child.print();
    }
  }
}

// 具体员工类
class Employee extends OrganizationComponent {
  constructor(name) {
    super(name);
  }
  
  print() {
    console.log(`Employee: ${this.getName()}`);
  }
}

// 客户端代码
const organization = new Department('Headquarter');

const financeDept = new Department('Finance Department');
financeDept.add(new Employee('Alice'));
financeDept.add(new Employee('Bob'));

const salesDept = new Department('Sales Department');
salesDept.add(new Employee('Charlie'));
salesDept.add(new Employee('David'));

organization.add(financeDept);
organization.add(salesDept);

organization.print();

在这个示例中,我们定义了一个抽象组件类 OrganizationComponent 和两个具体的类 DepartmentEmployee。具体部门类 Department 内部维护一个员工列表,同时还实现了添加、删除和打印子组件的方法。具体员工类 Employee 重写了 print() 方法用于输出员工姓名。

在客户端代码中,我们创建了一个总部部门 Headquarter,然后又分别创建了财务部门 Finance Department 和销售部门 Sales Department。其中,财务部门又包括了员工 Alice 和员工 Bob;销售部门又包括了员工 Charlie 和员工 David

享元模式

享元模式(Flyweight Pattern)是一种结构型设计模式,它可以减少程序中的对象数量,通过共享相同对象的方式来减少内存和计算资源的开销。该模式的主要思路是将一个对象的状态拆分成内部状态和外部状态两部分,内部状态作为对象的固有属性进行共享复用,外部状态则通过参数的方式传递进来,每个独立对象可以重用内部状态,拥有自己独有的外部状态。

以下是JS中的一个享元模式的示例代码:

// 定义一个享元工厂对象
var FlyweightFactory = (function () {
  var flyweights = {};

  return {
    get: function (key) {
      if (!flyweights[key]) {
        flyweights[key] = new Flyweight(key);
      }

      return flyweights[key];
    },

    getCount: function () {
      var count = 0;

      for (var f in flyweights) count++;

      return count;
    }
  };
})();

// 定义一个享元对象
function Flyweight (name) {
  this.name = name;
}

Flyweight.prototype.execute = function (state) {
  console.log(`Flyweight ${this.name}, state: ${state}`);
};

// 定义一个客户端对象
function Client (name, state) {
  this.flyweight = FlyweightFactory.get(name);
  this.state = state;
}

Client.prototype.execute = function () {
  this.flyweight.execute(this.state);
};

// 客户端调用
var client1 = new Client('flyweight1', 'state1');
client1.execute(); // Flyweight flyweight1, state: state1

var client2 = new Client('flyweight2', 'state2');
client2.execute(); // Flyweight flyweight2, state: state2

console.log(`共创建了 ${FlyweightFactory.getCount()} 个享元对象`);

在上述代码中,我们通过工厂对象FlyweightFactory创建享元对象Flyweight,并通过客户端对象Client在需要使用时获取享元对象。由于享元对象Flyweight的内部状态是可以共享的,因此我们只需要在需要使用时获取相应的享元对象,而不需要多次创建。这样可以节省内存和计算资源的开销。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

opencv 图像识别

opencv的目标是使计算机可以快速准确地从数字图像中提取和分析特征。它使用了许多新的算法和技术,例如改进的模板匹配、基于统计的特征分析以及深度学习等。opencv支持多种平台,包括 Windows、 MacOS、 Linux和 Android,开发者可以使用 OpenC…

浏览器相关前端开发事项

文章目录 存储浏览器持久化存储(F12->应用->存储)浏览器缓存(F12->内存)浏览器存储管理单位(域名/IP为单位)区别localStorage VS 浏览器缓存localStorage VS cookies 存储 浏览器持久化存储&…

【CORS策略: Multiple CORS header ‘Access-Control-Allow-Origin‘ not allowed导致的跨域问题】

引起跨域CORS报错的原因有很多种!!!!! 这里我的报错属于最后一条。 探索的原因 正常axios请求接口,调试接口时出现以下问题 Access to XMLHttpRequest at http://192.168.31.111:9000/api/user/sessio…

皮卡丘../../(目录遍历)/敏感信息泄露/PHP反序列化

一.目录遍历 1.概述 在web功能设计中,很多时候我们会要将需要访问的文件定义成变量,从而让前端的功能便的更加灵活。 当用户发起一个前端的请求时,便会将请求的这个文件的值(比如文件名称)传递到后台,后台再执行其对应的文件。 在这个过程中…

【MySQL数据库 | 第四篇】SQL通用语法及分类

目录 🤔SQL通用语法: 😊语句: 😊注释: 🤔SQL语句分类: 😊1.DDL语句: 😊2.DML语句: 😊3.DQL语言: &…

C++STL库之map

文章目录 关于仿函数stackdeque(双端对列)queuepriority_queuemap(重点)set(去重) 关于仿函数 //C不能重载的运算符sizeof、 ::、 ? :、 .、 *、 class Add { public:int operator()(int a, int b)const{return a b;} }; //函数对象,仿函数…

2022年长三角高校数学建模竞赛C题隧道的升级改造与设计解题全过程文档及程序

2022年长三角高校数学建模竞赛 C题 隧道的升级改造与设计 原题再现: 某地现存一旧式双洞隧道,现计划将该隧道在旧貌基础上升级改造。在升级改造前,需进行定标与设计。考虑到该隧道洞壁附着特殊涂料,无人机在洞内通信信号较差&am…

LIBEVENT 框架

LIBEVENT 框架 LAMPlibevent特点:libevent的功能libevent官网安装步骤Linux下libevent主要API介绍libevent使用步骤libevent 编程案例LAMP 从LAMP说起: 是一个缩写,它指一组通常一起使用来运行动态网站或者服务器的自由软件 Linux - 操作系统Apache - 网页服务器MySQL - 数据…

基于Yolov5目标检测的物体分类识别及定位(一) -- 数据集原图获取与标注

从本篇博客正式开始深度学习项目的记录,实例代码只会放通用的代码,数据集和训练数据也是不会全部放出。 系列文章: 基于Yolov5目标检测的物体分类识别及定位(一) -- 数据集原图获取与标注 基于Yolov5目标检测的物体分类…

Data Distillation: A Survey

本文是蒸馏学习综述系列的第二篇文章,Data Distillation: A Survey的一个翻译 数据蒸馏:综述 摘要1 引言2 数据蒸馏框架2.1 元模型匹配的数据蒸馏2.2 梯度匹配的数据蒸馏2.3 轨迹匹配的数据蒸馏2.4 分布匹配的数据蒸馏2.5 因式分解的数据蒸馏 3 数据模态…

python中Requests发送json格式的post请求方法

问题:做requests请求时遇到如下报错: {“code”:“500”,“message”:"JSON parse error: Cannot construct instance of com.bang.erpapplication.domain.User (although at least one Creator exists): no String-argument constructor/factory …

16.2:岛屿数量问题

文章目录 岛屿数量问题方法一:采用递归的方法方法二:使用并查集的方法(map)方法三:使用并查集的方法(数组) 岛屿数量问题 测试链接:https://leetcode.com/problems/number-of-islan…

C++ string类-2

at at 函数是在C还没有支持运算符重载的时候提供的。 他可以像 [] 重载运算符一样&#xff0c;找到某个位置的字符&#xff1a; string s1("hello world");s1.at(0) x;cout << s1 << endl; 输出&#xff1a; [] 重载运算符和 at&#xff08;&#x…

8自由度并联腿机器狗实现行走功能

1. 功能说明 本文示例将实现R309a样机8自由度并联腿机器狗行走的功能。 2. 并联仿生机器人结构设计 机器狗是一种典型的并联仿生四足机器人&#xff0c;其腿部结构主要模仿了四足哺乳动物的腿部结构&#xff0c;主要由腿部的节段和旋转关节组成。在设计机器狗的腿部结构时&…

echart实现地图展示

最近做的页面中需要展示省级地图精确到市级且悬浮到地区上时会显示一些信息 然后参考了网址&#xff1a; “绿色金融” - 江西省 - category-work,geo地理坐标,legend,series-map地图,series-scatter散点图,title标题,tooltip提示框,visualMap视觉映射 - makeapie echarts社区…

【玩转Linux操作】硬链接和软连接

&#x1f38a;专栏【玩转Linux操作】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【Counting Stars 】 欢迎并且感谢大家指出小吉的问题&#x1f970; 欢迎大家访问“在下小吉.”&#xff08;偷偷告诉你这个是我的大号哦&#…

yolov8seg模型转onnx转ncnn

yolov8是yolo的最新版本&#xff0c;可做图像分类&#xff0c;目标检测&#xff0c;实例分割&#xff0c;姿态估计。 主页地址 这里测试一个分割模型。 模型如下 选yolov8n-seg模型&#xff0c;转成onnx&#xff0c;再转ncnn测试。 yolov8s-seg的ncnn版可以直接用这个 如果用…

【Django 网页Web开发】07. 快捷的表单生成 Form与MoudleForm(保姆级图文)

目录 注意 正规写法是 ModelForm&#xff0c;下面文章我多实现效果url.py新建3个html文件数据库连接model.py 数据表1. 原始方法view.pytestOrgion.html 2. Form方法view.pytestForm.html 3. MoudleForm方法给字段设置样式面向对象的思路&#xff0c;批量添加样式错误信息的显示…

搜索算法(三) 回溯法

1.回溯法 回溯法可以理解成一种特殊的深度优先算法&#xff0c;比起普通的DFS&#xff0c;多了还原当前节点的一步。 修改当前节点、递归子节点、还原当前节点。 本质是一种试错的思想。 维基百科&#xff1a; 2.例题 1&#xff09; 力扣https://leetcode.cn/problems/pe…

17_Linux根文件简介与Busybox构建文件系统

目录 根文件系统简介 文件目录简介 BusyBox简介 编译BusyBox构建根文件系统 修改Makefile添加编译器 busybox中文字符支持 配置 busybox 编译busybox 向根文件系统添加lib库 向rootfs的“usr/lib”目录添加库文件 创建其他文件夹 根文件系统初步测试 根文件系统简介…
最新文章