這裏花幾分鐘時間來說解幾個設計模式以及它們的應用場景。能夠幫助你在平時開發時把設計模式用起來html
廢話很少說,直接上demo前端
<!--index.js-->
function decoratorHoc(target){
target.customerName = 'xuqiang';
}
@decoratorHoc
class Person{}
console.log(Person.customerName);
複製代碼
那麼下面三步來把babel環境搞一下react
<!--在當前index.js目錄下-->
yarn add babel-cli -g
yarn add babel-plugin-transform-decorators-legacy
複製代碼
<!--在當前index.js目錄下新建.babelrc文件,內容以下-->
{
plugins: ['transform-decorators-legacy']
}
複製代碼
<!--在當前index.js目錄下-->
babel index.js --out-file compiled.js
複製代碼
這裏把index.js編譯爲了compiled.js。而後code runner compiled.js,發現日誌輸出了"xuqiang"jquery
裝飾器模式能夠說是很是方便地擴展了一個對象。那麼平時開發中是否是有幾類代碼跟裝飾器模式很類似es6
這裏就舉兩個例子,更多場景須要你本身去發現了json
迭代一個對象,就能夠稱爲是迭代器,下面從es6的迭代器來說解下後端
這是一個es6的自定義迭代器DEMO,講解如何寫一個迭代器來遍歷普通對象,由於遍歷數組內置已經支持了設計模式
let obj = {
name: 'xuqiang',
age: 20,
[Symbol.iterator]: () => {
let props = Object.keys(obj), i = props.length;
return {
next(){
if(i > 0){
i = i - 1;
return {
value: obj[props[props.length - i - 1]],
done: false
};
}else{
return {
value: '',
done: true
};
}
}
};
}
}
for(let prop of obj){
console.log(prop);
}
複製代碼
code runner發現能夠正確遍歷一個Object了api
用一個老生常談的場景先來解釋下發布訂閱,那就是學生時代的訂牛奶,先來整理下需求數組
需求整理清楚了,下面用個DEMO來實現下
// 發佈訂閱模式
// 發佈訂閱模式
class Puber{
constructor(name){
this.name = name;
this.products = {};
this.startInterval();
}
startInterval(){
setInterval(() => {
for(let prop in this.products){
if(this.products.hasOwnProperty(prop)){
this.emit(prop);
}
}
}, 3000);
}
sub(evt, cb){
if(!this.products[evt]){
this.products[evt] = [];
}
this.products[evt].push(cb);
}
emit(evt){
if(this.products[evt]){
let cbs = this.products[evt];
for(let cb of cbs){
cb && cb();
}
}
}
}
class Suber{
constructor(name){
this.name = name;
this.puber = new Puber('徐強');
}
getPuber(){
console.log(`我是${this.name},個人牛奶配送員是${this.puber.name}`);
}
sub(evt, cb){
this.puber.sub(evt, cb);
}
}
let customer1 = new Suber('劉思琪');
customer1.getPuber();
customer1.sub('牛奶', () => {
console.log(`如今時間是${+new Date},牛奶送至將來科技城,收件人:劉思琪`);
});
let customer2 = new Suber('徐大佬');
customer2.getPuber();
customer2.sub('牛奶', () => {
console.log(`如今時間是${+new Date},牛奶送至空港新城,收件人:徐大佬`);
});
複製代碼
class jQuery{
constructor(name){
this.name = name;
}
}
function $(name){
return new jQuery(name);
}
let obj1 = $('xuqiang');
let obj2 = $('liusiqi');
console.log(obj1);
console.log(obj2);
複製代碼
這裏舉例也是用的jquery,能夠發現jquery的$函數就是用了工廠模式,那麼工廠模式有哪些好處呢?
光是單例模式的話比較簡單,感受沒什麼亮點,因此這裏結合裝飾器模式來寫一個單例模式
function getInstanceHoc(target){
target.getInstance = (() => {
let instance;
return () => {
if(!instance){
instance = new Function(`return new ${target}()`)();
}
return instance;
}
})();
}
@getInstanceHoc
class Person{
eat(){
console.log('i am eating');
}
}
let obj = Person.getInstance();
console.log(obj);
obj.eat();
let obj1 = Person.getInstance();
console.log(obj === obj1);
複製代碼
code runner以後發現,obj和obj1均可以eat了,而後比較obj===obj1,發現是true,說明單例模式已經成功了
用es6的Proxy來說一下代理
class Vue{
constructor(data){
let _data = data;
return new Proxy(this, {
get(target, key){
return _data[key];
},
set(target, key, val){
_data[key] = val;
return true;
}
});
}
}
let obj = new Vue({
name: '徐強',
age: 20
});
console.log(obj.name);
obj.name = '劉思琪';
console.log(obj.name);
複製代碼
外觀模式在jquery中很常見。在咱們平時開發中感受也很好用
function winAlert(title, message, buttons, cb){
if(cb === undefined){
cb = buttons;
buttons = null;
}
console.log(title);
console.log(message);
console.log(buttons);
console.log(cb);
}
winAlert('提示', '操做完成', ['確認', '取消'], () => {});
winAlert('提示', '操做完成', () => {});
複製代碼
運行結果:
這讓我想起目前業務中後端全部接口都是app/htmlGateway.do,只是version,rd等參數區別,從某種角度來講這是符合外觀模式的。封閉後端api的內部實現,開放htmlGetway給前端調用
可是目前這種方式有個問題是,對於yapi,rap2等mock平臺不太友好。由於api路徑都是一致的,會不太好mock,也多是由於我沒有發現解決方案吧,因此以爲不太好mock
ok 這幾種設計模式的demo都已經講完了。有問題能夠一塊兒談論。