代理模式
場景:小明送花記
小明喜歡一群漂亮的女神MM*,所以開始了瘋狂的送花行為,開始他自己去送花,發現被別人發現了會影響后面的追求其他女神,所以小明踏上了找代理送花的這條不歸路
初識代理
- 小明追MM送花,直接送
- 小明選擇MM的好朋友(小明同桌)送花
let Flower = function(flowerName) {
this.flowerName = flowerName
}
let XiaoMing = {
sendFlower : function (target){
let flower = new Flower("牡丹");
target.receiveFlower(flower);
}
}
const MM = {
receiveFlower : function (flower){
console.log("MM收到一束花: " + flower.flowerName)
}
}
const Frient = {
receiveFlower : function(flower){
MM.receiveFlower(flower);
}
}
XiaoMing.sendFlower(MM)
XiaoMing.sendFlower(Frient)
你會發現結果是一樣的,所以這個代理有什么用呢???效果都一樣嘛!!!會要轉手,多麻煩!!!
別著急,繼續看下去就知道了
初見代理作用
- 小明上次失敗了,他覺得是可能是MM心情不好,所以拒絕了他
- 吸取上次的教訓,這次花了多一點錢,找了一個靠譜的代理,朋友2,希望她能在MM2心情好的時候送出花花
let MM2 = {
receiveFlower : function(flower){
console.log("MM2收到一束:" + flower.flowerName)
},
listenGood: function(fn){
// 假設1秒后心情變得特別好
setTimeout(() => {
fn();
}, 1000);
}
}
let Frient2 = {
receiveFlower:function(flower){
MM2.listenGood(() => {
MM2.receiveFlower(flower);
});
}
}
XiaoMing.sendFlower(Frient2)
這里可以看出,代理的作用還是很大的,能決定事件觸發執行時間(這里更好的是時機)
代理 - 保護模式
- 小明表白失敗了,他覺得是自己買錯花了,表白怎么能用牡丹呢?于是買了一束玫瑰準備繼續表白
- 找到了第三個MM3,但是這個MM3的朋友知道小明前面的事跡
- MM3的朋友覺得小明太渣了,直接拒絕了幫忙送花的事
XiaoMing = {
sendFlower : function (target){
let flower = new Flower("玫瑰");
target.receiveFlower("小明", flower);
}
}
let MM3 = {
receiveFlower : function(flower){
console.log("MM3收到一束:" + flower.flowerName)
}
}
let Friend3 = {
receiveFlower: function(name , flower){
if(name === "小明"){
console.log(name + ",你不配給我替你送花")
return;
}
MM3.receiveFlower(flower);
}
}
XiaoMing.sendFlower(Friend3);
這里可以看到我們可以在外設定關卡,如果說是渣渣,我們不讓進入后面部分,這樣可以很好的保護內部
- 小明受不了,“你不幫忙送,怎么不早說”,這接連的失敗,然后就委屈巴巴的哭了,嘴里還念叨著:“這是我一個星期的生活費呀!!!”
- 朋友3:“你以前都沒有問我呀,我咋知道呢!!!”
- 小明:“哦,原來還是我的錯!!!”
- 朋友3看著小明的樣子:“看你這樣子,只要你耐心改過,不這么花心,我可以考慮幫你一回”
- 小明答應了,于是又改變了,小明會提前問朋友3是否愿意送花,在決定買花
XiaoMing = {
sendFlower : function (target){
target.receiveFlower("小明", function(){
return new Flower("玫瑰");
});
}
}
MM3 = {
receiveFlower : function(flower){
console.log("MM3收到一束:" + flower.flowerName)
}
}
Friend3 = {
receiveFlower: function(name , fn){
if(name === "小明"){
console.log(name + ",你還不配給我替你送花")
return;
}
// 有送花的資格了
let flower = fn();
MM3.receiveFlower(flower);
}
}
XiaoMing.sendFlower(Friend3);
上面不難看出,其實我們可以把一些很消耗資源的事情放在我們通過代理后再做,這樣就節省了很多不必要的消耗
代理模式 - 虛擬代理
不使用代理的圖片預加載
var myImageNoProxy = (function(){
var imgNode = document.createElement("img");
document.body.appendChild(imgNode);
var img = new Image;
img.onload = function(){
// 模擬加載程序
setTimeout(() => {
imgNode.src = https://www.cnblogs.com/wangzhaoyv/p/img.src;
}, 1000);
}
return {
setSrc: function(src){
imgNode.src ="../../work/圖片/loadding.jpg";
img.src = https://www.cnblogs.com/wangzhaoyv/p/src;
}
}
}())
myImageNoProxy.setSrc("../../work/圖片/test.png")
使用代理的圖片預加載
let myImage = (function(){
let imgNode = document.createElement("img");
document.body.appendChild(imgNode);
return {
setSrc:function(src) {
imgNode.src = https://www.cnblogs.com/wangzhaoyv/p/src;
}
}
}())
myImage.setSrc("../../work/圖片/test.png")
let proxyMyImage = (function(){
let img = new Image();
img.onload = function(){
// 模擬加載程序
setTimeout(() => {
myImage.setSrc(img.src)
}, 1000);
}
return {
setSrc:function(src){
myImage.setSrc("../../work/圖片/loadding.jpg")
img.src = https://www.cnblogs.com/wangzhaoyv/p/src;
}
}
}())
proxyMyImage.setSrc("../../work/圖片/test.png")
整體來看,其實兩個圖片的預加載都差不多,但是代理模式相對會好一點,每個方法都有自己的作用,后面有部分圖片不需要預加載的時候只需要更換方法,而無需改變方法內部代碼
請求統一上傳
場景
點擊一下復選框就會上傳服務器,但是這樣比較消耗性能,所以更改為點擊的時候先保存在本地,等到不再操作的時候就一起上傳上去
let sendToServer = function(id){
console.log("開始上傳到服務器... id :" + id);
}
var proxySendToServer = (function(){
var cache = [], // 快取一段時間內的id串列
timer = null; // 定時器
return function(id){
// 快取id
cache.push(id);
// 如果上一個timer還在,那么就結束
if(timer){
return;
}
// 否則設定定時器
timer = setTimeout(() => {
// 真正的上傳到服務器
sendToServer(cache.join(","));
clearTimeout(timer)
timer = null;
cache = [];
}, 2000);
}
}())
let checkBoxs = document.getElementsByTagName("input");
for (let index = 0; index < checkBoxs.length; index++) {
const element = checkBoxs[index];
element.onclick = function(){
// 使用代理上傳到服務器
if(this.checked === true){
proxySendToServer(this.id);
}
}
}
代理總結
代理和本體介面的一致性:通過上面的代碼可以看到,我們代理和本體都是暴露了相同的介面,代理接手請求的程序對于用戶來說是透明的,用戶并不清楚代理和本體的區別
-
用戶可以放心請求代理,他只關心是否得到自己想要的結果
-
在任何使用本體的地方都可以直接使用代理替代,反之亦然
代理意義:面向物件中有一個設計原則 ----> 單一職責原則【就是一個類(通常也包括一個物件和函式等)而言,應該僅有一個引起它變化的原因,如果一個物件承擔了多項職責,就意味著這個物件將變得巨大,引起它變化的原因可能有很多個,面向物件設計鼓勵將行為分布到細粒度的物件中,如果一個物件承擔太多職責,等于把這些職責耦合到一起,這種耦合會導致脆弱和低內聚的設計】
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/257040.html
標籤:設計模式
