摘要:實現(xiàn)種設(shè)計模式最近在學(xué)習(xí)面向?qū)ο蟮姆N設(shè)計模式,使用和實現(xiàn)了一遍,但是因為目前大三,還沒有比較正規(guī)的大項目經(jīng)驗,所以學(xué)習(xí)的過程種我覺得如果沒有一定的項目經(jīng)驗的話很難去完全掌控,所以學(xué)習(xí)的過程中只是大致學(xué)習(xí)了每種設(shè)計模式的特點,我覺得在學(xué)習(xí)的過
js實現(xiàn)23種設(shè)計模式最近在學(xué)習(xí)面向?qū)ο蟮?3種設(shè)計模式,使用java 和 javascript 實現(xiàn)了一遍,但是因為目前大三,還沒有比較正規(guī)的大項目經(jīng)驗,所以學(xué)習(xí)的過程種我覺得如果沒有一定的項目經(jīng)驗的話很難去完全掌控,所以學(xué)習(xí)的過程中只是大致學(xué)習(xí)了每種設(shè)計模式的特點,我覺得在學(xué)習(xí)的過程中應(yīng)該自己找場景實現(xiàn),這樣學(xué)習(xí)效果很好,下面是代碼,當(dāng)然僅供參考。下面是代碼:
創(chuàng)建型模式三要素:
同一個實例
類自行創(chuàng)建實例對象
可向整個系統(tǒng)輸出這個實例
分類:
餓漢式( 類加載到實例時創(chuàng)建實例對象)
懶漢式( 第一次使用時才創(chuàng)建實例對象)
代碼示例:懶漢式
// 手機 用來打電話,玩游戲,看電影,且都是同一個手機 // 懶漢式 var Phone = (function () { // 規(guī)定只能使用 Phone.getInstance 獲取實例 var res = function () { throw new Error("Please use Phone.getInstance() to get the object."); }; var has = false; var phone = null; Object.defineProperty(res, "getInstance", { value: function () { if (has) { return phone; } else { has = true; // 調(diào)用時才創(chuàng)建實例 phone = { call () { console.log("打電話"); }, playGame () { console.log("玩游戲"); }, watchMovie () { console.log("看電影"); } } return phone; } }, writable: false, configurable: false, enumerable: false }); return res; }()); var p1 = Phone.getInstance(); var p2 = Phone.getInstance(); var p3 = Phone.getInstance(); p1.call(); p2.playGame(); p3.watchMovie(); console.log(p1 === p2 && p2 === p3);
代碼示例:餓漢式
// 手機 用來打電話,玩游戲,看電影,且都是同一個手機 // 餓漢式 // 規(guī)定只能使用 Phone.getInstance 獲取實例 var Phone = (function () { // 在此創(chuàng)建實例,裝入內(nèi)存時 實例已創(chuàng)建 var phone = { call () { console.log("打電話"); }, playGame () { console.log("玩游戲"); }, watchMovie () { console.log("看電影"); } }; var res = function () { throw new Error("Please use Phone.getInstance() to get the object."); }; Object.defineProperty(res, "getInstance", { value: function () { return phone; }, writable: false, configurable: false, enumerable: false }); return res; }()); var p1 = Phone.getInstance(); var p2 = Phone.getInstance(); var p3 = Phone.getInstance(); p1.call(); p2.playGame(); p3.watchMovie(); console.log(p1 === p2 && p2 === p3); Phone.getInstance = function () { console.log("I am Groot!"); } var p4 = Phone.getInstance(); p4.call();
定義:
定義一個工廠,工廠定義一個方法,該方法可以根據(jù)傳入的參數(shù)去返回某一個類的實例。
代碼示例:
// 根據(jù)參數(shù)決定去實例汽車還是摩托車 // 定義接口 const Vehicle = { run () { console.log(this.name + "跑..."); } } //汽車類 function Car () { this.name = "汽車"; } Car.prototype = Object.assign(Vehicle); //摩托車類 function Moto () { this.name = "摩托車"; } Moto.prototype = Object.assign(Vehicle); // 車庫 const Garage = { chooseVehicle (constructor) { return new constructor(); } }; Object.freeze(Garage); var car = Garage.chooseVehicle(Car); var moto = Garage.chooseVehicle(Moto); car.run(); moto.run();
簡要:
定義一個工廠接口,接口存在一個創(chuàng)建產(chǎn)品類的方法,為每個類創(chuàng)建一個這樣的類工廠。
代碼示例:
// 工廠方法,創(chuàng)建工廠接口,為每個類創(chuàng)建一個工廠 // 定義接口 const Vehicle = { run () { console.log(this.name + "跑..."); } } //汽車類 function Car () { this.name = "汽車"; } Car.prototype = Object.assign(Vehicle); //摩托車類 function Moto () { this.name = "摩托車"; } Moto.prototype = Object.assign(Vehicle); // 汽車車庫 function CarGarage () { this.createVehicle = function () { return new Car(); } Object.freeze(this); } // 摩托車車庫 function MotoGarage () { this.createVehicle = function () { return new Moto(); } Object.freeze(this); } // 測試 var carGarage = new CarGarage(); var motoGarage = new MotoGarage(); var car = carGarage.createVehicle(); var moto = motoGarage.createVehicle(); car.run(); moto.run();
簡要:
對比于工廠方法,抽象工廠可以說是多種產(chǎn)品,每種產(chǎn)品都要用工廠方法實現(xiàn)。
代碼示例:
// 生產(chǎn)槍的工廠 // createGun 生產(chǎn)槍 // ak47 槍工廠,生產(chǎn) ak47 槍 function Ak47GunCompany () { this.createGun = function () { console.log("生產(chǎn) ak47 槍..."); } } // 巴雷特 槍工廠,生產(chǎn) 巴雷特 槍 function BarrettGunCompany () { this.createGun = function () { console.log("生產(chǎn) 巴雷特 槍..."); } } // 生產(chǎn)子彈的工廠 // createBubble 生產(chǎn)子彈 // ak47 子彈工廠,生產(chǎn) ak47 子彈 function Ak47BubbleCompany () { this.createBubble = function () { console.log("生產(chǎn) ak47 子彈..."); } } // 巴雷特 子彈工廠,生產(chǎn) 巴雷特 子彈 function BarrettBubbleCompany () { this.createBubble = function () { console.log("生產(chǎn) 巴雷特 子彈..."); } } // 武器工廠,生產(chǎn)槍和子彈 // createGun 生產(chǎn)槍 // createBubble 生產(chǎn)子彈 // ak47 武器工廠,生產(chǎn) ak47槍 和 ak47 子彈 function Ak47Company () { var ak47GunCompany = new Ak47GunCompany(); var ak47BubbleCompany = new Ak47BubbleCompany(); this.createGun = function () { ak47GunCompany.createGun(); } this.createBubble = function () { ak47BubbleCompany.createBubble(); } } // 巴雷特 武器工廠,生產(chǎn) 巴雷特槍 和 巴雷特子彈 function BarrettCompany () { var barrettGunCompany = new BarrettGunCompany(); var barrettBubbleCompany = new BarrettBubbleCompany(); this.createGun = function () { barrettGunCompany.createGun(); } this.createBubble = function () { barrettBubbleCompany.createBubble(); } } var ak47Company = new Ak47Company(); var barrettCompany = new BarrettCompany(); ak47Company.createGun(); ak47Company.createBubble(); barrettCompany.createGun(); barrettCompany.createBubble();
簡要:
當(dāng)構(gòu)造一個實例的時候,需要執(zhí)行多個步驟才能生成實例,并且每個步驟有多種選擇從而會生成多種實例的時候使用。
代碼示例:
// 適用于 構(gòu)造一個實例對象需要多個步驟,且每個步驟可能不同會導(dǎo)致不同的實例類 /** 果汁制作步驟 * StirFruit() 將水果打碎 * addWater() 加水 */ // 西瓜汁制作步驟 function WatermelonJuiceStep() { this.StirFruit = function () { console.log("將西瓜打碎..."); }; this.addWater = function () { console.log("加水..."); } } // 橙汁制作步驟 function OrangeJuiceStep() { this.StirFruit = function () { console.log("將橙子打碎..."); }; this.addWater = function () { console.log("加水..."); } } /** 果汁生成器 * make() 生成果汁 * getJuice() 獲取制作的果汁 */ // 西瓜汁生成器 function WatermelonJuiceMaker () { var maker = new WatermelonJuiceStep(); this.make = function () { maker.StirFruit(); maker.addWater(); } this.getJuice = function () { return maker; } } // 橙汁生成器 function OrangeJuiceMaker () { var maker = new OrangeJuiceStep(); this.make = function () { maker.StirFruit(); maker.addWater(); } this.getJuice = function () { return maker; } } // 果汁生成器 function JuiceMaker() { var orangeJuiceMaker = new OrangeJuiceMaker(); var watermelonJuiceMaker = new WatermelonJuiceMaker(); this.makeOrangeJuice = function () { orangeJuiceMaker.make(); return orangeJuiceMaker.getJuice(); } this.makeWatermelonJuice = function () { watermelonJuiceMaker.make(); return watermelonJuiceMaker.getJuice(); } } // 使用果汁生成器 var juiceMaker = new JuiceMaker(); var watermelonJuice = juiceMaker.makeWatermelonJuice(); var orangeJuice = juiceMaker.makeOrangeJuice();結(jié)構(gòu)型模式
簡要:
共同繼承同一接口或抽象類,代理類包含被代理類(has-a)
代碼示例:
// 代理模式 // 共同繼承同一接口或抽象類,代理類包含被代理類(has-a) // 場景:幫別人考試 /** 接口(考試人) * test() 參加考試 */ /** 被代理人考試 * */ function testSelf() { this.test = function() { console.log("參加考試,可是我不會."); } } /** 代理人考試 * */ function testOther(self) { this.test = function() { console.log("參加考試,我會."); } } // 測試 var self = new testSelf(); var other = new testOther(self); other.test();
簡要:
將兩個不能一塊工作的接口或者類,通過新建一個類繼承兩者,從而使得可以一起工作
代碼示例:
// 適配器模式 // 將兩個不能一塊工作的接口或者類,通過新建一個類繼承兩者,從而使得可以一起工作 // 比如小米8的方形耳機插口與圓形耳機接頭需要耳機適配器才能工作 /** 手機接口 * access() 提供的接口類型 */ function Mi8() { this.access = function () { console.log("小米8提供方形插口."); } } /** 耳機接頭 * insert() 提供的接頭類型 */ function MiHeadset() { this.insert = function () { console.log("小米耳機提供圓形插頭."); } } // 適配器 需要實現(xiàn) 手機接口與耳機接頭 function HeadsetAdapter() { this.access = function () { console.log("耳機適配器提供圓形插口."); } this.insert = function () { console.log("耳機適配器提供方形插頭."); } } // 測試 var mi8 = new Mi8(); var miHeadset = new MiHeadset(); var headsetAdapter = new HeadsetAdapter(); mi8.access(); headsetAdapter.insert(); headsetAdapter.access(); miHeadset.insert();
簡要:
主要是兩個不同的類有多種種類,通過 has-a 組合方式去進(jìn)行多種類的結(jié)合
示例代碼:
// 橋接模式,主要是兩個不同的類有多種種類,通過 has-a 組合方式去進(jìn)行多種類的結(jié)合 /** 場景: * 鞋子有跑鞋,籃球鞋,鞋子的品牌有李寧,耐克 */ /** 接口:鞋柜 ShoesBar * saleShoes() 出售鞋子 */ /** 繼承鞋柜接口:跑鞋鞋柜 * */ function RunShoesBar() { this.saleShoes = function () { console.log("出售跑鞋."); } } /** 繼承鞋柜接口:籃球鞋鞋柜 * */ function BasketballShoesBar() { this.saleShoes = function () { console.log("出售籃球鞋."); } } /** 抽象類:品牌鞋柜 * shoesBar 繼承 ShoesBar 的鞋柜 * saleShoes 鞋柜 */ /** 品牌鞋柜繼承類:李寧鞋柜 * */ function LiNingShoesBar(shoesBar) { var shoesBar = shoesBar; this.saleShoes = function () { console.log("李寧鞋柜:"); shoesBar.saleShoes(); } } /** 品牌鞋柜繼承類:耐克鞋柜 * */ function NickShoesBar(shoesBar) { var shoesBar = shoesBar; this.saleShoes = function () { console.log("耐克鞋柜:"); shoesBar.saleShoes(); } } // 測試 // 定義一個跑鞋柜 var runShoesBar = new RunShoesBar(); // 定義一個李寧的跑鞋柜 var liningRunShoesBar = new LiNingShoesBar(runShoesBar); liningRunShoesBar.saleShoes(); // 定義一個耐克的跑鞋柜 var nickShoesBar = new NickShoesBar(runShoesBar); nickShoesBar.saleShoes();
簡要:
就是不同層級的兩個類具有極其相似的結(jié)構(gòu),可以只構(gòu)造一個類來表示這兩個類
// 組合模式:就是不同層級的兩個類具有極其相似的結(jié)構(gòu),可以只構(gòu)造一個類來表示這兩個類 // 場景:表示爺爺,爸爸,兒子三代關(guān)系 // 接口:屬于人,都有名字 const Person = { getName() { return this.name; }, setName(name) { this.name = name; }, display () { } } // 爺爺和爸爸都是父親,都有兒子,所以... function Father(name) { this.setName(name); var sons = []; this.add = function (person) { sons.push(person); } this.display = function () { console.log("作為父親:" + this.getName()); sons.forEach((son) => { son.display(); }); } } // 繼承一下 Father.prototype = Person; // 作為兒子,只能是兒子 function Son(name) { this.setName(name); this.display = function () { console.log("作為兒子:" + this.getName()); } } // 繼承以下 Son.prototype = Person; // 測試 var grandfather = new Father("張爺爺"); var father1 = new Father("張伯伯"); var father2 = new Father("張大爺"); var son1 = new Son("張娃子"); var son2 = new Son("張嘎子"); grandfather.add(father1); grandfather.add(father2); father1.add(son1); father2.add(son2); grandfather.display();
簡要:
裝飾模式,基本類和裝飾類共同繼承某個接口或者抽象類,
通過裝飾類包含基本類以及在裝飾類中添加裝飾方法的方式去裝飾基本類
代碼示例:
// 場景:lol 英雄buff, 普通英雄,露露buff,努努buff /** 公共接口:Hero * getBuff() 獲取英雄的 buff */ function NormalHero() { this.getBuff = function () { console.log("初始的英雄,無 buff."); } } // 加露露 buff function LuLuBuffHero(hero) { this.getBuff = function() { hero.getBuff(); console.log("加露露 buff."); } } // 加努努 buff function NuNuBuffHero(hero) { this.getBuff = function () { hero.getBuff(); console.log("加努努 buff."); } } // 測試 var noBuffHero = new NormalHero(); var luluBuffHero = new LuLuBuffHero(noBuffHero); var nunuBuffHero = new NuNuBuffHero(luluBuffHero); nunuBuffHero.getBuff();
簡要:
通過統(tǒng)一的管理類對內(nèi)部類管理,同時暴露接口接收來自外部類的消息
代碼示例:
/** 外觀模式 * 通過統(tǒng)一的管理類對內(nèi)部類管理,同時暴露接口接收來自外部類的消息 */ // 場景描述: 需求人員提出需求,開發(fā)人員進(jìn)行開發(fā),測試人員進(jìn)行測試 // 需求人員不需要通知開發(fā)人員去開發(fā),測試人員去測試 // 只需要告訴小組組長這個需求就可以了 // 開發(fā)人員,負(fù)責(zé)開發(fā)需求 function Developter() { this.develop = function(demand_name) { console.log("開發(fā)人員開發(fā)需求:" + demand_name); } } // 測試人員,負(fù)責(zé)測試需求 function Tester() { this.test = function (demand_name) { console.log("測試人員測試需求:" + demand_name); } } // 技術(shù)部組長,負(fù)責(zé)安排開發(fā)人員開發(fā)和測試人員測試 function Leader() { var developer = new Developter(); var tester = new Tester(); this.processDemand = function (demand_name) { developer.develop(demand_name); tester.test(demand_name); } } // 需求人員,提出需求 function Demander() { var leader = new Leader(); this.demand = function (demand_name) { console.log("提出需求:" + demand_name); leader.processDemand(demand_name); } } // 測試 var demand_name = "開發(fā)一款MOBA游戲."; var demander = new Demander(); demander.demand(demand_name);
簡要:
對于系統(tǒng)中使用的一些對象可以共享使用,那么每次使用時先判斷有沒有,有直接使用,沒有再去創(chuàng)建,節(jié)省內(nèi)存空間
代碼示例:
/** 享元模式 * 對于系統(tǒng)中使用的一些對象可以共享使用,那么每次使用時先判斷有沒有 * 有直接使用,沒有再去創(chuàng)建,節(jié)省內(nèi)存空間 */ // 場景: // 土豪打英雄聯(lián)盟,想用哪個皮膚,就用哪個 // 有皮膚直接使用,沒有就買買買... /** 英雄皮膚類 * name 皮膚名字 * show() 皮膚展示 */ function HeroSkin(name) { console.log("玩家購買了" + name + "皮膚"); this.show = function () { console.log("玩家使用了" + name + "皮膚"); } } /** 玩家以及擁有的皮膚 * useSkin(skinName) 使用皮膚 */ function Player() { var mySkins = {}; this.useSkin = function (skinName) { if (!(skinName in mySkins)) { mySkins[skinName] = new HeroSkin(skinName); } mySkins[skinName].show(); } } // 測試 var player = new Player(); player.useSkin("伊澤瑞爾-未來戰(zhàn)士"); player.useSkin("銳雯-光明使者"); player.useSkin("銳雯-光明使者");行為型模式
簡要:
簡單而言就是定義子類需要做什么,具體做什么交給子類去做
代碼示例(java, 因為 js 沒有抽象方法這些,而且我覺得模板方法主要是固定流程,實現(xiàn)交給子類實現(xiàn))
package actionModel.templateModel; // 模板方法 // 場景:召喚師選擇英雄,皮膚和召喚師技能 // 步驟:選擇英雄 -> 選擇皮膚 -> 選擇召喚師技能1 -> 選擇召喚師技能2 // 角色:召喚師(就是玩家) abstract class Player { private String name; public Player(String name) { this.name = name; } public abstract void chooseHero(); public abstract void chooseSkin(); public abstract void chooseSummonerSkillFirst(); public abstract void chooseSummonerSkillSecond(); public void show() { // 顯示玩家信息 System.out.println(this.name + "的選擇:"); // 顯示選擇的英雄 chooseHero(); // 顯示選擇的皮膚 chooseSkin(); // 顯示選擇的召喚師技能一 chooseSummonerSkillFirst(); // 顯示選擇的召喚師技能二 chooseSummonerSkillSecond(); } } // 玩家小明 class XiaoMing extends Player{ public XiaoMing(){ super("小明"); } @Override public void chooseHero() { System.out.println("英雄:奧拉夫"); } @Override public void chooseSkin() { System.out.println("皮膚:鐵哥們"); } @Override public void chooseSummonerSkillFirst() { System.out.println("召喚師技能一:疾走"); } @Override public void chooseSummonerSkillSecond() { System.out.println("召喚師技能二:閃現(xiàn)"); } } // 玩家小張 class XiaoZhang extends Player { public XiaoZhang() { super("小張"); } @Override public void chooseHero() { System.out.println("英雄:銳雯"); } @Override public void chooseSkin() { System.out.println("皮膚:光明使者"); } @Override public void chooseSummonerSkillFirst() { System.out.println("召喚師技能一:傳送"); } @Override public void chooseSummonerSkillSecond() { System.out.println("召喚師技能二:閃現(xiàn)"); } } public class Test { public static void main(String[] args) { // 測試 Player xiaoming = new XiaoMing(); Player xiaozhang = new XiaoZhang(); xiaoming.show(); xiaozhang.show(); } }
簡要:
簡單來說就是通過中介者進(jìn)行數(shù)據(jù)傳遞,一方提供數(shù)據(jù),一方訂閱數(shù)據(jù)
代碼示例:
// 中介者模式 // 簡單來說就是通過中介者進(jìn)行數(shù)據(jù)傳遞 // 一方提供數(shù)據(jù),一方訂閱數(shù)據(jù) // 場景:使用第三方買二手手機 // 購買者去預(yù)定手機,當(dāng)出售者賣該型號的手機時候通知購買者 /** 購買者構(gòu)造函數(shù) * * @param phoneName 購買人需要的手機 */ function Buyer(phoneName) { this.getPhoneName = function() { return phoneName; } this.callSellerPhone = function(phone) { console.log(`聯(lián)系賣家:${phone}買 ${phoneName}`); } } /** 出售者構(gòu)造函數(shù) * @param phoneName 賣的的手機 * @param phone 賣主聯(lián)系方式 */ function Seller(phoneName, phone) { this.getPhoneName = function() { return phoneName; } this.getPhone = function() { return phone; } } /** 中介者構(gòu)造函數(shù) * */ function Intermediary() { var buyerList = []; var sellerList = []; this.addBuyer = function(buyer) { // 若存在一個合適的賣家,直接通知買主,不添加到列表 for (let i of sellerList) { if (i.getPhoneName() === buyer.getPhoneName()) { buyer.callSellerPhone(i.getPhone()); break; } } buyerList.push(buyer); } this.addSeller = function(seller) { // 若存在一個合適的買家,直接通知買主,不添加到列表 for (let i of buyerList) { if (i.getPhoneName() === seller.getPhoneName()) { i.callSellerPhone(seller.getPhone()); break; } } sellerList.push(seller); } } var intermediary = new Intermediary(); var buyer1 = new Buyer("小米3"); intermediary.addBuyer(buyer1); var buyer2 = new Buyer("小米8"); intermediary.addBuyer(buyer2); var seller1 = new Seller("小米8", "15684175538"); intermediary.addSeller(seller1);
簡要:
使用命令模式可以在擴展調(diào)度中心的時候不修改調(diào)度中心的代碼
代碼示例:
// 命令模式 // 使用命令模式可以在擴展調(diào)度中心的時候不修改調(diào)度中心的代碼 // 場景:玩具遙控汽車 /** 汽車構(gòu)造函數(shù) * */ function ToyCar() { this.goOn = function() { console.log("小車前進(jìn)"); } this.stop = function() { console.log("小車停止"); } this.speedUp = function() { console.log("小車加速"); } } /** 命令接口 CarCommand * car 遙控汽車的實例 * execute() 執(zhí)行命令 */ /** 前進(jìn)的命令 extends CarCommand * @param car 汽車實例 */ function GoOnCommand(car) { this.execute = function() { car.goOn(); } } /** 停止的命令 extends CarCommand * @param car 汽車實例 */ function StopCommand(car) { this.execute = function() { car.stop(); } } /** 加速的命令 extends CarCommand * @param car 汽車實例 */ function SpeedUpCommand(car) { this.execute = function() { car.speedUp(); } } /** 汽車遙控器 * setCarCommand() 設(shè)置命令 * trigger() 觸發(fā)命令 */ function CarControlHandle() { var carCommand = null; this.setCommand = function(newCarCommand) { carCommand = newCarCommand; } this.trigger = function() { carCommand.execute(); } } // 測試 var car = new ToyCar(); var controlHandle = new CarControlHandle(); var goOn = new GoOnCommand(car); controlHandle.setCommand(goOn); controlHandle.trigger(); var stop = new StopCommand(car); controlHandle.setCommand(stop); controlHandle.trigger(); var speedUp = new SpeedUpCommand(car); controlHandle.setCommand(speedUp); controlHandle.trigger();
簡要:
將請求交給一條處理鏈,處理鏈上的有多個處理器處理,當(dāng)處理鏈上某個處理器處理了該請求,返回處理的結(jié)果優(yōu)點是添加刪除處理器時不需要修改內(nèi)部代碼,只需要添加或者刪除即可,符合開閉原則
代碼示例:
// 責(zé)任鏈模式 // 將請求交給一條處理鏈,處理鏈上的有多個處理器處理, // 當(dāng)處理鏈上某個處理器處理了該請求,返回處理的結(jié)果 // 優(yōu)點是添加刪除處理器時不需要修改內(nèi)部代碼,只需要添加或者刪除即可 // 符合開閉原則 // 場景:dnf 玩家刷圖打怪,怪物有普通怪,精英怪,boss /** 怪物抽象類 * nextMonster 下一個怪物 * setNextMonster 設(shè)置下一個怪物 * battle() 和玩家戰(zhàn)斗 * battleSuccess() 戰(zhàn)斗勝利 * battalFail() 戰(zhàn)斗失敗 */ /** 普通怪 * */ function NomalMonster() { var nextMonster = null; this.setNextMonster = function(Monster) { nextMonster = Monster; } this.battle = function(player) { var res = Math.round(Math.random() * 10) % 2 === 0; if (res) { this.battleSuccess(); nextMonster.battle(player); } else { this.battleFail(); } } this.battleSuccess = function() { console.log("打敗了普通怪."); } this.battleFail = function() { console.log("被普通怪打死, 請使用復(fù)活幣"); } } /** 精英怪 * */ function CreamMonster() { var nextMonster = null; this.setNextMonster = function(Monster) { nextMonster = Monster; } this.battle = function(player) { var res = Math.round(Math.random() * 10) % 2 === 0; if (res) { this.battleSuccess(); nextMonster.battle(player); } else { this.battleFail(); } } this.battleSuccess = function() { console.log("打敗了精英怪."); } this.battleFail = function() { console.log("被精英怪打死, 請使用復(fù)活幣"); } } /** Boss怪 * */ function BossMonster() { var nextMonster = null; this.setNextMonster = function(Monster) { nextMonster = Monster; } this.battle = function(player) { var res = Math.round(Math.random() * 10) % 2 === 0; if (res) { this.battleSuccess(); } else { this.battleFail(); } } this.battleSuccess = function() { console.log("打敗了boss怪,通關(guān)成功!"); } this.battleFail = function() { console.log("被boss怪打死, 請使用復(fù)活幣"); } } /** 玩家類 * */ function Player() { } // 測試 var player = new Player(); var nomalMonster = new NomalMonster(); var creamMonster = new CreamMonster(); nomalMonster.setNextMonster(creamMonster); var bossMonster = new BossMonster(); creamMonster.setNextMonster(bossMonster); nomalMonster.battle(player);
簡要:
定義一組算法,將每個算法都封裝起來,并且使他們之間可以互換
代碼示例:
// 策略模式 // 定義一組算法,將每個算法都封裝起來,并且使他們之間可以互換 // 場景: 五個人租房子,要么找五室一廳,要么三室一廳 + 二室一廳 // 角色:找房人 /** 方案接口 * sayMethod() 輸出方案 */ /** 方案一 五室一廳 * sayMethod() 輸出方案 */ function Method1() { this.sayMethod = function() { console.log("找一個五室一廳."); } } /** 方案二 三室一廳 + 二室一廳 * sayMethod() 輸出方案 */ function Method2() { this.sayMethod = function() { console.log("找一個三室一廳和一個二室一廳"); } } /** 找房人 * method 方案 * findHouse() 找房子 */ function findHousePeople(method) { this.findHouse = function() { method.sayMethod(); } this.setMethod = function(newMethod) { method = newMethod; } } // 測試 var method = new Method1(); var people = new findHousePeople(method); people.findHouse(); method = new Method2(); people.setMethod(method); people.findHouse();
簡要:
給定一個遍歷規(guī)則,不管其數(shù)據(jù)結(jié)構(gòu)實現(xiàn)
代碼示例:
// 迭代器模式 // 給定一個遍歷規(guī)則,不管其數(shù)據(jù)結(jié)構(gòu)實現(xiàn) // 場景:排隊拿快遞 /** 學(xué)生構(gòu)造函數(shù) * */ function Student(name, phone, expressId) { this.getName = function() { return name; } this.getPhone = function() { return phone; } this.getExpressId = function() { return expressId; } } /** 快遞點構(gòu)造函數(shù) * */ function ExpressStation() { var index = -1; var students = []; var iterator = null; iterator = { hasNext() { return index < students.length - 1; }, next() { index ++; return students[index]; } } this.getIterator = function() { return iterator; } this.addStudent = function(student) { students.push(student); } } // 測試 var s1 = new Student("張三", "15684175538", "5-68-9"); var s2 = new Student("李四", "15806378470", "5-98-6"); var expressStation = new ExpressStation(); expressStation.addStudent(s1); expressStation.addStudent(s2); var iterator = expressStation.getIterator(); while (iterator.hasNext()) { var student = iterator.next(); console.log(`快遞員:"下一位"`); console.log(`學(xué)生:"${student.getExpressId()}"`); console.log(`快遞員:"姓名,電話"`); console.log(`學(xué)生: ${student.getName()}, ${student.getPhone()}`); console.log(); }
簡要:
定義對象間一種一對多的依賴關(guān)系,使得每當(dāng)一個對象改變狀態(tài),則所有依賴于它的對象都會得到通知并被自動更新。
代碼示例:
// 觀察者模式 // 定義對象間一種一對多的依賴關(guān)系,使得每當(dāng)一個對象改變狀態(tài),則所有依賴于它的對象都會得到通知并被自動更新。 // 場景:訂閱公眾號 /** 觀察者接口 Observer * update(String barName, String message) 收到消息 */ /** 被觀察者接口 Observable * addObserver(Observer ob) 添加觀察者 * removeObserver(Observe ob) 刪除觀察者 * notifyObservers(String message) 通知所有觀察者 */ /** 微信用戶構(gòu)造函數(shù) * */ function WxUser() { this.update = function(barName, message) { console.log(`公眾號${barName}發(fā)來消息:${message}`); } } /** 微信公眾號構(gòu)造函數(shù) * */ function WxBar(name) { var obs = new Set(); this.addObserver = function(ob) { obs.add(ob); } this.removeObserver = function(ob) { obs.delete(ob); } this.notifyObservers = function(message) { for (let ob of obs) { ob.update(name, message); } } } // 測試 var user1 = new WxUser(); var user2 = new WxUser(); var wxBar = new WxBar("黨尼瑪?shù)墓娞?); wxBar.addObserver(user1); wxBar.addObserver(user2); wxBar.notifyObservers("這波超級帥!");
簡要:
當(dāng)一個對象內(nèi)在狀態(tài)改變時允許其改變行為,這個對象看起來像改變了其類。簡單講就是一個對象有多個狀態(tài),且這個對象有幾個行為,每個狀態(tài)的這些行為不同
代碼示例:
// 狀態(tài)模式 // 當(dāng)一個對象內(nèi)在狀態(tài)改變時允許其改變行為,這個對象看起來像改變了其類。 // 簡單講就是一個對象有多個狀態(tài),且這個對象有幾個行為, // 每個狀態(tài)的這些行為不同 // 場景:文件權(quán)限(普通用戶只可讀,一般管理員可讀可寫,超級管理員可讀可寫可刪除) /** 狀態(tài)接口 State * read() 是否可讀 * write() 是否可寫 * delete() 是否可刪除 */ /** 普通用戶狀態(tài)構(gòu)造函數(shù) * */ function NomalUser() { this.read = function() { console.log("可讀"); } this.write = function() { console.log("不可寫"); } this.delete = function() { console.log("不可刪除"); } } /** 一般管理員狀態(tài)構(gòu)造函數(shù) * */ function Admin() { this.read = function() { console.log("可讀"); } this.write = function() { console.log("可寫"); } this.delete = function() { console.log("不可刪除"); } } /** 超級管理員構(gòu)造函數(shù) * */ function SuperAdmin() { this.read = function() { console.log("可讀"); } this.write = function() { console.log("可寫"); } this.delete = function() { console.log("可刪除"); } } /** 用戶構(gòu)造函數(shù) * */ function User(state) { this.setState = function(newState) { state = newState; } this.readFile = function() { state.read(); } this.writeFile = function() { state.write(); } this.deleteFile = function() { state.delete(); } } // 測試 var user = new User(new NomalUser()); user.readFile(); user.writeFile(); user.setState(new SuperAdmin()); user.readFile(); user.writeFile(); user.deleteFile();
簡要:
三個角色,原發(fā)器,備忘錄,備忘錄守護(hù)者。原發(fā)器中暴露出兩個接口,一個用于包裝自己的狀態(tài)成一個備忘錄,另一個用于通過備忘錄守護(hù)者恢復(fù)自身狀態(tài),備忘錄中只保存原發(fā)器的狀態(tài),備忘錄守護(hù)者中維持一個備忘錄,可讀可寫。
代碼示例:
// 備忘錄模式 // 設(shè)置另外的對象作為備忘錄對象,保存對象的狀態(tài) // 場景:英雄聯(lián)盟購買裝備撤回 /** 裝備備忘錄構(gòu)造函數(shù) * */ function EquipmentsMemento(equipments) { this.setEquipments = function(newEquipments) { equipments = newEquipments; } this.getEquipments = function() { return equipments; } } /** 裝備欄構(gòu)造函數(shù) * */ function EquipmentBar() { var equipments = []; this.buyEquipment = function(equipment) { console.log(`購買了裝備:${equipment}`); equipments.push(equipment); } this.showEquipments = function() { console.log("已購買裝備: ", equipments.join(" ")); } this.getEquipmentsMemento = function() { return new EquipmentsMemento([...equipments]); } this.recoverEquipments = function(equipmentCaretaker) { equipments = equipmentCaretaker.getEquipmentsMemento().getEquipments(); } } /** 裝備狀態(tài)管理者構(gòu)造函數(shù) * */ function EquipmentCaretaker() { var equipmentsMemento = null; this.setEquipmentsMemento = function(newEquipmentsMemento) { equipmentsMemento = newEquipmentsMemento; } this.getEquipmentsMemento = function() { return equipmentsMemento; } } // 測試 // 初始化狀態(tài)看守者 var equipmentCaretaker = new EquipmentCaretaker(); // 初始化裝備欄 var equipmentBar = new EquipmentBar(); // 購買裝備 equipmentBar.buyEquipment("無盡之刃"); equipmentBar.buyEquipment("狂戰(zhàn)士脛甲"); // 保存當(dāng)前 equipmentCaretaker.setEquipmentsMemento(equipmentBar.getEquipmentsMemento()); // 購買了一件不想要的裝備 equipmentBar.buyEquipment("無用大棒"); equipmentBar.showEquipments(); // 撤回 console.log("玩家買錯了,撤回..."); equipmentBar.recoverEquipments(equipmentCaretaker); equipmentBar.showEquipments();
簡要:
給定一門語言,定義它的文法的一種表示,并定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。
代碼示例:
// 解釋器模式 // 給定一門語言,定義它的文法的一種表示,并定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。 // 場景:sql 解釋器 /** sql 內(nèi)容構(gòu)造函數(shù) * */ function Context() { var tableName = null/** string */; var params = null/** object */; var wheres = null/** object */; var fields = null/** set */; this.setTableName = function(newTableName) { tableName = newTableName; } this.getTableName = function() { return tableName; } this.setParams = function(newParams) { params = newParams; } this.getParams = function() { return params; } this.setWheres = function(newWheres) { wheres = newWheres; } this.getWheres = function() { return wheres; } this.setFields = function(newFields) { fields = newFields; } this.getFields = function() { return fields; } } /** 解釋器接口 SQLExpression * string interpret(Context context) */ /** insert sql 解釋器 * */ function InsertSQLExpression() { this.interpret = function(context) { var params = context.getParams(); // 拼接 key var keys = "("; var allKey = Object.getOwnPropertyNames(params); allKey.forEach((key) => { keys += key + ","; }); keys = keys.substring(0, keys.length - 1); keys += ")"; // 拼接 value var values = "("; allKey.forEach((key) => { values += (typeof params[key] === "string" ");
簡要:
見人說人話,見鬼說鬼話
代碼示例:
// 訪問者模式 // 見人說人話,見鬼說鬼話 // 場景:買衣服時服務(wù)員的引導(dǎo),男生引導(dǎo)到男生區(qū),女生引導(dǎo)到女生區(qū) /** 服務(wù)員抽象類 Waiter * accept(Customer customer) */ /** 以純商場服務(wù)員 extends Waiter * */ function YiChunWaiter() { this.accept = function(customer) { customer.visit(this); } // 服務(wù)女士 this.serverWoman = function() { console.log("帶領(lǐng)女士到女士服裝區(qū)."); } // 服務(wù)男士 this.serveMan = function() { console.log("帶領(lǐng)男士到男士服裝區(qū)."); } } /** 顧客接口(訪問者) * visit(MarketWaiter waiter) */ /** 女士顧客 * */ function WomanCustomer() { this.visit = function(waiter) { waiter.serverWoman(); } } /** 男士顧客 * */ function ManCustomer() { this.visit = function(waiter) { waiter.serveMan(); } } // 測試 var yichunWaiter = new YiChunWaiter(); var womanCustomer = new WomanCustomer(); var manCustomer = new ManCustomer(); yichunWaiter.accept(womanCustomer); yichunWaiter.accept(manCustomer);
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/7307.html
摘要:然后將構(gòu)造函數(shù)的原型設(shè)為,便實現(xiàn)了對象繼承。首先,我們定義一個構(gòu)造函數(shù),并在其中定義一個局部變量。這里的是局部變量,其作用域仍然存在是閉包現(xiàn)象,而非對象屬性。 Javascript是動態(tài)的,弱類型的,解釋執(zhí)行的程序設(shè)計語言。 Javascript極其靈活,支持多種程序設(shè)計范式:面向?qū)ο?、指令式、函?shù)式。JavaSCript最初被用于瀏覽器腳本,現(xiàn)在已經(jīng)是所有主流瀏覽器的默認(rèn)腳本語言。瀏...
摘要:官方解釋工廠是構(gòu)造方法的抽象,抽象了創(chuàng)建具體對象的過程。工廠方法模式的實質(zhì)是定義一個創(chuàng)建對象的接口,但讓實現(xiàn)這個接口的類來決定實例化哪個類。 前言 上一章回顧了JS對象的屬性類型,那么除了我們常用的new Object()構(gòu)造函數(shù)創(chuàng)建對象和字面量方式創(chuàng)建對象的方式外,還需要用到更多的模式來解決對象被多次復(fù)用的問題。什么意思呢?就是我們很有可能會在各個地方去使用已經(jīng)創(chuàng)建過的對象,但是對象...
摘要:錯誤與異常錯誤,指程序中的非正常運行狀態(tài),在其他編程語言中稱為異?;?,錯誤。定義一個全局變量,并賦值對象的方法綁定在中,構(gòu)造函數(shù)只是一些使用操作符時被調(diào)用的函數(shù)。包括內(nèi)置對象函數(shù)在內(nèi)的所有函數(shù)都可以用來調(diào)用,這種函數(shù)調(diào)用被稱為構(gòu)造函數(shù)調(diào)用。 錯誤與異常 錯誤,指程序中的非正常運行狀態(tài),在其他編程語言中稱為‘異?!?,‘錯誤’。解釋器為每個錯誤情形創(chuàng)建并拋出一個Error對象,其中包含錯...
摘要:為目前使用范圍最廣的網(wǎng)絡(luò)保護(hù)協(xié)議。身處攻擊目標(biāo)周邊的惡意人士能夠利用密鑰重裝攻擊,利用此類安全漏洞。本文和大家一起探討下如何在三年內(nèi)快速成長為一名技術(shù)專家。 業(yè)界動態(tài) Vue 2.5 released Vue 2.5 正式發(fā)布,作者對于該版本的優(yōu)化總結(jié):更好的TypeScript 集成,更好的錯誤處理,更好的單文件功能組件支持以及更好的與環(huán)境無關(guān)的SSR WiFi爆驚天漏洞!KRACK...
摘要:并總結(jié)經(jīng)典面試題集各種算法和插件前端視頻源碼資源于一身的文檔,優(yōu)化項目,在瀏覽器端的層面上提升速度,幫助初中級前端工程師快速搭建項目。 本文是關(guān)注微信小程序的開發(fā)和面試問題,由基礎(chǔ)到困難循序漸進(jìn),適合面試和開發(fā)小程序。并總結(jié)vue React html css js 經(jīng)典面試題 集各種算法和插件、前端視頻源碼資源于一身的文檔,優(yōu)化項目,在瀏覽器端的層面上提升速度,幫助初中級前端工程師快...
閱讀 2303·2021-10-13 09:39
閱讀 3426·2021-09-30 09:52
閱讀 811·2021-09-26 09:55
閱讀 2782·2019-08-30 13:19
閱讀 1902·2019-08-26 10:42
閱讀 3198·2019-08-26 10:17
閱讀 552·2019-08-23 14:52
閱讀 3648·2019-08-23 14:39