摘要:實(shí)現(xiàn)種設(shè)計(jì)模式最近在學(xué)習(xí)面向?qū)ο蟮姆N設(shè)計(jì)模式,使用和實(shí)現(xiàn)了一遍,但是因?yàn)槟壳按笕?,還沒(méi)有比較正規(guī)的大項(xiàng)目經(jīng)驗(yàn),所以學(xué)習(xí)的過(guò)程種我覺(jué)得如果沒(méi)有一定的項(xiàng)目經(jīng)驗(yàn)的話很難去完全掌控,所以學(xué)習(xí)的過(guò)程中只是大致學(xué)習(xí)了每種設(shè)計(jì)模式的特點(diǎn),我覺(jué)得在學(xué)習(xí)的過(guò)
js實(shí)現(xiàn)23種設(shè)計(jì)模式最近在學(xué)習(xí)面向?qū)ο蟮?3種設(shè)計(jì)模式,使用java 和 javascript 實(shí)現(xiàn)了一遍,但是因?yàn)槟壳按笕?,還沒(méi)有比較正規(guī)的大項(xiàng)目經(jīng)驗(yàn),所以學(xué)習(xí)的過(guò)程種我覺(jué)得如果沒(méi)有一定的項(xiàng)目經(jīng)驗(yàn)的話很難去完全掌控,所以學(xué)習(xí)的過(guò)程中只是大致學(xué)習(xí)了每種設(shè)計(jì)模式的特點(diǎn),我覺(jué)得在學(xué)習(xí)的過(guò)程中應(yīng)該自己找場(chǎng)景實(shí)現(xiàn),這樣學(xué)習(xí)效果很好,下面是代碼,當(dāng)然僅供參考。下面是代碼:
創(chuàng)建型模式三要素:
同一個(gè)實(shí)例
類自行創(chuàng)建實(shí)例對(duì)象
可向整個(gè)系統(tǒng)輸出這個(gè)實(shí)例
分類:
餓漢式( 類加載到實(shí)例時(shí)創(chuàng)建實(shí)例對(duì)象)
懶漢式( 第一次使用時(shí)才創(chuàng)建實(shí)例對(duì)象)
代碼示例:懶漢式
// 手機(jī) 用來(lái)打電話,玩游戲,看電影,且都是同一個(gè)手機(jī) // 懶漢式 var Phone = (function () { // 規(guī)定只能使用 Phone.getInstance 獲取實(shí)例 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)用時(shí)才創(chuàng)建實(shí)例 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);
代碼示例:餓漢式
// 手機(jī) 用來(lái)打電話,玩游戲,看電影,且都是同一個(gè)手機(jī) // 餓漢式 // 規(guī)定只能使用 Phone.getInstance 獲取實(shí)例 var Phone = (function () { // 在此創(chuàng)建實(shí)例,裝入內(nèi)存時(shí) 實(shí)例已創(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();
定義:
定義一個(gè)工廠,工廠定義一個(gè)方法,該方法可以根據(jù)傳入的參數(shù)去返回某一個(gè)類的實(shí)例。
代碼示例:
// 根據(jù)參數(shù)決定去實(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); // 車庫(kù) const Garage = { chooseVehicle (constructor) { return new constructor(); } }; Object.freeze(Garage); var car = Garage.chooseVehicle(Car); var moto = Garage.chooseVehicle(Moto); car.run(); moto.run();
簡(jiǎn)要:
定義一個(gè)工廠接口,接口存在一個(gè)創(chuàng)建產(chǎn)品類的方法,為每個(gè)類創(chuàng)建一個(gè)這樣的類工廠。
代碼示例:
// 工廠方法,創(chuàng)建工廠接口,為每個(gè)類創(chuàng)建一個(gè)工廠 // 定義接口 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); // 汽車車庫(kù) function CarGarage () { this.createVehicle = function () { return new Car(); } Object.freeze(this); } // 摩托車車庫(kù) function MotoGarage () { this.createVehicle = function () { return new Moto(); } Object.freeze(this); } // 測(cè)試 var carGarage = new CarGarage(); var motoGarage = new MotoGarage(); var car = carGarage.createVehicle(); var moto = motoGarage.createVehicle(); car.run(); moto.run();
簡(jiǎn)要:
對(duì)比于工廠方法,抽象工廠可以說(shuō)是多種產(chǎn)品,每種產(chǎn)品都要用工廠方法實(shí)現(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();
簡(jiǎn)要:
當(dāng)構(gòu)造一個(gè)實(shí)例的時(shí)候,需要執(zhí)行多個(gè)步驟才能生成實(shí)例,并且每個(gè)步驟有多種選擇從而會(huì)生成多種實(shí)例的時(shí)候使用。
代碼示例:
// 適用于 構(gòu)造一個(gè)實(shí)例對(duì)象需要多個(gè)步驟,且每個(gè)步驟可能不同會(huì)導(dǎo)致不同的實(shí)例類 /** 果汁制作步驟 * 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)型模式
簡(jiǎn)要:
共同繼承同一接口或抽象類,代理類包含被代理類(has-a)
代碼示例:
// 代理模式 // 共同繼承同一接口或抽象類,代理類包含被代理類(has-a) // 場(chǎng)景:幫別人考試 /** 接口(考試人) * test() 參加考試 */ /** 被代理人考試 * */ function testSelf() { this.test = function() { console.log("參加考試,可是我不會(huì)."); } } /** 代理人考試 * */ function testOther(self) { this.test = function() { console.log("參加考試,我會(huì)."); } } // 測(cè)試 var self = new testSelf(); var other = new testOther(self); other.test();
簡(jiǎn)要:
將兩個(gè)不能一塊工作的接口或者類,通過(guò)新建一個(gè)類繼承兩者,從而使得可以一起工作
代碼示例:
// 適配器模式 // 將兩個(gè)不能一塊工作的接口或者類,通過(guò)新建一個(gè)類繼承兩者,從而使得可以一起工作 // 比如小米8的方形耳機(jī)插口與圓形耳機(jī)接頭需要耳機(jī)適配器才能工作 /** 手機(jī)接口 * access() 提供的接口類型 */ function Mi8() { this.access = function () { console.log("小米8提供方形插口."); } } /** 耳機(jī)接頭 * insert() 提供的接頭類型 */ function MiHeadset() { this.insert = function () { console.log("小米耳機(jī)提供圓形插頭."); } } // 適配器 需要實(shí)現(xiàn) 手機(jī)接口與耳機(jī)接頭 function HeadsetAdapter() { this.access = function () { console.log("耳機(jī)適配器提供圓形插口."); } this.insert = function () { console.log("耳機(jī)適配器提供方形插頭."); } } // 測(cè)試 var mi8 = new Mi8(); var miHeadset = new MiHeadset(); var headsetAdapter = new HeadsetAdapter(); mi8.access(); headsetAdapter.insert(); headsetAdapter.access(); miHeadset.insert();
簡(jiǎn)要:
主要是兩個(gè)不同的類有多種種類,通過(guò) has-a 組合方式去進(jìn)行多種類的結(jié)合
示例代碼:
// 橋接模式,主要是兩個(gè)不同的類有多種種類,通過(guò) has-a 組合方式去進(jìn)行多種類的結(jié)合 /** 場(chǎng)景: * 鞋子有跑鞋,籃球鞋,鞋子的品牌有李寧,耐克 */ /** 接口:鞋柜 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(); } } // 測(cè)試 // 定義一個(gè)跑鞋柜 var runShoesBar = new RunShoesBar(); // 定義一個(gè)李寧的跑鞋柜 var liningRunShoesBar = new LiNingShoesBar(runShoesBar); liningRunShoesBar.saleShoes(); // 定義一個(gè)耐克的跑鞋柜 var nickShoesBar = new NickShoesBar(runShoesBar); nickShoesBar.saleShoes();
簡(jiǎn)要:
就是不同層級(jí)的兩個(gè)類具有極其相似的結(jié)構(gòu),可以只構(gòu)造一個(gè)類來(lái)表示這兩個(gè)類
// 組合模式:就是不同層級(jí)的兩個(gè)類具有極其相似的結(jié)構(gòu),可以只構(gòu)造一個(gè)類來(lái)表示這兩個(gè)類 // 場(chǎng)景:表示爺爺,爸爸,兒子三代關(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; // 測(cè)試 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();
簡(jiǎn)要:
裝飾模式,基本類和裝飾類共同繼承某個(gè)接口或者抽象類,
通過(guò)裝飾類包含基本類以及在裝飾類中添加裝飾方法的方式去裝飾基本類
代碼示例:
// 場(chǎng)景:lol 英雄buff, 普通英雄,露露buff,努努buff /** 公共接口:Hero * getBuff() 獲取英雄的 buff */ function NormalHero() { this.getBuff = function () { console.log("初始的英雄,無(wú) 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."); } } // 測(cè)試 var noBuffHero = new NormalHero(); var luluBuffHero = new LuLuBuffHero(noBuffHero); var nunuBuffHero = new NuNuBuffHero(luluBuffHero); nunuBuffHero.getBuff();
簡(jiǎn)要:
通過(guò)統(tǒng)一的管理類對(duì)內(nèi)部類管理,同時(shí)暴露接口接收來(lái)自外部類的消息
代碼示例:
/** 外觀模式 * 通過(guò)統(tǒng)一的管理類對(duì)內(nèi)部類管理,同時(shí)暴露接口接收來(lái)自外部類的消息 */ // 場(chǎng)景描述: 需求人員提出需求,開發(fā)人員進(jìn)行開發(fā),測(cè)試人員進(jìn)行測(cè)試 // 需求人員不需要通知開發(fā)人員去開發(fā),測(cè)試人員去測(cè)試 // 只需要告訴小組組長(zhǎng)這個(gè)需求就可以了 // 開發(fā)人員,負(fù)責(zé)開發(fā)需求 function Developter() { this.develop = function(demand_name) { console.log("開發(fā)人員開發(fā)需求:" + demand_name); } } // 測(cè)試人員,負(fù)責(zé)測(cè)試需求 function Tester() { this.test = function (demand_name) { console.log("測(cè)試人員測(cè)試需求:" + demand_name); } } // 技術(shù)部組長(zhǎng),負(fù)責(zé)安排開發(fā)人員開發(fā)和測(cè)試人員測(cè)試 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); } } // 測(cè)試 var demand_name = "開發(fā)一款MOBA游戲."; var demander = new Demander(); demander.demand(demand_name);
簡(jiǎn)要:
對(duì)于系統(tǒng)中使用的一些對(duì)象可以共享使用,那么每次使用時(shí)先判斷有沒(méi)有,有直接使用,沒(méi)有再去創(chuàng)建,節(jié)省內(nèi)存空間
代碼示例:
/** 享元模式 * 對(duì)于系統(tǒng)中使用的一些對(duì)象可以共享使用,那么每次使用時(shí)先判斷有沒(méi)有 * 有直接使用,沒(méi)有再去創(chuàng)建,節(jié)省內(nèi)存空間 */ // 場(chǎng)景: // 土豪打英雄聯(lián)盟,想用哪個(gè)皮膚,就用哪個(gè) // 有皮膚直接使用,沒(méi)有就買買買... /** 英雄皮膚類 * name 皮膚名字 * show() 皮膚展示 */ function HeroSkin(name) { console.log("玩家購(gòu)買了" + 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(); } } // 測(cè)試 var player = new Player(); player.useSkin("伊澤瑞爾-未來(lái)戰(zhàn)士"); player.useSkin("銳雯-光明使者"); player.useSkin("銳雯-光明使者");行為型模式
簡(jiǎn)要:
簡(jiǎn)單而言就是定義子類需要做什么,具體做什么交給子類去做
代碼示例(java, 因?yàn)?js 沒(méi)有抽象方法這些,而且我覺(jué)得模板方法主要是固定流程,實(shí)現(xiàn)交給子類實(shí)現(xiàn))
package actionModel.templateModel; // 模板方法 // 場(chǎng)景:召喚師選擇英雄,皮膚和召喚師技能 // 步驟:選擇英雄 -> 選擇皮膚 -> 選擇召喚師技能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) { // 測(cè)試 Player xiaoming = new XiaoMing(); Player xiaozhang = new XiaoZhang(); xiaoming.show(); xiaozhang.show(); } }
簡(jiǎn)要:
簡(jiǎn)單來(lái)說(shuō)就是通過(guò)中介者進(jìn)行數(shù)據(jù)傳遞,一方提供數(shù)據(jù),一方訂閱數(shù)據(jù)
代碼示例:
// 中介者模式 // 簡(jiǎn)單來(lái)說(shuō)就是通過(guò)中介者進(jìn)行數(shù)據(jù)傳遞 // 一方提供數(shù)據(jù),一方訂閱數(shù)據(jù) // 場(chǎng)景:使用第三方買二手手機(jī) // 購(gòu)買者去預(yù)定手機(jī),當(dāng)出售者賣該型號(hào)的手機(jī)時(shí)候通知購(gòu)買者 /** 購(gòu)買者構(gòu)造函數(shù) * * @param phoneName 購(gòu)買人需要的手機(jī) */ function Buyer(phoneName) { this.getPhoneName = function() { return phoneName; } this.callSellerPhone = function(phone) { console.log(`聯(lián)系賣家:${phone}買 ${phoneName}`); } } /** 出售者構(gòu)造函數(shù) * @param phoneName 賣的的手機(jī) * @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) { // 若存在一個(gè)合適的賣家,直接通知買主,不添加到列表 for (let i of sellerList) { if (i.getPhoneName() === buyer.getPhoneName()) { buyer.callSellerPhone(i.getPhone()); break; } } buyerList.push(buyer); } this.addSeller = function(seller) { // 若存在一個(gè)合適的買家,直接通知買主,不添加到列表 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);
簡(jiǎn)要:
使用命令模式可以在擴(kuò)展調(diào)度中心的時(shí)候不修改調(diào)度中心的代碼
代碼示例:
// 命令模式 // 使用命令模式可以在擴(kuò)展調(diào)度中心的時(shí)候不修改調(diào)度中心的代碼 // 場(chǎng)景:玩具遙控汽車 /** 汽車構(gòu)造函數(shù) * */ function ToyCar() { this.goOn = function() { console.log("小車前進(jìn)"); } this.stop = function() { console.log("小車停止"); } this.speedUp = function() { console.log("小車加速"); } } /** 命令接口 CarCommand * car 遙控汽車的實(shí)例 * execute() 執(zhí)行命令 */ /** 前進(jìn)的命令 extends CarCommand * @param car 汽車實(shí)例 */ function GoOnCommand(car) { this.execute = function() { car.goOn(); } } /** 停止的命令 extends CarCommand * @param car 汽車實(shí)例 */ function StopCommand(car) { this.execute = function() { car.stop(); } } /** 加速的命令 extends CarCommand * @param car 汽車實(shí)例 */ 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(); } } // 測(cè)試 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();
簡(jiǎn)要:
將請(qǐng)求交給一條處理鏈,處理鏈上的有多個(gè)處理器處理,當(dāng)處理鏈上某個(gè)處理器處理了該請(qǐng)求,返回處理的結(jié)果優(yōu)點(diǎn)是添加刪除處理器時(shí)不需要修改內(nèi)部代碼,只需要添加或者刪除即可,符合開閉原則
代碼示例:
// 責(zé)任鏈模式 // 將請(qǐng)求交給一條處理鏈,處理鏈上的有多個(gè)處理器處理, // 當(dāng)處理鏈上某個(gè)處理器處理了該請(qǐng)求,返回處理的結(jié)果 // 優(yōu)點(diǎn)是添加刪除處理器時(shí)不需要修改內(nèi)部代碼,只需要添加或者刪除即可 // 符合開閉原則 // 場(chǎng)景:dnf 玩家刷圖打怪,怪物有普通怪,精英怪,boss /** 怪物抽象類 * nextMonster 下一個(gè)怪物 * setNextMonster 設(shè)置下一個(gè)怪物 * 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("被普通怪打死, 請(qǐng)使用復(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("被精英怪打死, 請(qǐng)使用復(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怪打死, 請(qǐng)使用復(fù)活幣"); } } /** 玩家類 * */ function Player() { } // 測(cè)試 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);
簡(jiǎn)要:
定義一組算法,將每個(gè)算法都封裝起來(lái),并且使他們之間可以互換
代碼示例:
// 策略模式 // 定義一組算法,將每個(gè)算法都封裝起來(lái),并且使他們之間可以互換 // 場(chǎng)景: 五個(gè)人租房子,要么找五室一廳,要么三室一廳 + 二室一廳 // 角色:找房人 /** 方案接口 * sayMethod() 輸出方案 */ /** 方案一 五室一廳 * sayMethod() 輸出方案 */ function Method1() { this.sayMethod = function() { console.log("找一個(gè)五室一廳."); } } /** 方案二 三室一廳 + 二室一廳 * sayMethod() 輸出方案 */ function Method2() { this.sayMethod = function() { console.log("找一個(gè)三室一廳和一個(gè)二室一廳"); } } /** 找房人 * method 方案 * findHouse() 找房子 */ function findHousePeople(method) { this.findHouse = function() { method.sayMethod(); } this.setMethod = function(newMethod) { method = newMethod; } } // 測(cè)試 var method = new Method1(); var people = new findHousePeople(method); people.findHouse(); method = new Method2(); people.setMethod(method); people.findHouse();
簡(jiǎn)要:
給定一個(gè)遍歷規(guī)則,不管其數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)
代碼示例:
// 迭代器模式 // 給定一個(gè)遍歷規(guī)則,不管其數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn) // 場(chǎng)景:排隊(duì)拿快遞 /** 學(xué)生構(gòu)造函數(shù) * */ function Student(name, phone, expressId) { this.getName = function() { return name; } this.getPhone = function() { return phone; } this.getExpressId = function() { return expressId; } } /** 快遞點(diǎn)構(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); } } // 測(cè)試 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(); }
簡(jiǎn)要:
定義對(duì)象間一種一對(duì)多的依賴關(guān)系,使得每當(dāng)一個(gè)對(duì)象改變狀態(tài),則所有依賴于它的對(duì)象都會(huì)得到通知并被自動(dòng)更新。
代碼示例:
// 觀察者模式 // 定義對(duì)象間一種一對(duì)多的依賴關(guān)系,使得每當(dāng)一個(gè)對(duì)象改變狀態(tài),則所有依賴于它的對(duì)象都會(huì)得到通知并被自動(dòng)更新。 // 場(chǎng)景:訂閱公眾號(hào) /** 觀察者接口 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(`公眾號(hào)${barName}發(fā)來(lái)消息:${message}`); } } /** 微信公眾號(hào)構(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); } } } // 測(cè)試 var user1 = new WxUser(); var user2 = new WxUser(); var wxBar = new WxBar("黨尼瑪?shù)墓娞?hào)"); wxBar.addObserver(user1); wxBar.addObserver(user2); wxBar.notifyObservers("這波超級(jí)帥!");
簡(jiǎn)要:
當(dāng)一個(gè)對(duì)象內(nèi)在狀態(tài)改變時(shí)允許其改變行為,這個(gè)對(duì)象看起來(lái)像改變了其類。簡(jiǎn)單講就是一個(gè)對(duì)象有多個(gè)狀態(tài),且這個(gè)對(duì)象有幾個(gè)行為,每個(gè)狀態(tài)的這些行為不同
代碼示例:
// 狀態(tài)模式 // 當(dāng)一個(gè)對(duì)象內(nèi)在狀態(tài)改變時(shí)允許其改變行為,這個(gè)對(duì)象看起來(lái)像改變了其類。 // 簡(jiǎn)單講就是一個(gè)對(duì)象有多個(gè)狀態(tài),且這個(gè)對(duì)象有幾個(gè)行為, // 每個(gè)狀態(tài)的這些行為不同 // 場(chǎng)景:文件權(quán)限(普通用戶只可讀,一般管理員可讀可寫,超級(jí)管理員可讀可寫可刪除) /** 狀態(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("不可刪除"); } } /** 超級(jí)管理員構(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(); } } // 測(cè)試 var user = new User(new NomalUser()); user.readFile(); user.writeFile(); user.setState(new SuperAdmin()); user.readFile(); user.writeFile(); user.deleteFile();
簡(jiǎn)要:
三個(gè)角色,原發(fā)器,備忘錄,備忘錄守護(hù)者。原發(fā)器中暴露出兩個(gè)接口,一個(gè)用于包裝自己的狀態(tài)成一個(gè)備忘錄,另一個(gè)用于通過(guò)備忘錄守護(hù)者恢復(fù)自身狀態(tài),備忘錄中只保存原發(fā)器的狀態(tài),備忘錄守護(hù)者中維持一個(gè)備忘錄,可讀可寫。
代碼示例:
// 備忘錄模式 // 設(shè)置另外的對(duì)象作為備忘錄對(duì)象,保存對(duì)象的狀態(tài) // 場(chǎng)景:英雄聯(lián)盟購(gòu)買裝備撤回 /** 裝備備忘錄構(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(`購(gòu)買了裝備:${equipment}`); equipments.push(equipment); } this.showEquipments = function() { console.log("已購(gòu)買裝備: ", 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; } } // 測(cè)試 // 初始化狀態(tài)看守者 var equipmentCaretaker = new EquipmentCaretaker(); // 初始化裝備欄 var equipmentBar = new EquipmentBar(); // 購(gòu)買裝備 equipmentBar.buyEquipment("無(wú)盡之刃"); equipmentBar.buyEquipment("狂戰(zhàn)士脛甲"); // 保存當(dāng)前 equipmentCaretaker.setEquipmentsMemento(equipmentBar.getEquipmentsMemento()); // 購(gòu)買了一件不想要的裝備 equipmentBar.buyEquipment("無(wú)用大棒"); equipmentBar.showEquipments(); // 撤回 console.log("玩家買錯(cuò)了,撤回..."); equipmentBar.recoverEquipments(equipmentCaretaker); equipmentBar.showEquipments();
簡(jiǎn)要:
給定一門語(yǔ)言,定義它的文法的一種表示,并定義一個(gè)解釋器,該解釋器使用該表示來(lái)解釋語(yǔ)言中的句子。
代碼示例:
// 解釋器模式 // 給定一門語(yǔ)言,定義它的文法的一種表示,并定義一個(gè)解釋器,該解釋器使用該表示來(lái)解釋語(yǔ)言中的句子。 // 場(chǎng)景: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" ");
簡(jiǎn)要:
見人說(shuō)人話,見鬼說(shuō)鬼話
代碼示例:
// 訪問(wèn)者模式 // 見人說(shuō)人話,見鬼說(shuō)鬼話 // 場(chǎng)景:買衣服時(shí)服務(wù)員的引導(dǎo),男生引導(dǎo)到男生區(qū),女生引導(dǎo)到女生區(qū) /** 服務(wù)員抽象類 Waiter * accept(Customer customer) */ /** 以純商場(chǎng)服務(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ū)."); } } /** 顧客接口(訪問(wèn)者) * visit(MarketWaiter waiter) */ /** 女士顧客 * */ function WomanCustomer() { this.visit = function(waiter) { waiter.serverWoman(); } } /** 男士顧客 * */ function ManCustomer() { this.visit = function(waiter) { waiter.serveMan(); } } // 測(cè)試 var yichunWaiter = new YiChunWaiter(); var womanCustomer = new WomanCustomer(); var manCustomer = new ManCustomer(); yichunWaiter.accept(womanCustomer); yichunWaiter.accept(manCustomer);
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/7307.html
摘要:然后將構(gòu)造函數(shù)的原型設(shè)為,便實(shí)現(xiàn)了對(duì)象繼承。首先,我們定義一個(gè)構(gòu)造函數(shù),并在其中定義一個(gè)局部變量。這里的是局部變量,其作用域仍然存在是閉包現(xiàn)象,而非對(duì)象屬性。 Javascript是動(dòng)態(tài)的,弱類型的,解釋執(zhí)行的程序設(shè)計(jì)語(yǔ)言。 Javascript極其靈活,支持多種程序設(shè)計(jì)范式:面向?qū)ο蟆⒅噶钍?、函?shù)式。JavaSCript最初被用于瀏覽器腳本,現(xiàn)在已經(jīng)是所有主流瀏覽器的默認(rèn)腳本語(yǔ)言。瀏...
摘要:官方解釋工廠是構(gòu)造方法的抽象,抽象了創(chuàng)建具體對(duì)象的過(guò)程。工廠方法模式的實(shí)質(zhì)是定義一個(gè)創(chuàng)建對(duì)象的接口,但讓實(shí)現(xiàn)這個(gè)接口的類來(lái)決定實(shí)例化哪個(gè)類。 前言 上一章回顧了JS對(duì)象的屬性類型,那么除了我們常用的new Object()構(gòu)造函數(shù)創(chuàng)建對(duì)象和字面量方式創(chuàng)建對(duì)象的方式外,還需要用到更多的模式來(lái)解決對(duì)象被多次復(fù)用的問(wèn)題。什么意思呢?就是我們很有可能會(huì)在各個(gè)地方去使用已經(jīng)創(chuàng)建過(guò)的對(duì)象,但是對(duì)象...
摘要:錯(cuò)誤與異常錯(cuò)誤,指程序中的非正常運(yùn)行狀態(tài),在其他編程語(yǔ)言中稱為異?;?,錯(cuò)誤。定義一個(gè)全局變量,并賦值對(duì)象的方法綁定在中,構(gòu)造函數(shù)只是一些使用操作符時(shí)被調(diào)用的函數(shù)。包括內(nèi)置對(duì)象函數(shù)在內(nèi)的所有函數(shù)都可以用來(lái)調(diào)用,這種函數(shù)調(diào)用被稱為構(gòu)造函數(shù)調(diào)用。 錯(cuò)誤與異常 錯(cuò)誤,指程序中的非正常運(yùn)行狀態(tài),在其他編程語(yǔ)言中稱為‘異?!?,‘錯(cuò)誤’。解釋器為每個(gè)錯(cuò)誤情形創(chuàng)建并拋出一個(gè)Error對(duì)象,其中包含錯(cuò)...
摘要:為目前使用范圍最廣的網(wǎng)絡(luò)保護(hù)協(xié)議。身處攻擊目標(biāo)周邊的惡意人士能夠利用密鑰重裝攻擊,利用此類安全漏洞。本文和大家一起探討下如何在三年內(nèi)快速成長(zhǎng)為一名技術(shù)專家。 業(yè)界動(dòng)態(tài) Vue 2.5 released Vue 2.5 正式發(fā)布,作者對(duì)于該版本的優(yōu)化總結(jié):更好的TypeScript 集成,更好的錯(cuò)誤處理,更好的單文件功能組件支持以及更好的與環(huán)境無(wú)關(guān)的SSR WiFi爆驚天漏洞!KRACK...
摘要:并總結(jié)經(jīng)典面試題集各種算法和插件前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快速搭建項(xiàng)目。 本文是關(guān)注微信小程序的開發(fā)和面試問(wèn)題,由基礎(chǔ)到困難循序漸進(jìn),適合面試和開發(fā)小程序。并總結(jié)vue React html css js 經(jīng)典面試題 集各種算法和插件、前端視頻源碼資源于一身的文檔,優(yōu)化項(xiàng)目,在瀏覽器端的層面上提升速度,幫助初中級(jí)前端工程師快...
閱讀 2618·2021-10-13 09:39
閱讀 3596·2021-09-30 09:52
閱讀 868·2021-09-26 09:55
閱讀 2841·2019-08-30 13:19
閱讀 1951·2019-08-26 10:42
閱讀 3242·2019-08-26 10:17
閱讀 607·2019-08-23 14:52
閱讀 3710·2019-08-23 14:39