前端开发中常用的几种设计模式

article/2025/10/22 4:52:29

设计模式概览

设计模式是对软件设计开发过程中反复出现的某类问题的通用解决方案。设计模式更多的是指导思想和方法论,而不是现成的代码,当然每种设计模式都有每种语言中的具体实现方式。学习设计模式更多的是理解各种模式的内在思想和解决的问题,毕竟这是前人无数经验总结成的最佳实践,而代码实现则是对加深理解的辅助。

设计模式可以分为三大类:

  1. 结构型模式(Structural Patterns): 通过识别系统中组件间的简单关系来简化系统的设计。
  2. 创建型模式(Creational Patterns): 处理对象的创建,根据实际情况使用合适的方式创建对象。常规的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。
  3. 行为型模式(Behavioral Patterns):用于识别对象之间常见的交互模式并加以实现,如此,增加了这些交互的灵活性。

 23种设计模式概览

上述中一共有23种设计模式,但我们作为前端开发人员,需要了解的大概有以下10种。

前端需要了解的设计模式(10种)

创建型模式

故名思意,这些模式都是用来创建实例对象的。

1. 工厂模式

我们从简单的开始。 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。 

工厂模式

上图为例,我们构造一个简单的汽车工厂来生产汽车:

// 汽车构造函数
function SuzukiCar(color) {this.color = color;this.brand = 'Suzuki';
}// 汽车构造函数
function HondaCar(color) {this.color = color;this.brand = 'Honda';
}// 汽车构造函数
function BMWCar(color) {this.color = color;this.brand = 'BMW';
}// 汽车品牌枚举
const BRANDS = {suzuki: 1,honda: 2,bmw: 3
}/*** 汽车工厂*/
function CarFactory() {this.create = (brand, color)=> {switch (brand) {case BRANDS.suzuki:return new SuzukiCar(color);case BRANDS.honda:return new HondaCar(color);case BRANDS.bmw:return new BMWCar(color);default:break;}}
}

使用一下我们的工厂:

const carFactory = new CarFactory();
const cars = [];cars.push(carFactory.create(BRANDS.suzuki, 'brown'));
cars.push(carFactory.create(BRANDS.honda, 'grey'));
cars.push(carFactory.create(BRANDS.bmw, 'red'));function sayHello() {console.log(`Hello, I am a ${this.color} ${this.brand} car`);
}for (const car of cars) {sayHello.call(car);
}

输出结果:

Hello, I am a brown Suzuki car
Hello, I am a grey Honda car
Hello, I am a red BMW car

使用工厂模式之后,不再需要重复引入一个个构造函数,只需要引入工厂对象就可以方便的创建各类对象。

2. 单例模式

首先我们需要理解什么是单例?

单:指的是一个。
例:指的是创建的实例。
单例:指的是创建的总是同一个实例。也就是使用类创建的实例始终是相同的。

先看下面的一段代码:

class Person{constructor(){}
}let p1 = new Person();
let p2 = new Person();console.log(p1===p2) //false

上面这段代码,定义了一个Person类,通过这个类创建了两个实例,我们可以看到最终这两个实例是不相等的。也就是说,通过同一个类得到的实例不是同一个(这本就是理所应当),但是如果我们想始终得到的是同一个实例,那么这就是单例模式。那么下面就该介绍如何实现单例模式了

想要实现单例模式,我们需要注意两点:

  1. 需要使用return。使用new的时候如果没有手动设置return,那么会默认返回this。但是,我们这里要使得每次返回的实例相同,也就是需要手动控制创建的对象,因此这里需要使用return
  2.  我们需要每次return的是同一个对象。也就是说实际上在第一次实例的时候,需要把这个实例保存起来。再下一个实例的时候,直接return这个保存的实例。因此,这里需要用到闭包了
const Person = (function(){let instance = null;return class{constructor(){if(!instance){//第一次创建实例,那么需要把实例保存instance = this;}else{return instance;}}}
})()
let p3 = new Person();
let p4 = new Person();
console.log(p3===p4)  //true

从上面的代码中,我们可以看到在闭包中,使用instance变量来保存创建的实例,每次返回的都是第一次创建的实例。这样的话就实现了无论创建多少次,创建的都是同一个实例,这就是单例模式。

3. 原型模式

通俗点讲就是创建一个共享的原型,并通过拷贝这些原型创建新的对象。

在我看来,其实原型模式就是指定新创建对象的模型,更通俗一点来说就是我想要新创建的对象的原型是我指定的对象。

最简单的原型模式的实现就是通过Object.create()。Object.create(),会使用现有的对象来提供新创建的对象的__proto__。例如下方代码:

let person = {name:'hello',age:24
}let anotherPerson = Object.create(person);
console.log(anotherPerson.__proto__)  //{name: "hello", age: 24}anotherPerson.name = 'world';  //可以修改属性
anotherPerson.job = 'teacher';

另外,如果我们想要自己实现原型模式,而不是使用封装好的Object.create()函数,那么可以使用原型继承来实现

function F(){}F.prototype.g = function(){}//G类继承F类function G(){F.call(this);
}//原型继承
function Fn(){};
Fn.prototype = F.prototype;
G.prototype = new Fn();G.prototype.constructor = G;

原型模式就是创建一个指定原型的对象。如果我们需要重复创建某个对象,那么就可以使用原型模式来实现。


结构型模式

1. 装饰器模式

装饰器模式:为对象添加新功能,不改变其原有的结构和功能。

适配器模式是原有的不能用了,要重新封装接口。装饰器模式是原有的还能用,但是需要新增一些东西来完善这个功能。

比如手机壳,手机本身的功能不受影响,手机壳就是手机的装饰器模式。

装饰器模式

class Circle {draw() {console.log('画一个圆形');}
}class Decorator {constructor(circle) {this.circle = circle;}draw() {this.circle.draw();this.setRedBorder(circle);}setRedBorder(circle) {console.log('设置红色边框')}
}// 测试
let circle = new Circle();let client = new Decorator(circle);
client.draw();

输出结果:

画一个圆形
设置红色边框

如今都2021了,es7也应用广泛,我们在es7中这么写(ES7装饰器):

1、安装 yarn add babel-plugin-transform-decorators-legacy

2、新建.babelrc文件,进行下面的配置

{"presets": ["es2015", "latest"],"plugins": ["transform-decorators-legacy"]
}

 3、上代码

@testDec
class Demo {// ...
}function testDec(target) {target.isDec = true
}console.log(Demo.isDec)//输出true

打印出来了true,说明@testDec这个装饰器已经成功了,函数是个装饰器,用@testDec给Demo装饰了一遍。这个target其实就是class Demo,然后给她加一个isDec。

拆解后就是下面的内容:

// 装饰器原理
@decorator
class A {}// 等同于
class A {}
A = decorator(A) || A;

装饰器参数的形式 

@testDec(false)class Demo {
}function testDec(isDec) {return function (target) {target.isDec = isDec}
}console.log(Demo.isDec);

验证是否是一个真正的装饰器模式需要验证以下几点:

1.将现有对戏那个和装饰器进行分离,两者独立存在
2.符合开放封闭原则

2. 适配器模式

适配器模式:旧接口格式和使用者不兼容,中间加一个适配转换接口。

比如国外的插座跟国内的插座不一样,我们需要买个转换器去兼容。

适配器模式

 上代码:

class Adaptee {specificRequest() {return '德国标准的插头';}
}class Target {constructor() {this.adaptee = new Adaptee();}request() {let info = this.adaptee.specificRequest();return `${info} -> 转换器 -> 中国标准的插头`}
}// 测试
let client = new Target();
client.request();

 结果:

德国标准的插头 -> 转换器 -> 中国标准的插头

 场景上可封装旧接口:

// 自己封装的ajax,使用方式如下:
ajax({url: '/getData',type: 'Post',dataType: 'json',data: {id: '123'}
}).done(function(){})
// 但因为历史原因,代码中全都是:
// $.ajax({...})

这个时候需要一个适配器

// 做一层适配器
var $ = {ajax: function (options) {return ajax(options)}
}

3. 代理模式

代理模式:使用者无权访问目标对象,中间加代理,通过代理做授权和控制。

明星经纪人:比如有个演出,要请明星,要先联系经纪人。

或者理解为:为一个对象提供一个代用品或者占位符,以便控制对它的访问。例如图片懒加载、中介等。代理模式

/*** pre:代理模式* 小明追求A,B是A的好朋友,小明比不知道A什么时候心情好,不好意思直接将花交给A,* 于是小明将花交给B,再由B交给A.*/// 花的类 
class Flower{constructor(name){this.name = name }
}// 小明拥有sendFlower的方法
let Xioaming = {sendFlower(target){var flower = new Flower("玫瑰花")target.receive(flower)}
}
// B对象中拥有接受花的方法,同时接收到花之后,监听A的心情,并且传入A心情好的时候函数
let B = {receive(flower){this.flower =flowerA.listenMood(()=>{A.receive(this.flower)})}}
// A接收到花之后输出花的名字
let A = {receive(flower){console.log(`A收到了${flower.name} `)// A收到了玫瑰花 },listenMood(func){setTimeout(func,1000)}
}
Xioaming.sendFlower(B)

虚拟代理用于图片的预加载

图片很大,页面加载时会空白,体验不好,所以我们需要个占位符,来短暂替代这个图片,等图片加载好了放上去。

let myImage = (function(){let img = new Imagedocument.body.appendChild(img)return {setSrc:(src)=>{img.src = src}}
})()
let imgProxy =(function(){let imgProxy = new Image// 这个地方我使用了setTimeout来增强演示效果,否则本地加载太快,根本看不到。imgProxy.onload=function(){setTimeout(()=>{myImage.setSrc(this.src)},2000)}return (src)=>{myImage.setSrc("../../img/bgimg.jpeg")imgProxy.src=src}
})()imgProxy("../../img/background-cover.jpg")

ES6 Proxy 

其实在ES6中,已经有了Proxy,这个内置的函数。我们来用一个例子来演示一下他的用法。这是一个明星代理的问题。

let star={name : "张XX",age:25,phone : "1300001111"
}
let agent = new Proxy(star,{get:function(target,key){if(key === "phone"){return  "18839552597"}else if(key === "name"){return "张XX"}else if(key === "price"){return "12W"}else if(key === "customPrice"){return target.customPrice}},set:function(target,key,value){if(key === "customPrice"){if(value < "10"){console.log("太低了!!!")return false}else{target[key] = valuereturn true}}}}
)console.log(agent.name)
console.log(agent.price)
console.log(agent.phone)
console.log(agent.age)
agent.customPrice = "12"
console.log(agent)
console.log(agent.customPrice)

设计原则验证

代理类和目标类分离,隔离开目标类和使用者

符合开放封闭原则


行为型模式

1. 策略模式

策略模式是一种简单却常用的设计模式,它的应用场景非常广泛。我们先了解下策略模式的概念,再通过代码示例来更清晰的认识它。

策略模式由两部分构成:一部分是封装不同策略的策略组,另一部分是 Context。通过组合和委托来让 Context 拥有执行策略的能力,从而实现可复用、可扩展和可维护,并且避免大量复制粘贴的工作。

策略模式

策略模式的典型应用场景是表单校验中,对于校验规则的封装。接下来我们就通过一个简单的例子具体了解一下:

/*** 登录控制器*/
function LoginController() {this.strategy = undefined;this.setStrategy = function (strategy) {this.strategy = strategy;this.login = this.strategy.login;}
}/*** 用户名、密码登录策略*/
function LocalStragegy() {this.login = ({ username, password }) => {console.log(username, password);// authenticating with username and password... }
}/*** 手机号、验证码登录策略*/
function PhoneStragety() {this.login = ({ phone, verifyCode }) => {console.log(phone, verifyCode);// authenticating with hone and verifyCode... }
}/*** 第三方社交登录策略*/
function SocialStragety() {this.login = ({ id, secret }) => {console.log(id, secret);// authenticating with id and secret... }
}const loginController = new LoginController();// 调用用户名、密码登录接口,使用LocalStrategy
app.use('/login/local', function (req, res) {loginController.setStrategy(new LocalStragegy());loginController.login(req.body);
});// 调用手机、验证码登录接口,使用PhoneStrategy
app.use('/login/phone', function (req, res) {loginController.setStrategy(new PhoneStragety());loginController.login(req.body);
});// 调用社交登录接口,使用SocialStrategy
app.use('/login/social', function (req, res) {loginController.setStrategy(new SocialStragety());loginController.login(req.body);
});

从以上示例可以得出使用策略模式有以下优势:

  1. 方便在运行时切换算法和策略
  2. 代码更简洁,避免使用大量的条件判断
  3. 关注分离,每个strategy类控制自己的算法逻辑,strategy和其使用者之间也相互独立 

2. 观察者模式

观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一或一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。典型代表vue/react等。

使用观察者模式的好处:

  1. 支持简单的广播通信,自动通知所有已经订阅过的对象。
  2. 目标对象与观察者存在的是动态关联,增加了灵活性。
  3. 目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。

观察者模式当然给元素绑定事件的addEventListener()也是一种:

target.addEventListener(type, listener [, options]);

Target就是被观察对象Subject,listener就是观察者Observer。

观察者模式中Subject对象一般需要实现以下API:

  • subscribe(): 接收一个观察者observer对象,使其订阅自己
  • unsubscribe(): 接收一个观察者observer对象,使其取消订阅自己
  • fire(): 触发事件,通知到所有观察者

用JavaScript手动实现观察者模式:

// 被观察者
function Subject() {this.observers = [];
}Subject.prototype = {// 订阅subscribe: function (observer) {this.observers.push(observer);},// 取消订阅unsubscribe: function (observerToRemove) {this.observers = this.observers.filter(observer => {return observer !== observerToRemove;})},// 事件触发fire: function () {this.observers.forEach(observer => {observer.call();});}
}

验证一下订阅是否成功: 

const subject = new Subject();function observer1() {console.log('Observer 1 Firing!');
}function observer2() {console.log('Observer 2 Firing!');
}subject.subscribe(observer1);
subject.subscribe(observer2);
subject.fire();

输出:

Observer 1 Firing! 
Observer 2 Firing!

验证一下取消订阅是否成功:

subject.unsubscribe(observer2);
subject.fire();

输出:

Observer 1 Firing!

3. 迭代器模式

ES6中的迭代器 Iterator 相信大家都不陌生,迭代器用于遍历容器(集合)并访问容器中的元素,而且无论容器的数据结构是什么(Array、Set、Map等),迭代器的接口都应该是一样的,都需要遵循 迭代器协议。

迭代器模式解决了以下问题:

  1. 提供一致的遍历各种数据结构的方式,而不用了解数据的内部结构
  2. 提供遍历容器(集合)的能力而无需改变容器的接口

迭代器模式

一个迭代器通常需要实现以下接口:

  • hasNext():判断迭代是否结束,返回Boolean
  • next():查找并返回下一个元素

为Javascript的数组实现一个迭代器可以这么写:

const item = [1, 'red', false, 3.14];function Iterator(items) {this.items = items;this.index = 0;
}Iterator.prototype = {hasNext: function () {return this.index < this.items.length;},next: function () {return this.items[this.index++];}
}

 验证一下迭代器:

const iterator = new Iterator(item);while(iterator.hasNext()){console.log(iterator.next());
}

输出:

1, red, false, 3.14

ES6提供了更简单的迭代循环语法 for...of,使用该语法的前提是操作对象需要实现 可迭代协议(The iterable protocol),简单说就是该对象有个Key为 Symbol.iterator 的方法,该方法返回一个iterator对象。

比如我们实现一个 Range 类用于在某个数字区间进行迭代:

function Range(start, end) {return {[Symbol.iterator]: function () {return {next() {if (start < end) {return { value: start++, done: false };}return { done: true, value: end };}}}}
}

验证:

for (num of Range(1, 5)) {console.log(num);
}

结果:

1, 2, 3, 4

4. 状态模式

状态模式:一个对象有状态变化,每次状态变化都会触发一个逻辑,不能总是用if...else来控制。

状态模式

 比如红绿灯:

// 状态(红灯,绿灯 黄灯)
class State {constructor(color) {this.color = color;}// 设置状态handle(context) {console.log(`turn to ${this.color} light`);context.setState(this)}
}// 主体
class Context {constructor() {this.state = null;}// 获取状态getState() {return this.state;}setState(state) {this.state = state;}
}// 测试
let context = new Context();
let green = new State('green');
let yellow = new State('yellow');
let red = new State('red');// 绿灯亮了
green.handle(context);
console.log(context.getState())// 黄灯亮了
yellow.handle(context);
console.log(context.getState())// 红灯亮了
red.handle(context);
console.log(context.getState())

设计原则验证

将状态对象和主体对象分离,状态的变化逻辑单独处理

符合开放封闭原则


http://chatgpt.dhexx.cn/article/fMeqUJdO.shtml

相关文章

图像金字塔原理

一、图像缩小 先高斯模糊&#xff0c;再降采样&#xff0c;需要一次次重复&#xff0c;不能一次到底 二、图像扩大 先扩大&#xff0c;再卷积或者使用拉普拉斯金字塔 三、金字塔类型 1、高斯金字塔 用于下采样。 高斯金字塔是最基本的图像塔。 原理&#xff1a;首先将原图…

【编程】金字塔图案

1&#xff0e;问题描述 打印出金字塔图案&#xff0c;如图1.1所示。 图1-1 2&#xff0e;问题分析 这个问题是一个很经典的循环应用的题目。我们都知道&#xff0c;打印输出的时候&#xff0c;都是从最左端输出&#xff0c;而这里&#xff0c;第一个星号是在中间。这实际是…

计算机视觉-OpenCV图像金字塔

&#x1f60a;&#x1f60a;&#x1f60a;欢迎来到本博客&#x1f60a;&#x1f60a;&#x1f60a; 本次博客内容将继续讲解关于OpenCV的相关知识 &#x1f389;作者简介&#xff1a;⭐️⭐️⭐️目前计算机研究生在读。主要研究方向是人工智能和群智能算法方向。目前熟悉pytho…

图像金字塔(image pyramid) 分为两种:高斯金字塔  和  拉普拉斯金字塔。

高斯金字塔 高斯金字塔模仿的是图像的不同的尺度&#xff0c;尺度应该怎样理解&#xff1f;对于一副图像&#xff0c;你近距离观察图像&#xff0c;与你在一米之外观察&#xff0c;看到的图像效果是不同的&#xff0c;前者比较清晰&#xff0c;后者比较模糊&#xff0c;前者比…

数字图像处理:图像金字塔

转载请标明出处&#xff1a;数字图像处理&#xff1a;图像金字塔_数字图像处理opencv_新浪博客 &#xff08;一&#xff09;概念 以多个分辨率来表示图像的一种有效且概念简单的结构是图像金字塔。图像金字塔最初用于机器视觉和图像压缩&#xff0c;一个图像金字塔是一系列以金…

图像处理-图像金字塔

图像金字塔&#xff08;image pyramid&#xff09;&#xff0c;一般有两种&#xff1a;高斯金字塔、拉普拉斯金字塔 ——————————————————————————————— 先介绍下里面的一些操作&#xff1a; 下采样&#xff1a;相当于对图像进行一个像素的抽取&a…

10.图像金字塔

图像金字塔&#xff1a;主要是指一种算法思想 一般情况下&#xff0c;我们要处理是一副具有固定分辨率的图像。但是有些情况下&#xff0c;我们雪要对同一图像的不同分辨率的子图像进行处理。比如&#xff0c;我们要在一幅图像中查找某个目标&#xff0c;比如险&#xff0c;我们…

图像金字塔:概念及实现

文章目录 图像金字塔&#xff1a;概念和实现1. 图像金字塔的概念2. 图像金字塔的实现方式3. 基于OpenCV的图像金字塔实现参考资料 图像金字塔&#xff1a;概念和实现 首先补充一下分辨率的概念&#xff1a;图像分辨率指图像中存储的信息量&#xff0c;是每英寸图像内有多少个像…

图像金字塔的简单理解

图像金字塔模型&#xff1a; Level层定义的是图片的分辨率&#xff0c;图像金字塔的塔底到塔顶表示的是图片的缩小过程。也就是说从第Level0层开始是原图&#xff0c;越往上越压缩&#xff0c;丢失的信息越多。 图像金字塔的测试&#xff1a; 图片&#xff1a; halcon代码&am…

数字图像处理5:图像金字塔

图像金字塔 近似金字塔和残差金字塔 图像金字塔是图像中多尺度表达的一种&#xff0c;最主要用于图像的分割&#xff0c;是一种以多分辨率来解 释图像的有效但概念简单的结构。图像金字塔最初用于机器视觉和图像压缩&#xff0c;一幅图像的金字塔是一系列以金字塔形状排列的分…

图像金字塔、特征金字塔(FPN)

图像金字塔 参考&#xff1a; https://www.jianshu.com/p/436e96200f80 图像金字塔是图像多尺度表达的一种&#xff0c;是一种以多分辨率来解释图像的有效但概念简单的结构。一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低&#xff0c;且来源于同一张原始图的图像…

图像金字塔,原理、实现及应用

什么是图像金字塔 图像金字塔是对图像的一种多尺度表达&#xff0c;将各个尺度的图像按照分辨率从小到大&#xff0c;依次从上到下排列&#xff0c;就会形成类似金字塔的结构&#xff0c;因此称为图像金字塔。 常见的图像金字塔有两类&#xff0c;一种是高斯金字塔&#xff0…

计算机视觉教程2-5:图像金字塔送她一朵玫瑰(附代码)

目录 1 金字塔2 什么是图像金字塔&#xff1f;3 图像金字塔有什么用&#xff1f;4 OpenCV实战图像金字塔 1 金字塔 平时你听到、见到的金字塔是什么样的&#xff1f; 这样&#xff1f; 还是这样&#xff1f; 实际上除了这些&#xff0c;还有图像金字塔 图像金字塔有什么用&am…

图像金字塔(Python实现)

图像金字塔&#xff08;Python实现&#xff09; 1 简介 在图像处理中常常会调整图像大小,最长的就是放大(zoom in)和缩小(zoom out),尽管集合变换也可以实现图像放大或者缩小 一个图像金字塔式一系列的图像组成,最底下一张式图像尺寸最大,最上方的图像尺寸最小,从空间上从上向下…

图像金字塔分层算法

一. 图像金字塔概述 欢迎关注微信公众号“智能算法”&#xff01; 1. 图像金字塔是图像中多尺度表达的一种&#xff0c;最主要用于图像的分割&#xff0c;是一种以多分辨率来解释图像的有效但概念简单的结构。 2. 图像金字塔最初用于机器视觉和图像压缩&#xff0c;一幅图像的金…

图像金字塔是什么?

一般情况下&#xff0c;我们要处理是一副具有固定分辨率的图像。但是有些情况下&#xff0c;我们需要对同一图像的不同分辨率的子图像进行处理。比如&#xff0c;我们要在一幅图像中查找某个目标&#xff0c;比如脸&#xff0c;我们不知道目标在图像中的尺寸大小。这种情况下&a…

图像处理之高斯金字塔

一&#xff1a;图像金字塔基本操作 对一张图像不断的模糊之后向下采样&#xff0c;得到不同分辨率的图像&#xff0c;同时每次得到的 新的图像宽与高是原来图像的1/2, 最常见就是基于高斯的模糊之后采样&#xff0c;得到的 一系列图像称为高斯金字塔。 高斯金字塔不同(DoG)又…

【OpenCV学习笔记】之图像金字塔(Image Pyramid)

一、尺度调整 顾名思义&#xff0c;即对源图像的尺寸进行放大或者缩小变换。在opencv里面可以用resize函数&#xff0c;将源图像精准地转化为指定尺寸的目标图像。要缩小图像&#xff0c;一般推荐使用CV_INETR_AREA(区域插值)来插值&#xff1b;若要放大图像&#xff0c;推荐使…

图像金字塔总结

本文转载自&#xff1a; http://blog.csdn.net/dcrmg/article/details/52561656 一、 图像金字塔 图像金字塔是一种以多分辨率来解释图像的结构&#xff0c;通过对原始图像进行多尺度像素采样的方式&#xff0c;生成N个不同分辨率的图像。把具有最高级别分辨率的图像放在底…

数字图像处理(21): 图像金字塔(高斯金字塔 与 拉普拉斯金字塔)

目录 1 图像金字塔简介 2 向下取样——pyrDown() 2.1 基础理论 2.2 代码示例 3 向上取样——pyrUp() 3.1 基础理论 3.2 代码示例 4 Laplacian 金字塔 4.1 基础理论 4.2 代码示例 参考资料 1 图像金字塔简介 以多个分辨率来表示图像的一种有效且概念简单的结构是图像…