亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

詳解JavaScript的策略模式編程

2019-11-20 12:10:35
字體:
來源:轉載
供稿:網友

 我喜歡策略設計模式。我盡可能多的試著去使用它。究其本質,策略模式使用委托去解耦使用它們的算法類。

這樣做有幾個好處。他可以防止使用大條件語句來決定哪些算法用于特定類型的對象。將關注點分離開來,因此降低了客戶端的復雜度,同時還可以促進子類化的組成。它提高了模塊化和可測性。每一個算法都可以單獨測試。每一個客戶端都可以模擬算法。任意的客戶端都能使用任何算法。他們可以互調。就像樂高積木一樣。

為了實現策略模式,通常有兩個參與者:

該策略的對象,封裝了算法。

客戶端(上下文)對象,以即插即用的方式能使用任何策略。

這里介紹了我在Javascrip里,怎樣使用策略模式,在混亂無序的環境中怎樣使用它將庫拆成小插件,以及即插即用包的。

函數作為策略

一個函數提供了一種封裝算法的絕佳方式,同時可以作為一種策略來使用。只需通過一個到客戶端的函數并確保你的客戶端能調用該策略。

我們用一個例子來證明。假設我們想創建一個Greeter 類。它所要做的就是和人打招呼。我們希望Greeter 類能知道跟人打招呼的不同方式。為了實現這一想法,我們為打招呼創建不同的策略。
 

// Greeter is a class of object that can greet people.// It can learn different ways of greeting people through// 'Strategies.'//// This is the Greeter constructor.var Greeter = function(strategy) {this.strategy = strategy;}; // Greeter provides a greet function that is going to// greet people using the Strategy passed to the constructor.Greeter.prototype.greet = function() {return this.strategy();}; // Since a function encapsulates an algorithm, it makes a perfect// candidate for a Strategy.//// Here are a couple of Strategies to use with our Greeter.var politeGreetingStrategy = function() {console.log("Hello.");}; var friendlyGreetingStrategy = function() {console.log("Hey!");}; var boredGreetingStrategy = function() {console.log("sup.");}; // Let's use these strategies!var politeGreeter = new Greeter(politeGreetingStrategy);var friendlyGreeter = new Greeter(friendlyGreetingStrategy);var boredGreeter = new Greeter(boredGreetingStrategy); console.log(politeGreeter.greet()); //=> Hello.console.log(friendlyGreeter.greet()); //=> Hey!console.log(boredGreeter.greet()); //=> sup.

在上面的例子中,Greeter 是客戶端,并有三種策略。正如你所看到的,Greeter 知道怎樣使用算法,但對于算法的細節卻一無所知。

對于復雜的算法,一個簡單的函數往往不能滿足。在這種情況下,對好的方式就是按照對象來定義。
 
類作為策略

策略同樣可以是類,特別是當算比上述例子中使用的人為的(策略/算法)更復雜的時候。使用類的話,允許你為每一種策略定義一個接口。

在下面的例子中,證實了這一點。
 

// We can also leverage the power of Prototypes in Javascript to create// classes that act as strategies.//// Here, we create an abstract class that will serve as the interface// for all our strategies. It isn't needed, but it's good for documenting// purposes.var Strategy = function() {}; Strategy.prototype.execute = function() { throw new Error('Strategy#execute needs to be overridden.')}; // Like above, we want to create Greeting strategies. Let's subclass// our Strategy class to define them. Notice that the parent class// requires its children to override the execute method.var GreetingStrategy = function() {};GreetingStrategy.prototype = Object.create(Strategy.prototype); // Here is the `execute` method, which is part of the public interface of// our Strategy-based objects. Notice how I implemented this method in term of// of other methods. This pattern is called a Template Method, and you'll see// the benefits later on.GreetingStrategy.prototype.execute = function() { return this.sayHi() + this.sayBye();}; GreetingStrategy.prototype.sayHi = function() { return "Hello, ";}; GreetingStrategy.prototype.sayBye = function() { return "Goodbye.";}; // We can already try out our Strategy. It requires a little tweak in the// Greeter class before, though.Greeter.prototype.greet = function() { return this.strategy.execute();}; var greeter = new Greeter(new GreetingStrategy());greeter.greet() //=> 'Hello, Goodbye.'

通過使用類,我們與anexecutemethod對象定義了一個策略。客戶端可以使用任何策略實現該接口。

同樣注意我又是怎樣創建GreetingStrategy的。有趣的部分是對methodexecute的重載。它以其他函數的形式定義。現在類的后繼子類可以改變特定的行為,如thesayHiorsayByemethod,并不改變常規的算法。這種模式叫做模板方法,非常適合策略模式。

讓我們看個究竟。
 

// Since the GreetingStrategy#execute method uses methods to define its algorithm,// the Template Method pattern, we can subclass it and simply override one of those// methods to alter the behavior without changing the algorithm. var PoliteGreetingStrategy = function() {};PoliteGreetingStrategy.prototype = Object.create(GreetingStrategy.prototype);PoliteGreetingStrategy.prototype.sayHi = function() { return "Welcome sir, ";}; var FriendlyGreetingStrategy = function() {};FriendlyGreetingStrategy.prototype = Object.create(GreetingStrategy.prototype);FriendlyGreetingStrategy.prototype.sayHi = function() { return "Hey, ";}; var BoredGreetingStrategy = function() {};BoredGreetingStrategy.prototype = Object.create(GreetingStrategy.prototype);BoredGreetingStrategy.prototype.sayHi = function() { return "sup, ";}; var politeGreeter  = new Greeter(new PoliteGreetingStrategy());var friendlyGreeter = new Greeter(new FriendlyGreetingStrategy());var boredGreeter  = new Greeter(new BoredGreetingStrategy()); politeGreeter.greet();  //=> 'Welcome sir, Goodbye.'friendlyGreeter.greet(); //=> 'Hey, Goodbye.'boredGreeter.greet();  //=> 'sup, Goodbye.'

GreetingStrategy 通過指定theexecutemethod的步驟,創建了一個類的算法。在上面的代碼片段中,我們通過創建專門的算法從而利用了這一點。

沒有使用子類,我們的Greeter 依然展示出一種多態行為。沒有必要在Greeter 的不同類型上進行切換來觸發正確的算法。這一切都綁定到每一個Greeter 對象上。
 

var greeters = [ new Greeter(new BoredGreetingStrategy()), new Greeter(new PoliteGreetingStrategy()), new Greeter(new FriendlyGreetingStrategy()),]; greeters.forEach(function(greeter) {   // Since each greeter knows its strategy, there's no need // to do any type checking. We just greet, and the object // knows how to handle it. greeter.greet();});

多環境下的策略模式

我最喜歡的有關策略模式的例子之一,實在 Passport.js庫中。Passport.js提供了一種在Node中處理身份驗證的簡單方式。大范圍內的供應商都支持(Facebook, Twitter, Google等等),每一個都作為一種策略實現。

該庫作為一個npm包是可行的,其所有的策略也一樣。庫的用戶可以決定為他們特有的用例安裝哪一個npm包。下面是展示其如何實現的代碼片段:
 

// Taken from http://passportjs.org var passport = require('passport')     // Each authentication mechanism is provided as an npm package.  // These packages expose a Strategy object. , LocalStrategy = require('passport-local').Strategy , FacebookStrategy = require('passport-facebook').Strategy; // Passport can be instanciated using any Strategy.passport.use(new LocalStrategy( function(username, password, done) {  User.findOne({ username: username }, function (err, user) {   if (err) { return done(err); }   if (!user) {    return done(null, false, { message: 'Incorrect username.' });   }   if (!user.validPassword(password)) {    return done(null, false, { message: 'Incorrect password.' });   }   return done(null, user);  }); })); // In this case, we instanciate a Facebook Strategypassport.use(new FacebookStrategy({  clientID: FACEBOOK_APP_ID,  clientSecret: FACEBOOK_APP_SECRET,  callbackURL: "http://www.example.com/auth/facebook/callback" }, function(accessToken, refreshToken, profile, done) {  User.findOrCreate(..., function(err, user) {   if (err) { return done(err); }   done(null, user);  }); }));

Passport.js庫只配備了一兩個簡單的身份驗證機制。除此之外,它沒有超過一個符合上下文對象的一個策略類的接口。這種機制讓他的使用者,很容易的實現他們自己的身份驗證機制,而對項目不產生不利的影響。
 
反思

策略模式為你的代碼提供了一種增加模塊化和可測性的方式。這并不意味著(策略模式)總是有效。Mixins 同樣可以被用來進行功能性注入,如在運行時的一個對象的算法。扁平的老式 duck-typing多態有時候也可以足夠簡單。

然而,使用策略模式允許你在一開始沒有引入大型體系的情況下,隨著負載型的增長,擴大你的代碼的規模。正如我們在Passport.js例子中看到的一樣,對于維護人員在將來增加另外的策略,將變得更加方便。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产视频精品va久久久久久| 66m—66摸成人免费视频| 国产乱人伦真实精品视频| 亚洲性视频网站| 午夜欧美不卡精品aaaaa| 国产精品久久久久高潮| xx视频.9999.com| 亚洲国产精品久久久| 日本欧美在线视频| 精品香蕉在线观看视频一| 91欧美精品午夜性色福利在线| 欧美成人激情视频免费观看| 国产欧美久久一区二区| 国产成人精品日本亚洲专区61| 久久99久国产精品黄毛片入口| 高清欧美一区二区三区| 亚洲欧美综合精品久久成人| 91av在线视频观看| 成人欧美一区二区三区黑人孕妇| 亚洲免费中文字幕| 亚洲最大的网站| 亚洲国产精品成人精品| 欧美人交a欧美精品| 正在播放亚洲1区| 亚洲最新中文字幕| 日韩毛片中文字幕| 欧美一级淫片aaaaaaa视频| 91精品久久久久久久久中文字幕| 久久久人成影片一区二区三区| 国产ts一区二区| 成人网址在线观看| 精品久久久久久久久久国产| 欧美日韩福利视频| 欧美激情亚洲自拍| 欧美性猛交xxxx免费看| 成人h视频在线观看播放| 久久深夜福利免费观看| 日韩美女在线观看一区| 国产综合久久久久| 欧美日韩综合视频| 亚洲性av网站| 91久久久久久久久久| 欧美一级大片在线免费观看| 91在线观看免费高清| 91探花福利精品国产自产在线| 亚洲欧美日韩国产中文专区| 国产亚洲一区二区在线| 国产在线拍揄自揄视频不卡99| 91精品国产91久久久久久最新| 在线丨暗呦小u女国产精品| 成人久久18免费网站图片| 亚洲激情中文字幕| 精品久久久久久亚洲国产300| 久久久久久久成人| 疯狂做受xxxx高潮欧美日本| 国产又爽又黄的激情精品视频| 狠狠色噜噜狠狠狠狠97| 国产成人福利夜色影视| 欧美黑人视频一区| 亚洲国产日韩欧美在线99| 久久久久久91香蕉国产| 成人欧美在线观看| 久久精品成人欧美大片| 欧美精品videossex88| 欧美日韩国产成人高清视频| 97国产精品视频人人做人人爱| 国产精品va在线播放我和闺蜜| 欧美视频精品一区| 中文字幕亚洲欧美日韩2019| 亚洲第一福利网| 欧美性猛交xxxx黑人猛交| 国产福利视频一区| 亚洲国产精品悠悠久久琪琪| 97精品久久久| 久久中文字幕国产| 欧美激情国产高清| 成人免费观看a| 久久久久久一区二区三区| 国产精品入口日韩视频大尺度| 色偷偷亚洲男人天堂| 国产精品揄拍500视频| 欧美亚洲第一区| 中文字幕亚洲一区| 97不卡在线视频| 精品久久久久久亚洲国产300| 中文字幕久久久| 欧美激情xxxxx| 国产精品久久久久91| 亚洲精品狠狠操| 久久精品国产久精国产思思| 亚洲性线免费观看视频成熟| 国产精品美女无圣光视频| 亚洲自拍偷拍色图| 亚洲男人天堂2024| 91午夜在线播放| 国产91在线播放九色快色| 中文字幕日韩精品在线| 日韩最新av在线| 91久久夜色精品国产网站| 最近中文字幕日韩精品| 久久国产精品久久久| 亚洲天堂影视av| 久久综合久久美利坚合众国| 午夜精品一区二区三区视频免费看| 久久久精品一区二区| 亚洲国产精品中文| 日韩电影大全免费观看2023年上| 欧美视频在线视频| www日韩中文字幕在线看| 亚洲国产精品久久久久秋霞不卡| 欧美极度另类性三渗透| 亚洲已满18点击进入在线看片| 少妇高潮久久久久久潘金莲| 久久久噜久噜久久综合| 国内精品久久久久影院 日本资源| 国产精品极品美女粉嫩高清在线| 97超碰国产精品女人人人爽| 亚洲国产精品福利| 国产亚洲精品综合一区91| 久久99精品久久久久久青青91| 亚洲一区精品电影| 91免费人成网站在线观看18| 欧美日韩国产精品| 久久国产加勒比精品无码| 久久久久久久一区二区| 日韩有码在线播放| 色妞一区二区三区| 亚洲电影免费观看高清完整版在线| 亚洲最大中文字幕| 亚洲色图校园春色| 欧美极品美女电影一区| 久久久久成人精品| 日韩精品免费在线| 97av视频在线| 国产日韩精品一区二区| 日本精品一区二区三区在线播放视频| 久久久久久有精品国产| 欧美在线视频观看| 5566成人精品视频免费| 日韩美女视频免费看| 国精产品一区一区三区有限在线| 欧美巨大黑人极品精男| 欧美日韩国产一区在线| 亚洲乱码国产乱码精品精| 91在线看www| 欧美在线观看网址综合| 青青久久av北条麻妃海外网| 不卡av日日日| 亚洲欧美在线第一页| 欧美日韩视频在线| 国产精品美女网站| 欧美高清一级大片| 久久成人亚洲精品| 在线播放国产精品| 日本成人激情视频| 裸体女人亚洲精品一区| 日韩av手机在线观看| 欧美性猛交xxxx久久久| 中文欧美在线视频| 成人av在线亚洲| 欧洲永久精品大片ww免费漫画| 国产精品视频免费在线| 成人97在线观看视频| 国产精品视频网址|