引:什么是装饰者模式

在传统的面向对象语言中,给对象添加功能常常使用继承的方式,但是继承的方式并不灵活,还会带来许多问题:一方面会导致超类和子类之间存在强耦合性,当超类改变时,子类也会随之改变;另一方面,继承这种功能复用方式通常被称为“白箱复用”,“白箱”是相对可见性而言的,在继承方式中,超类的内部细节是对子类可见的,继承常常被认为破坏了封装性。

使用继承还会带来另外一个问题,在完成一些功能复用的同时,有可能创建出大量的子类,使子类的数量呈爆炸性增长。比如现在有4种型号的自行车,我们为每种自行车都定义了一个单独的类。现在要给每种自行车都装上前灯、尾灯和铃铛这3种配件。如果使用继承的方式来给每种自行车创建子类,则需要4×3=12个子类。但是如果把前灯、尾灯、铃铛这些对象动态组合到自行车上面,则只需要额外增加3个类。

这种给对象动态地增加职责的方式称为装饰者(decorator)模式。装饰者模式能够在不改变对象自身的基础上,在程序运行期间给对象动态地添加职责。跟继承相比,装饰者是一种更轻便灵活的做法,这是一种“即用即付”的方式,比如天冷了就多穿一件外套,需要飞行时就在头上插一支竹蜻蜓,遇到一堆食尸鬼时就点开AOE(范围攻击)技能。

模拟传统面向对象语言的装饰者模式

首先要提出来的是,作为一门解释执行的语言,给JavaScript中的对象动态添加或者改变职责是一件再简单不过的事情,虽然这种做法改动了对象自身,跟传统定义中的装饰者模式并不一样,但这无疑更符合JavaScript的语言特色。代码如下:

var obj = {name: 'sven',address: '深圳市'
};
obj.address = obj.address + '福田区';

传统面向对象语言中的装饰者模式在JavaScript中适用的场景并不多,如上面代码所示,通常我们并不太介意改动对象自身。尽管如此,但是我们还是稍微模拟一下传统面向对象语言中的装饰者模式实现。

假设我们在编写一个飞机大战的游戏,随着经验值的增加,我们操作的飞机对象可以升级成更厉害的飞机,一开始这些飞机只能发射普通的子弹,升到第二级时可以发射导弹,升到第三级时可以发射原子弹。

// 建立一架飞机
var Plane = function(){}
// 飞机有发射普通子弹的方法
Plane.prototype.fire = function(){console.log( '发射普通子弹' );
}

接下来增加两个装饰类,分别是导弹和原子弹:

var MissileDecorator = function( plane ){this.plane = plane;
}
MissileDecorator.prototype.fire = function(){this.plane.fire();console.log( '发射导弹' );
}
var AtomDecorator = function( plane ){this.plane = plane;
}
AtomDecorator.prototype.fire = function(){this.plane.fire();console.log( '发射原子弹' );
}

导弹类和原子弹类的构造函数都接受参数plane对象,并且保存好这个参数,在它们的fire方法中,除了执行自身的操作之外,还调用plane对象的fire方法。

这种给对象动态增加职责的方式,并没有真正地改动对象自身,而是将对象放入另一个对象之中,这些对象以一条链的方式进行引用,形成一个聚合对象。这些对象都拥有相同的接口(fire方法),当请求达到链中的某个对象时,这个对象会执行自身的操作,随后把请求转发给链中的下一个对象。

因为装饰者对象和它所装饰的对象拥有一致的接口,所以它们对使用该对象的客户来说是透明的,被装饰的对象也并不需要了解它曾经被装饰过,这种透明性使得我们可以递归地嵌套任意多个装饰者对象,如图所示。

最后看看测试结果:

var plane = new Plane();
plane = new MissileDecorator( plane );
plane = new AtomDecorator( plane );
plane.fire();
// 分别输出: 发射普通子弹、发射导弹、发射原子弹

回到JavaScript的装饰者

JavaScript语言动态改变对象相当容易,我们可以直接改写对象或者对象的某个方法,并不需要使用“类”来实现装饰者模式,代码如下:

var plane = {fire: function(){console.log( '发射普通子弹' );}
}
var missileDecorator = function(){console.log( '发射导弹' );
}
var atomDecorator = function(){console.log( '发射原子弹' );
}
var fire1 = plane.fire;
plane.fire = function(){fire1();missileDecorator();
}
var fire2 = plane.fire;
plane.fire = function(){fire2();atomDecorator();
}
plane.fire();
// 分别输出: 发射普通子弹、发射导弹、发射原子弹

装饰函数

在JavaScript中,几乎一切都是对象,其中函数又被称为一等对象。在平时的开发工作中,也许大部分时间都在和函数打交道。在JavaScript中可以很方便地给某个对象扩展属性和方法,但却很难在不改动某个函数源代码的情况下,给该函数添加一些额外的功能。在代码的运行期间,我们很难切入某个函数的执行环境。

要想为函数添加一些功能,最简单粗暴的方式就是直接改写该函数,但这是最差的办法,直接违反了开放-封闭原则:

var a = function(){alert (1);
}
// 改成:
var a = function(){alert (1);alert (2);
}

很多时候我们不想去碰原函数,也许原函数是由其他同事编写的,里面的实现非常杂乱。甚至在一个古老的项目中,这个函数的源代码被隐藏在一个我们不愿碰触的阴暗角落里。现在需要一个办法,在不改变函数源代码的情况下,能给函数增加功能,这正是开放-封闭原则给我们指出的光明道路。

通过保存原引用的方式就可以改写某个函数:

var a = function(){alert (1);
}
var _a = a;
a = function(){_a();alert (2);
}
a();

这是实际开发中很常见的一种做法,比如我们想给window绑定onload事件,但是又不确定这个事件是不是已经被其他人绑定过,为了避免覆盖掉之前的window.onload函数中的行为,我们一般都会先保存好原先的window.onload,把它放入新的window.onload里执行:

window.onload = function(){alert (1);
}
var _onload = window.onload || function(){};
window.onload = function(){_onload();alert (2);
}

这样的代码当然是符合开放-封闭原则的,我们在增加新功能的时候,确实没有修改原来的window.onload代码,但是这种方式存在以下两个问题。

  • 必须维护_onload这个中间变量,虽然看起来并不起眼,但如果函数的装饰链较长,或者需要装饰的函数变多,这些中间变量的数量也会越来越多。
  • 其实还遇到了this被劫持的问题,在window.onload的例子中没有这个烦恼,是因为调用普通函数_onload时,this也指向window,跟调用window.onload时一样(函数作为对象的方法被调用时,this指向该对象,所以此处this也只指向window)。现在把window.onload换成document.getElementById,代码如下:
var _getElementById = document.getElementById;
document.getElementById = function( id ){alert (1);return _getElementById( id ); // (1)
}
var button = document.getElementById( 'button' );
</script>

执行这段代码,我们看到在弹出alert(1)之后,紧接着控制台抛出了异常:

// 输出: Uncaught TypeError: Illegal invocation

异常发生在(1) 处的_getElementById(id)这句代码上,此时_getElementById是一个全局函数,当调用一个全局函数时,this是指向window的,而document.getElementById方法的内部实现需要使用this引用,this在这个方法内预期是指向document,而不
是window, 这是错误发生的原因,所以使用现在的方式给函数增加功能并不保险。

改进后的代码可以满足需求,我们要手动把document当作上下文this传入_getElementById:

<html><button id="button"></button>
<script>var _getElementById = document.getElementById;document.getElementById = function(){alert (1);return _getElementById.apply( document, arguments );}var button = document.getElementById( 'button' );
</script>
</html>

但这样做显然很不方便,下面我们引入AOP,来提供一种完美的方法给函数动态增加功能。

用AOP装饰函数

首先给出Function.prototype.before方法和Function.prototype.after方法:

Function.prototype.before = function( beforefn ){var __self = this; // 保存原函数的引用return function(){ // 返回包含了原函数和新函数的"代理"函数beforefn.apply( this, arguments ); // 执行新函数,且保证this不被劫持,新函数接受的参数// 也会被原封不动地传入原函数,新函数在原函数之前执行return __self.apply( this, arguments ); // 执行原函数并返回原函数的执行结果,// 并且保证this不被劫持}
}
Function.prototype.after = function( afterfn ){var __self = this;return function(){var ret = __self.apply( this, arguments );afterfn.apply( this, arguments );return ret;}
};

Function.prototype.before接受一个函数当作参数,这个函数即为新添加的函数,它装载了新添加的功能代码。

接下来把当前的this保存起来,这个this指向原函数,然后返回一个“代理”函数,这个“代理”函数只是结构上像代理而已,并不承担代理的职责(比如控制对象的访问等)。它的工作是把请求分别转发给新添加的函数和原函数,且负责保证它们的执行顺序,让新添加的函数在原函数之前执行(前置装饰),这样就实现了动态装饰的效果。

我们注意到,通过Function.prototype.apply来动态传入正确的this,保证了函数在被装饰之后,this不会被劫持。

Function.prototype.after的原理跟Function.prototype.before一模一样,唯一不同的地方在于让新添加的函数在原函数执行之后再执行。

下面来试试用Function.prototype.before的威力:

<html>
<button id="button"></button>
<script>Function.prototype.before = function( beforefn ){var __self = this;return function(){beforefn.apply( this, arguments );return __self.apply( this, arguments );}}document.getElementById = document.getElementById.before(function(){alert (1);});var button = document.getElementById( 'button' );console.log( button );
</script>
</html>

再回到window.onload的例子,看看用Function.prototype.after来增加新的window.onload事件是多么简单:

window.onload = function(){alert (1);
}
window.onload = ( window.onload || function(){} ).after(function(){alert (2);
}).after(function(){alert (3);
}).after(function(){alert (4);
});

值得提到的是,上面的AOP实现是在Function.prototype上添加before和after方法,但许多人不喜欢这种污染原型的方式,那么我
们可以做一些变通,把原函数和新函数都作为参数传入before或者after方法:

var before = function( fn, beforefn ){return function(){beforefn.apply( this, arguments );return fn.apply( this, arguments );}
}
var a = before(function(){alert (3)},function(){alert (2)}
);
a = before( a, function(){alert (1);} );
a();

AOP的应用实例

用AOP装饰函数的技巧在实际开发中非常有用。不论是业务代码的编写,还是在框架层面,我们都可以把行为依照职责分成粒度更细的函数,随后通过装饰把它们合并到一起,这有助于我们编写一个松耦合和高复用性的系统。

这一节将介绍几个例子,带大家进一步理解装饰函数的威力。

数据统计上报

分离业务代码和数据统计代码,无论在什么语言中,都是AOP的经典应用之一。在项目开发的结尾阶段难免要加上很多统计数据的代码,这些过程可能让我们被迫改动早已封装好的函数。

比如页面中有一个登录button,点击这个button会弹出登录浮层,与此同时要进行数据上报,来统计有多少用户点击了这个登录button:

<html>
<button tag="login" id="button">点击打开登录浮层</button>
<script>
var showLogin = function(){console.log( '打开登录浮层' );log( this.getAttribute( 'tag' ) );
}
var log = function( tag ){console.log( '上报标签为: ' + tag );// (new Image).src = 'http:// xxx.com/report?tag=' + tag; // 真正的上报代码略
}
document.getElementById( 'button' ).onclick = showLogin;
</script>
</html>

我们看到在showLogin函数里,既要负责打开登录浮层,又要负责数据上报,这是两个层面的功能,在此处却被耦合在一个函数里。使用AOP分离之后,代码如下:

<html>
<button tag="login" id="button">点击打开登录浮层</button>
<script>
Function.prototype.after = function( afterfn ){var __self = this;return function(){var ret = __self.apply( this, arguments );afterfn.apply( this, arguments );return ret;}
};
var showLogin = function(){console.log( '打开登录浮层' );
}
var log = function(){console.log( '上报标签为: ' + this.getAttribute( 'tag' ) );
}
showLogin = showLogin.after( log ); // 打开登录浮层之后上报数据
document.getElementById( 'button' ).onclick = showLogin;
</script>
</html>

用AOP动态改变函数的参数

观察Function.prototype.before方法:

Function.prototype.before = function( beforefn ){var __self = this;return function(){beforefn.apply( this, arguments ); // (1)return __self.apply( this, arguments ); // (2)}
}

从这段代码的(1)处和(2)处可以看到,beforefn和原函数__self共用一组参数列表arguments,当我们在beforefn的函数体内改变
arguments的时候,原函数__self接收的参数列表自然也会变化。

下面的例子展示了如何通过Function.prototype.before方法给函数func的参数param动态地添加属性b:

var func = function( param ){console.log( param ); // 输出: {a: "a", b: "b"}
}
func = func.before( function( param ){param.b = 'b';
});
func( {a: 'a'} );

现在有一个用于发起ajax请求的函数,这个函数负责项目中所有的ajax异步请求:

var ajax = function( type, url, param ){console.dir(param);// 发送ajax请求的代码略
};
ajax( 'get', 'http:// xxx.com/userinfo', { name: 'sven' } );

上面的伪代码表示向后台cgi发起一个请求来获取用户信息,传递给cgi的参数是{ name: ‘sven’ }。

ajax函数在项目中一直运转良好,跟cgi的合作也很愉快。直到有一天,我们的网站遭受了CSRF攻击。解决CSRF攻击最简单的一个办法就是在HTTP请求中带上一个Token参数。

假设我们已经有一个用于生成Token的函数

var getToken = function(){return 'Token';
}

现在的任务是给每个ajax请求都加上Token参数:

var ajax = function( type, url, param ){param = param || {};Param.Token = getToken(); // 发送ajax请求的代码略...
};

虽然已经解决了问题,但我们的ajax函数相对变得僵硬了,每个从ajax函数里发出的请求都自动带上了Token参数,虽然在现在的项目中没有什么问题,但如果将来把这个函数移植到其他项目上,或者把它放到一个开源库中供其他人使用,Token参数都将是多余的。

也许另一个项目不需要验证Token,或者是Token的生成方式不同,无论是哪种情况,都必须重新修改ajax函数。

为了解决这个问题,先把ajax函数还原成一个干净的函数:

var ajax= function( type, url, param ){console.log(param); // 发送ajax请求的代码略
};

然后把Token参数通过Function.prototyte.before装饰到ajax函数的参数param对象中:

var getToken = function(){return 'Token';
}
ajax = ajax.before(function( type, url, param ){param.Token = getToken();
});
ajax( 'get', 'http:// xxx.com/userinfo', { name: 'sven' } );

从ajax函数打印的log可以看到,Token参数已经被附加到了ajax请求的参数中:

{name: "sven", Token: "Token"}

明显可以看到,用AOP的方式给ajax函数动态装饰上Token参数,保证了ajax函数是一个相对纯净的函数,提高了ajax函数的可复用性,它在被迁往其他项目的时候,不需要做任何修改。

区分装饰者模式和代理模式

装饰者模式和代理模式的结构看起来非常相像,这两种模式都描述了怎样为对象提供一定程度上的间接引用,它们的实现部分都保留了对另外一个对象的引用,并且向那个对象发送请求。

代理模式和装饰者模式最重要的区别在于它们的意图和设计目的。代理模式的目的是,当直接访问本体不方便或者不符合需要时,为这个本体提供一个替代者。本体定义了关键功能,而代理提供或拒绝对它的访问,或者在访问本体之前做一些额外的事情。装饰者模式的作用就是为对象动态加入行为。换句话说,代理模式强调一种关系(Proxy与它的实体之间的关系),这种关系可以静态的表达,也就是说,这种关系在一开始就可以被确定。而装饰者模式用于一开始不能确定对象的全部功能时。代理模式通常只有一层代理-本体的引用,而装饰者模式经常会形成一条长长的装饰链。

在虚拟代理实现图片预加载的例子中,本体负责设置img节点的src,代理则提供了预加载的功能,这看起来也是“加入行为”的一种方式,但这种加入行为的方式和装饰者模式的偏重点是不一样的。装饰者模式是实实在在的为对象增加新的职责和行为,而代理做的事情还是跟本体一样,最终都是设置src。但代理可以加入一些“聪明”的功能,比如在图片真正加载好之前,先使用一张占位的loading图片反馈给客户。

结语

通过数据上报、统计函数的执行时间、动态改变函数参数例子,我们了解了装饰函数,它是JavaScript中独特的装饰者模式。这种模式在实际开发中非常有用,除了上面提到的例子,它在框架开发中也十分有用。作为框架作者,我们希望框架里的函数提供的是一些稳定而方便移植的功能,那些个性化的功能可以在框架之外动态装饰上去,这可以避免为了让框架拥有更多的功能,而去使用
一些if、else语句预测用户的实际需要。

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

相关文章

  1. eclipse adt sdk jdk的关系

    开始搭建android开发环境,按照网上的文章下载相关的工具.但是一直不知道都是干嘛用的.今天整理一下.有个系统的认识.记录一下 eclipse就是个代码编辑器,和记事本差不多. adt是里面的一个插件,eclipse安装后可以增加一些按钮.来管理android sdk.可以离线安装.注意去掉contact al…...

    2024/4/14 16:06:52
  2. Qt精美控件

    QT属性控件项目https://github.com/lexxmark/QtnProperty 比特币交易软件https://github.com/JulyIGHOR/QtBitcoinTrader 导航控件http://qt-apps.org/content/show.php/NavBar?content=162885 虚拟键盘http://qt-apps.org/content/show.php/VirtualKeyboard?content=107388 …...

    2024/4/15 9:05:38
  3. JavaScript 设计模式之迭代器模式

    什么是迭代器模式? 迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。 jQuery中的迭代器…...

    2024/3/14 20:00:00
  4. Yolov4论文翻译与解析(一)

    前言 时隔两年之后,伴着Yolo原作者Redmon在twitter正式宣布退出cv界,大家都以为yolo系列已经终结的时候,Yolov4横空出世,虽然作者已经大换血,但论文中给出的测试结果依然保留yolo系列的血统:保持相对较高的mAP的同时,大大降低计算量,可谓是学术成果在工业应用的典范,至…...

    2024/4/14 16:07:07
  5. ADT eclipse maven plugin 插件 安装 和 配置

    开发手机端用ADT集成好的环境,但是有时候也需要接触后台 ADT默认没有maven插件 经过一番查找 找到这篇文章解决问题 maven3 安装:安装 Maven 之前要求先确定你的 JDK 已经安装配置完成。Maven是 Apache 下的一个项目,目前最新版本是 3.0.4,我用的也是这个。首先去官网下载…...

    2024/4/14 16:06:52
  6. JavaScript 设计模式之发布-订阅模式(上)

    什么是发布订阅模式? 发布—订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。在JavaScript开发中,我们一般用事件模型来替代传统的发布—订阅模式。 发布订阅模式的构成 最常见的发布订阅模式就是…...

    2024/4/14 16:07:22
  7. EMC 电磁兼容知识简易解析

    EMC基础知识 电磁兼容性 EMC (Electromagnetic Compatibility ) 设备在共同的电磁环境中能一起执行各自功能的共存状态,即该设备不会由于受到处于同一电磁环境中其他设备的电磁发射导致不允许的降级;也不会使同一电磁环境中其他设备因受其电磁发射而导致不允许的降级。 一、…...

    2024/3/13 21:09:06
  8. Android studio导入eclipse(ADT)项目

    具体操作步骤1、在adt的标题栏中选择File——Export2、 选择Genrete Gradle build files,点击“Next >”3、之后只要一直点next或finish就可以了。但要注意的是其实有一个界面如下图所示 这里是选择要转换的项目。如果有依赖的项目也一并选择。4、对比一下前后两个项目目录…...

    2024/4/14 16:07:22
  9. C#时钟控件

    多年前写的时钟控件,发布出来,供大家参考。先看效果:首先,制作一个从UserControl继承的时钟控件,使用双缓冲绘制。由于是几年前的水平,一些代码写到了属性中,也懒得再改了,感兴趣的,可以改得更规范些。//ClockControl.csusing System;using System.Drawing;using Syst…...

    2024/4/14 16:07:22
  10. JavaScript 设计模式之组合模式

    引 我们知道地球和一些其他行星围绕着太阳旋转,也知道在一个原子中,有许多电子围绕着原子核旋转。我曾经想象,我们的太阳系也许是一个更大世界里的一个原子,地球只是围绕着太阳原子的一个电子。而我身上的每个原子又是一个星系,原子核就是这个星系中的恒星,电子是围绕着恒…...

    2024/4/14 16:07:02
  11. Eclipse、SDK、ADT资源下载

    刚学Android的时候光是配置SDK和ADT就用了好长时间,遇到了 1、Eclipse的32位和64位的问题 2、ADT版本过低的问题 3、找不到合适的SDK问题 4、下载SDK太慢的问题 5、配置java环境变量的问题 6、。。。。。 这些问题现在,学了快有一年的Android了,期间积累了一些不同版本的Ecl…...

    2024/4/14 16:07:22
  12. sql*plus

    主要功能:1. 数据库的维护,如启动,关闭等,这一般在服务器上操作。2. 执行sql语句执行pl/sql。3. 执行sql脚本。4. 数据的导出,报表。5. 应用程序开发、测试sql/plsql。6. 生成新的sql脚本。7. 供应用程序调用,如安装程序中进行脚本的安装。8. 用户管理及权限维护等。常用…...

    2024/4/15 22:01:35
  13. 关于eclipse adt更新的问题

    今早刚一开机,打开eclipse ,提示什么adt版本过低,提示我更新,但我不想更新,打算原来的版本,在这里写下方法,便于以后使用windows 下面安装Android虚拟机,有时候选择更新SDK后,在Eclipsepreference里指向android_sdk_windows_x86时。会出现诸如This AndroidSDK require…...

    2024/4/14 16:07:17
  14. JavaScript 设计模式之代理模式

    什么是代理模式? 首先我们先看一个有趣的例子 在四月一个晴朗的早晨,小明遇见了他的百分百女孩,我们暂且称呼小明的女神为A。两天之后,小明决定给A送一束花来表白。刚好小明打听到A和他有一个共同的朋友B,于是内向的小明决定让B来代替自己完成送花这件事情。虽然小明的故事…...

    2024/4/14 16:07:07
  15. c#中datagrid控件的基本使用

    c#中datagrid控件的基本使用datagrid控件的作用简单点说就是将表格显示出来,用的多的是直接链接数据库文件,也可以自己见一个表格对象,链接到datagrid控件,下面是一个简单的例子DataTable dt = new DataTable();//新建列DataColumn col1 = new DataColumn("设备名&quo…...

    2024/4/14 16:07:07
  16. JavaScript设计模式之适配器模式

    引 适配器模式的作用是解决两个软件实体间的接口不兼容的问题。使用适配器模式之后,原本由于接口不兼容而不能工作的两个软件实体可以一起工作。港式插头转换器 适配器的别名是包装器(wrapper),这是一个相对简单的模式。在程序开发中有许多这样的场景:当我们试图调用模块或…...

    2024/4/14 16:07:12
  17. Ubuntu搭建eclipse neon android环境(eclipse ADT)

    安装eclipse neon在官网:https://www.eclipse.org/downloads/ 下载最新neon: 点击“Select Another Mirror”,选择一个China的mirror,点击“Download”即可。解压下载的eclipse-installer,然后双击“eclipse-inst”即可安装。安装ADT由于下载ADT的官网:http://dl-ssl.goo…...

    2024/3/14 20:00:01
  18. eclipse中升级adt到23.0.x版本

    eclipse中旧版本adt为22.6,当升级到23.0.x版本时出现异常,直接在eclipse中进行旧版本的删除时也出现异常,在网上找了诸多方案都行不通(有人说这是adt的22版本到23版本不兼容造成的),心一横,采用重新安装eclipse的方式直接将adt手动升到23.0.x版本(如果读者eclipse上组件比…...

    2024/4/16 6:07:11
  19. IE8允许ActiveX控件设置

    IE8允许ActiveX控件设置在IE浏览器菜单栏,找到“Internet选项”,---》“安全”---》“Internet”---》“自定义级别” 找到ActiveX控件相关信息。 其他都改为启用 对未标记为可安全执行脚本的ActiveX控件初始化并执行脚本:提示 下载未签名的ActicveX控件:提示 下载已签名的…...

    2024/4/14 16:07:22
  20. JavaScript 设计模式之策略模式

    什么是策略模式? 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。 使用策略模式计算奖金 很多公司的年终奖是根据员工的工资基数和年底绩效情况来发放的。例 如,绩效为S的人年终奖有4倍工资,绩效为A的人年终奖有3倍工资, 而绩效为B的…...

    2024/4/14 16:07:07

最新文章

  1. RocketMQ 02 功能大纲介绍

    RocketMQ 02 主流的MQ有很多&#xff0c;比如ActiveMQ、RabbitMQ、RocketMQ、Kafka、ZeroMQ等。 之前阿里巴巴也是使用ActiveMQ&#xff0c;随着业务发展&#xff0c;ActiveMQ IO 模块出现瓶颈&#xff0c;后来阿里巴巴 通过一系列优化但是还是不能很好的解决&#xff0c;之后…...

    2024/4/16 14:47:50
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 游戏引擎架构01__引擎架构图

    根据游戏引擎架构预设的引擎架构来构建运行时引擎架构 ​...

    2024/4/16 12:29:49
  4. C# 构建可定时关闭的异步提示弹窗

    C# 构建可定时关闭的异步提示弹窗 引言1、调用接口的实现2、自动定时窗口的实现 引言 我们在最常用最简单的提示弹框莫过于MessageBox.Show( )的方法了&#xff0c;但是使用久了之后&#xff0c;你会发现这个MessageBox并不是万能的&#xff0c;有事后并不想客户去点击&#x…...

    2024/4/16 6:27:38
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/16 14:09:00
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/15 1:05:01
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/15 9:18:15
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/16 1:57:15
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/15 9:17:51
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/15 9:17:44
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/15 13:52:20
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/16 1:58:32
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/15 9:17:27
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/15 9:17:21
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/15 9:17:15
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/15 13:53:08
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/15 9:16:52
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/15 13:53:31
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/15 9:16:39
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/15 9:16:31
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/15 13:54:27
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/15 23:28:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/15 23:28:30
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/15 13:54:53
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57