定义

装饰者模式能够在补改变对象自身的基础上,在程序运行期间给对象动态的添加职责。

当看到装饰者模式的定义的时候,我们想到的js 的三大特性之一--继承,不也能够实现不改变对象自身的基础上,添加动态的职责,也是可以实现的。那为什么还需要装饰者模式呢?在解决这个问题之前,先讲一下继承的概念。

继承

继承可以解决代码复用的问题,让编程更靠近人类的思维。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过继承父类中的属性和方法。

js 实现继承的方式:下面介绍几种常见的继承方式

1.对象冒充 :对象冒充的意思就是获取那个类的所有成员,js调用哪个方法,就获取那个方法的所有。

// 对象冒充
function father(name, age) {
this.name = name
this.age = age
this.show= function() {
console.log('我叫' + this.name , '今年' + this.age)
}
}
function son(name, age) {
this.father = father
this.father(name, age)
this.showSon= function() {
console.log('自己')
}
}
let Son = new son('gmn', )
Son.show() //我叫gmn 今年18

2.原型链继承:将父类的实例作为子类的原型

// 原型链继承
function Father() { }
Father.prototype.name = function(name) {
this.name = name
console.log('name', name)
}
Father.prototype.age = function(age) {
this.age = age
}
function Son() { }
Son.prototype =new Father()
Son.prototype.name('gmn') // gmn

特点:

  1. 非常纯粹的继承关系,实例是子类的实例,也是父类的实例
  2. 父类新增原型方法/原型属性,子类都能访问到
  3. 简单,易于实现

缺点:

  1. 要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中
  2. 无法实现多继承
  3. 来自原型对象的所有属性被所有实例共享
  4. 创建子类实例时,无法向父类构造函数传参

在es6中也有extend 和class 来实现继承。其实,本质也是基于原型机制的。

其实,继承会存在一些缺点:

1.超类子类的强耦合,超类改变导致子类改变

2.超类内部细节对子类可见,破坏了封装性

3.完成功能复用的同时,可能会创造大量子类。

也正是因为继承的缺点,才有了装饰者模式。关于继承的概念就先暂时讲这么多把,言归正传,继续说装饰者模式。

例子:

1.传统面向对象语言的实现方式

// 原始类
var Original = function () {
}; Original.prototype.fire = function () {
console.log('着火了');
}; //装饰类
var MissileDecorator = function (plan) {
this.plan = plan;
} MissileDecorator.prototype.fire = function () {
this.plan.fire();
console.log('真的着火了');
}; var plan = new Original();
plan = new MissileDecorator(plan);
plan.fire();
// 着火了
// 真的着火了

这种方式的实现,室装饰器类要维护目标对象的一个引用,同时还是新啊目标类的所有接口哦。调用方法时,先执行目标对象原有的方法,在执行自行添加的特性。

2.JS基于对象的实现方式

var Original = {
fire: function () {
console.log('着火了');
}
}; var missileDecorator= function () {
console.log('真的着火了');
}; var fire = Original.fire; Original.fire=function () {
fire();
missileDecorator();
}; Original.fire();
//着火了
// 真的着火了

装饰者模式将一个对象嵌入到另一个对象之中,实际上相当于这个对象被另一个对像包装起来,形成一条包装链。请求随着这条包装链依次传递到所有的对象,每个对象都有处理这条请求的机会。

3,使用装饰者模式实现表单校验并提交:装饰着模式分离表单验证和提交的函数

Function.prototype.before=function (beforefn) {
var _this= this; //保存旧函数的引用
return function () { //返回包含旧函数和新函数的“代理”函数
beforefn.apply(this,arguments); //执行新函数,且保证this不被劫持,新函数接受的参数
// 也会被原封不动的传入旧函数,新函数在旧函数之前执行
return _this.apply(this,arguments);
};
}; var validata=function () {
if(username.value===''){
alert('用户名不能为空!')
return false;
}
if(password.value===''){
alert('密码不能为空!')
return false;
}
} var formSubmit=function () {
var param={
username=username.value;
password=password.value;
} ajax('post','http://www.mn.com',param);
} formSubmit= formSubmit.before(validata); submitBtn.onclick=function () {
formSubmit();
}

总结

装饰者模式是为以有功能动态的添加更多功能的一种方式,把每个要装饰的功能放在单独的函数里,然后用该函数包装所有装饰的已有函数对象,因此,当需要执行特殊行为的时候,调用代码就可以根据需要有选择的,按顺序的使用装饰功能来包装对象。优点事把类(函数)的核心职责和装饰功能区分开了

js --装饰者模式的更多相关文章

  1. js装饰者模式

    装饰者模式是为已有的功能动态地添加更多功能的一种方式.当系统需要新功能的时候,是向旧的类中添加新的代码.这些新加的代码通常装饰了原有类的核心职责或主要行为,在主类中加入了新的字段,新的方法和新的逻辑, ...

  2. JS装饰器模式

    装饰器模式:在不改变原对象的基础上,通过对其进行包装拓展(添加属性或者方法),保护原有功能的完整性需要条件:原对象,新内容(属性/方法)个人理解:重新实现一下,原对象的方法,在方法内容,先执行原对象的 ...

  3. 7.js模式-装饰者模式

    1. 装饰者模式 给对象动态增加职责的方式称为装饰者模式. Function.prototype.before = function(beforefn){ var _self = this; retu ...

  4. js设计模式(7)---装饰者模式

    0.前言 下午做事效率很低,无精打采的,整个脑子就跟浆糊一样,看看时间一点点流去,心中只能无可奈何,哎,码农的激情难道就这么容易熄灭吗? 1.该模式的使用情况 假如我们想给对象增加功能,但是又不想修改 ...

  5. js原生设计模式——12装饰者模式

    1.面向对象模式装饰者 <!DOCTYPE html><html lang="en"><head>    <meta charset=&q ...

  6. JS模式--装饰者模式

    在Javascript中动态的给对象添加职责的方式称作装饰者模式. 下面我们通常遇到的例子: var a = function () { alert(1); };//改成: var a = funct ...

  7. JS 设计模式九 -- 装饰器模式

    概念 装饰者(decorator)模式能够在不改变对象自身的基础上,动态的给某个对象添加额外的职责,不会影响原有接口的功能. 模拟传统面向对象语言的装饰者模式 //原始的飞机类 var Plane = ...

  8. JS设计模式(12)装饰者模式

    什么是装饰者模式? 定义:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰器模式相比生成子类更为灵活. 主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且 ...

  9. JS设计模式——12.装饰者模式

    装饰者模式概述 本章讨论的是一种为对象添加特性的技术,她并不使用创建新子类这种手段. 装饰者模式可以用来透明的把对象包装在具有同样接口的另一个对象中.这样一来,就可以给一个方法添加一些行为,然后将方法 ...

随机推荐

  1. 刷题记录:Shrine

    目录 刷题记录:Shrine 刷题记录:Shrine 题目复现链接:https://buuoj.cn/challenges 参考链接:Shrine 解此题总结一下flask的SSTI:CTF SSTI ...

  2. 刷题记录:[CISCN2019 华北赛区 Day1 Web1]Dropbox

    目录 刷题记录:[CISCN2019 华北赛区 Day1 Web1]Dropbox 一.涉及知识点 1.任意文件下载 2.PHAR反序列化RCE 二.解题方法 刷题记录:[CISCN2019 华北赛区 ...

  3. Devops(四):Docker 镜像管理

    参考 <Docker中上传镜像到docker hub中> <Docker 镜像管理> <通过容器提交镜像(docker commit)以及推送镜像(docker push ...

  4. WebGL学习笔记(二):WebGL坐标系及基础几何概念

    WebGL使用的是正交右手坐标系,且每个方向都有可使用的值的区间,超出该矩形区间的图像不会绘制: x轴最左边为-1,最右边为1: y轴最下边为-1,最上边为1: z轴朝向你的方向最大值为1,远离你的方 ...

  5. Java 解析XML数据

    实例一:获取指定两个标签之间的数据 XML数据格式: <?xml version="1.0" encoding="utf-8"?> <soap ...

  6. Java之安装JDK

    因为Java程序必须运行在JVM只是,所以我们第一件事情就是安装JDK 从Oracle官网下载最新稳定版JDK 一,Linux系统CentOS安装JDK 下载rpm安装包 安装 rpm -ivh jd ...

  7. git删除远程.idea目录

    git删除远程.idea目录 1. 登录 Administrator@USER-20180708AB MINGW32 / (master) $ git config --global user.nam ...

  8. hihocoder 1566 皇室成员的名字

    #1566 : 皇室成员的名字 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho正在学习世界历史.他发现历史上很多西方国家的皇室成员的名字都是由英文名字加罗马数字组 ...

  9. typeof与instanceof运算符

    typeof运算符用来判断某个变量的数据类型.typeof()返回值类型有如下几种: 1.number :数值类型 2.string :字符串类型 3.boolean :布尔型 4.function: ...

  10. 【Linux】Linux下进程间的通信方式

    本文内容: 1.进程通信的目的 2.介绍Linux下进程间的4种通信方式:管道,消息队列,共享内存,信号量 ps:套接字也可以用于进程间的通信,不过是不同物理机器上的进程通信,本章讨论是是同一台物理机 ...