Javascript设计模式之原型模式、发布订阅模式
原型模式
原型模式用于在创建对象时,通过共享某个对象原型的属性和方法,从而达到提高性能、降低内存占用、代码复用的效果。
- 示例一
function Person(name) {
this.name = name;
this.config = {
a: "1",
b: "2",
};
this.hello = function () {
console.info("hello");
};
}
假如需要通过以上代码创建 100 个实例,那么将需要创建 100 个 config、100 个 hello,而这两个东西在每个实例里面是完全一样的。
因此我们可以通过提取公共代码的方式进行油优化。
const config = {
a: "1",
b: "2",
};
const hello = function () {
console.info("hello");
};
function Person(name) {
this.name = name;
this.config = config;
this.hello = hello
}
这样的方式使得无论创建多少个Person对象都只需要创建一个config、一个hello。 但是仍然污染全局变量、config被误修改、Person和其他代码耦合大、不易于代码扩展维护等问题。
因此可以通过原型的方式进行优化。
function Person() {}
var p = new Person();
该函数创建实例时原型图如下:
- 示例二
function Person(name) {
this.name = name;
this.config = {
a: "1",
b: "2",
};
this.hello = function () {
console.info("hello");
};
}
//此方式会重写prototype,造成constructor丢失,变为Object()。
//可以使用Person.prototype.xx=yy的方式写,或者重新指定Person.prototype.constructor=Person
Person.prototype = {
version: 1.0,
say: function (arg) {
console.info(`${this.name} say ${arg}`);
},
constructor: Person,
};
var p1 = new Person("p1");
var p2 = new Person("p2");
console.info(p1.config == p2.config); //false
console.info(p1.hello == p2.hello); //false
console.info(p1.say === p2.say); //true
p1.say("qq");
p2.say("qq");
console.info(p1.version === p2.version); //true
console.info(p1.version);
该函数创建实例时原型图如下:
- 示例三
function Person(name) {
this.name = name;
this.config = {
a: "1",
b: "2",
};
this.hello = function () {
console.info("hello");
};
}
//此方式会重写prototype,造成constructor丢失,变为Object()
Person.prototype = {
version: 1.0,
say: function (arg) {
console.info(`${this.name} say ${arg}`);
},
};
function PersonA(name) {
Person.call(this, name);
}
PersonA.prototype = Person.prototype;
function PersonB(name) {
Person.call(this, name);
}
PersonB.prototype = Person.prototype;
var pA = new PersonA("pa");
var pB = new PersonB("pb");
console.info(pA.config == pB.config); //false 内部属性比较
console.info(pA.hello == pB.hello); //false 内部属性比较
console.info(pA.say === pB.say); //true 原型方法共享
pA.say("qq");
pB.say("qq");
console.info(pA.version === pB.version); //true 原型属性共享
console.info(pA.version); //1.0
Person.prototype.version = 2.0; //修改原型共享属性
console.info(pB.version); //2.0
console.info(new Person().version); //2.0
//修改原型共享方法
PersonB.prototype.say = function (arg) {
console.info(`v2--- ${this.name} say ${arg}`);
};
pB.say("qq");
new Person("Person").say("ww");
总结
js 在创建对象比较消耗内存、耗时长,可以通过减少内部属性创建的方式降低内存占用。
而原型模式就是使用 javascript 语言的原型特性进行相同属性的共享,从而达到降低内存占用、提高对象创建效率。
观察者模式
观察者模式用于模块、组件之间通讯,通过提供统一的模式进行事件订阅、事件发布。从而达到模块、组件之间解耦,提高代码的可维护性。
模块之间、组件之间通讯方式
模块之间、组件之间采用直接引用通讯方式
const moduleA = {
say: function (msg) {
console.info("A say " + msg);
},
letBrun: function () {
//直接引用了moduleB
moduleB.run();
},
};
const moduleB = {
run: function () {
console.info("B run ");
},
letAsay: function () {
//直接引用了moduleA
moduleA.say("hello");
},
};
moduleA.letBrun(); //B Run
moduleB.letAsay(); //A say hello
模块之间、组件之间采用父组件通讯方式
const moduleA = {
say: function (msg) {
console.info("A say " + msg);
},
};
const moduleB = {
run: function () {
console.info("B run ");
},
};
const parentModule = {
moduleA,
moduleB,
letBrun: function () {
this.moduleB.run();
},
letAsay: function () {
this.moduleA.say("hello");
},
};
parentModule.letBrun(); //B Run
parentModule.letAsay(); //A say hello
事件模块实现通讯
function Emitter() {
this.events = {};
this.res_oldAction = {}
this.res_action_events = {}
}
//订阅资源
Emitter.prototype.subscribe = function (res, action, fn) {
if(!this.res_oldAction[res.name]){
this.res_oldAction[res.name] = res[action]
res[action] = (data) => {
this.res_oldAction[res.name](data)
const fns = this.res_action_events[res.name].action;
for (let i = 0; i < fns.length; i++) {
fns[i](data);
}
}
}
if(!this.res_action_events[res.name]){
this.res_action_events[res.name] = {}
}
if(!this.res_action_events[res.name][action]){
this.res_action_events[res.name][action] = []
}
this.res_action_events[res.name].action.push(fn)
}
//取消订阅资源
Emitter.prototype.unsubscribe = function (res, action, fn) {
const fns = this.res_action_events[res.name].action;
for (let i = 0; i < fns.length; i++) {
if (fns[i] === fn) {
fns.splice(i, 1);
i--;
}
}
}
Emitter.prototype.on = function (name, fn) {
if (!this.events[name]) {
this.events[name] = [];
}
this.events[name].push(fn);
};
Emitter.prototype.remove = function (name, fn) {
if (!this.events[name]) {
return;
}
const fns = this.events[name];
for (let i = 0; i < fns.length; i++) {
if (fns[i] === fn) {
fns.splice(i, 1);
i--;
}
}
};
Emitter.prototype.fire = function (name, data) {
if (!this.events[name]) {
return;
}
const fns = this.events[name];
for (let i = 0; i < fns.length; i++) {
fns[i](data);
}
};
const emitter = new Emitter();
//模块A中注册事件
const methodA = (data) => {
console.info("模块A接受到food消息:");
console.info(data);
};
emitter.on("food", methodA);
//模块B中注册事件
const methodB = (data) => {
console.info("模块B接受到food消息:");
console.info(data);
};
emitter.on("food", methodB);
//模块C中触发事件
emitter.fire("food", "饭来了");
//模块B中移除事件
emitter.remove("food", methodB);
//模块C中再次触发事件
emitter.fire("food", "饭又来了");
执行结果如下:
模块 A 接受到 food 消息:
饭来了
模块 B 接受到 food 消息:
饭来了
模块 A 接受到 food 消息:
饭又来了
总结
js 组件模块的通讯方式一般分为3种(直接通讯、通过父组件通讯、通过事件模块通讯)。观察者模式用于模块、组件之间通讯,通过提供统一的模式进行事件订阅、事件发布,从而达到模块、组件之间解耦,提高代码的可维护性
Javascript设计模式之原型模式、发布订阅模式的更多相关文章
- 理解JavaScript设计模式与开发应用中发布-订阅模式的最终版代码
最近拜读了曾探所著的<JavaScript设计模式与开发应用>一书,在读到发布-订阅模式一章时,作者不仅给出了基本模式的通用版本的发布-订阅模式的代码,最后还做出了扩展,给该模式增加了离线 ...
- js 设计模式:观察者和发布订阅模式
总是把这两个当作同一个模式,但其实是不太一样的,现在重温一下. 观察者模式 观察者直接订阅目标,当目标触发事件时,通知观察者进行更新 简单实现 class Observer { constructor ...
- 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_8.RabbitMQ研究-工作模式-发布订阅模式-生产者
Publish/subscribe:发布订阅模式 发布订阅模式: 1.每个消费者监听自己的队列. 2.生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将 ...
- javascript设计模式学习之八_发布订阅(观察者)模式
一.发布订阅模式定义 jQuery中的callbacks,defered,promise本质上就是发布订阅模式的实现.ES6的promise内部实现未开源,不了解具体机制 发布订阅模式又叫做观察者模式 ...
- JS设计模式(5)发布订阅模式
什么是发布订阅模式(观察者模式)? 定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 主要解决:一个对象状态改变给其他对象通知的问题,而且 ...
- 4.js模式-发布-订阅模式
1. 发布-订阅模式 var observe = (function(){ var events = {}, listen, trigger, remmove; listen = function(k ...
- RabbitMQ六种队列模式-发布订阅模式
前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅 [本文]RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...
- 阶段5 3.微服务项目【学成在线】_day05 消息中间件RabbitMQ_9.RabbitMQ研究-工作模式-发布订阅模式-消费者
消费者需要写两个消费者 定义邮件的类 复制以前的代码到邮件类里面进行修改 最上面 声明队列的名称和交换机的名称 监听修改为email 的队列的名称 手机短信接收端 复制一份email的接收端的代码 改 ...
- java设计模式之-观察者模式(发布-订阅模式)
1.观察者模式定义 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象. 这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己. 2.观察者模式结构 ...
- java 观察这模式(发布订阅模式)
观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新. 发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息. 抽象 ...
随机推荐
- 高德Web开发入门之一
高德Web开发 一.地图开发阐述 1)不管是高德地图的Web开发使用,亦或是百度地图的应用开发,都可以直接百度"高德地图/百度地图",进入地图首页下边"开放平台" ...
- springboot中添加事务注解
1.首先在service层中的方法前添加@Transactional @Service public class UserService { @Autowired private UserMapper ...
- WPF---数据绑定之ValidationRule数据校验综合Demo(七)
一.概述 我们利用ValidationRule以及ErrorTemplate来制作一个简单的表单验证. 二.Demo 核心思想:我们在ValidationRule中的Validate函数中进行验证, ...
- Swagger2常用注解解析(轻松构建Swagger)
Swagger2常用注解解析 一.SpringBoot集成Swagger2 二.常用注解解析 具体使用举例说明: 一.SpringBoot集成Swagger2 引入相关jar包 <!-- swa ...
- springmvc框架(Spring SpringMVC, Hibernate整合)
直接干货 model 考虑给用户展示什么.关注支撑业务的信息构成.构建成模型. control 调用业务逻辑产生合适的数据以及传递数据给视图用于呈献: view怎样对数据进行布局,以一种优美的方式展示 ...
- SSM:Mybatis中引入通用mapper
如果你是SSM项目引入通用mapper记得要引入hibernate中的一个hibernate-jpa-2.1-api-1.0.0.Final.jar包(注意必须要Mybatis整合Spring噢,其实 ...
- promise加载图片
实现一个图片的加载:设置第一张图片加载1s之后加载第二张图片: <!DOCTYPE html> <html> <head> <meta charset=&qu ...
- Linux下修改mysql默认最大连接数
liunx下修改mysql最大连接数(Centos下测试通过)1.查看当前系统下mysql设置的最大连接数方式一.mysqladmin -uroot -p variables |grep max_co ...
- TDSQL-A与CK的对比
CK介绍 CK是目前社区里面比较热门的,应用场景也比较广泛. 首先,在架构上,集群内划分为多个分片,通过分片的线性扩展能力,支持海量数据的分布式存储计算,每个分片内包含一定数量的节点Node,即进程, ...
- MySQL主从不同步、数据不一致解决办法
第一种:通过sql_slave_skip_counter跳过同步错误,适用于一般异常如插入时主键冲突 这种情况一般是在从库进行了写操作,错误提示 Last_SQL_Errno: 1062 Last_S ...