日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

相信大家在平時的開發中或多或少聽說的聽說過各種設計模式,有非常常見的,比如:觀察者模式,工廠模式,裝飾器模式等等,熟練掌握設計模式不僅僅對我們技術提升有巨大的幫助,而且更有利于編程思維的提升,而且如果我們能夠熟練的將各種設計模式應用到實際的開發中,對代碼的易讀和維護都能夠起到積極的作用。

學好JavaScript設計模式,一文足矣!

 

設計原則

Tips:在學習設計模式的時候,盡量分開去學,即先學習設計,然后再去學模式,這樣的話,對于之后的理解更加容易一些,什么設計呢,其實就是指設計原則,而模式這里指的就是就是我們要講的設計模式。現在共有5大設計原則,不管是哪種設計模式,都是遵循設計原則的。下面來分別介紹這5大設計原則。

1.單一職責原則

單一職責原則原則就是每個程序只負責做好一件事情,如果功能過于復雜就拆分開,每個部分保持獨立。這個其實也符合我們當下流行框架Vue和React的組件化開發,把一個復雜的頁面拆分成一些零散的組件,并且每個組件保持獨立,同時也可在不同的頁面當中實現復用。

2.開放封閉原則

開發封閉原則大白話的意思就是對擴展開放,對修改封閉。放到實際開發中如何去理解呢,我們日常的網站和App開發每周都有發不同的版本來增加需求,那么增加需求的時候,盡量要做到擴展新代碼,而非修改已有代碼,如果我們修改已有代碼無疑增加了風險,因為本來原來的代碼是沒有問題的,加了新的代碼之后必然會增加不可預知的風險,當然有的個別需求必須修改已有代碼,這個另說。同時這個原則也是我們軟件設計的終極目標。

3.李氏置換原則

子類能夠覆蓋父類,父類能出現的地方,子類就可以出現,這個原則其實在JAVA等語言當中是較為常見的,多用于繼承,而JavaScript作為弱類型語言,繼承使用其實是很少的,這里簡單提一下。

4.接口獨立原則

接口獨立原則的含義是保持接口的單一獨立,避免出現胖接口,JavaScript中是沒有接口(typescript例外),使用較少, 它是有點類似于單一職責原則,這里更關注接口。

5.依賴倒置原則

依賴倒置原則的含義是面向接口編程,依賴于抽象而不依賴于具體,使用方只關注接口而不關注具體類的實現,同樣這里也是JavaScript中使用較少(沒有接口&弱類型)

設計模式

設計模式分類

  1. 創建型

工廠模式(工廠方法模式、抽象工廠模式、建造者模式) 單例模式

  1. 組合型
  2. 適配器模式 裝飾器模式 代理模式 外觀模式
  3. 行為型
  4. 觀察者模式 狀態模式

下面我們就來一一結合開發當中的實例,來分析各個設計模式

工廠模式

概念

工廠模式是由一個方法來確定是要創建哪個類的實例,在前端當中最為常見的工廠模式就是new操作的單獨封裝,當遇到new操作的時候,就要考慮是否該使用工廠模式。這里也可以結合生活中的例子去思考。當你去購買漢堡,直接點餐取餐,不會自己親手做,商店要“封裝”做漢堡的工作,做好直接給買者。也就是說通過提供原材料,最終得到是漢堡還是炸雞,是由你自己決定的。

前端中實例

1. jQuery當中的$('')

jQuery當中的$('div'),這里的$選擇器就是已經封裝好的API,這里我們直接使用即可。下面簡單實現一個JQuery的$操作符,幫助大家加深理解。

class jQuery {
	constructor(selector) {
		let slice = Array.prototype.slice
		let dom = slice.call(document.querySelectorAll(selector))
		let len = dom ? dom.length : 0
		for(let i = 0;i < len; i++) {
			this[i] = dom[i]
		}
		this.length = len
		this.selector = selector || ''
	}
	append(node) {
	
	}
	html(data) {
	
	}
	//等等API
}
window.$ = function (selector) {
	return new jQuery(selector)
}

2. Vue異步組件

這個大家應該比較熟悉,而且官方文檔講的也非常詳細,這里直接飲用官方文檔的案例,在大型應用中,我們可能需要將應用分割成小一些的代碼塊,并且只在需要的時候才從服務器加載一個模塊。為了簡化,Vue 允許你以一個工廠函數的方式定義你的組件,這個工廠函數會異步解析你的組件定義。Vue 只有在這個組件需要被渲染的時候才會觸發該工廠函數,且會把結果緩存起來供未來重渲染。例如:

Vue.component('async-example', function (resolve, reject) {
 setTimeout(function () {
 // 向 `resolve` 回調傳遞組件定義
 resolve({
 template: '<div>I am async!</div>'
 })
 }, 1000)
})

如你所見,這個工廠函數會收到一個 resolve 回調,這個回調函數會在你從服務器得到組件定義的時候被調用。你也可以調用 reject(reason) 來表示加載失敗。這里的 setTimeout 是為了演示用的,如何獲取組件取決于你自己。一個推薦的做法是將異步組件和 webpack 的 code-splitting 功能一起配合使用:

Vue.component('async-webpack-example', function (resolve) {
 // 這個特殊的 `require` 語法將會告訴 webpack
 // 自動將你的構建代碼切割成多個包,這些包
 // 會通過 Ajax 請求加載
 require(['./my-async-component'], resolve)
})

你也可以在工廠函數中返回一個 Promise,所以把 webpack 2 和 ES2015 語法加在一起,我們可以寫成這樣:

Vue.component(
 'async-webpack-example',
 // 這個 `import` 函數會返回一個 `Promise` 對象。
 () => import('./my-async-component')
)

當使用局部注冊的時候,你也可以直接提供一個返回 Promise 的函數:

new Vue({
 // ...
 components: {
 'my-component': () => import('./my-async-component')
 }
})

單例模式

概念

單例模式符合單一職責原則,用大白話描述單例模式就是系統中被唯一使用,例如:電子商務網站常見的購物車和登錄都是單例模式的運用。

前端中的實例

1.jQuery中的$('')

仍舊是jQuery當中的$(' ')選擇器,整個jQuery框架當中有一個這樣的選擇器。

2.Redux和Vuex

不管是Redux還是Vuex,里面的狀態store都是唯一的,Redux中的store只能通過Reducer去修改,而Vuex中的store只能通過Mutation修改,其余修改方式都是錯誤的。

適配器模式

概念

適配器模式的含義是舊接口格式和使用者不兼容,中間加一個適配器接口。生活當中隨處可見符合適配器模式的例子,如:插頭轉換器,電腦接口轉換器。

前端中的實例

封裝舊的接口

這里我來列舉一個例子,這里那我們常用的發起ajax請求為例,你自己封裝的ajax,使用方式如下:

ajax({
	url:'/getList',
	type:'Post',
	dataType:'json',
	data:{
		id:"123"
	}
})
.done(function(){})

但是這個時候你接到的項目當中都是:$.ajax({...}),這個時候我們只需要加一層適配器即可,代碼如下:

let $ = {

ajax:function (options) {

return ajax(options);

}

}

Vue中的computed

Vue的計算屬性相信大家在項目的開發當中都是經常會用到的一個特性,比如一個字符串我們想要他的翻轉后的結果,那么這里就可以使用計算屬性,計算屬性這個特性本身用的設計模式就是適配器模式,代碼如下:

<div id="example">
 <p>Original message: "{{ message }}"</p>
 <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
 el: '#example',
 data: {
 message: 'Hello'
 },
 computed: {
 // 計算屬性的 getter
 reversedMessage: function () {
 // `this` 指向 vm 實例
 return this.message.split('').reverse().join('')
 }
 }
})

結果:

Original message: "Hello"

Computed reversed message: "olleH"

學好JavaScript設計模式,一文足矣!

 

裝飾器模式

概念

裝飾器模式,裝飾我們可以理解為就是給一個東西裝飾另外一些東西使其更好看,對應到前端中就是為對象添加新功能,并且不改變其原有的結構和功能,這種模式創建了一個裝飾類,用來包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。在我們日常生活中用到的手機殼就是經典的例子

前端中的實例

1.ES7中的裝飾器

ES7裝飾器的具體用法可以去找阮一峰老師的相關文章,其實參照其字面意思,就是對類、方法、屬性進行修飾,從而進行一些相關功能的定制。那么JavaScript的Decorator在原理和功能上簡單明了,簡單來說就是對對象進行包裝,返回一個新的對象描述,這里可以類比高階組件。這里我們列舉一個簡單的例子,想必大家都玩過王者榮耀,英雄的戰斗力都是隨著裝備和等級的增加越來越厲害,那么這里我們就以王者榮耀當中的英雄為例,示例場景是這樣的:

  • 首先創建一個普通的英雄類,他的防御值為10,攻擊力為20,血量為20;
  • 然后我們給它出布甲裝備,這樣它的抵御力增加100,變為110;

然后按照這個場景來寫具體的代碼:

創建Hero類

class Hero {
		constructor(define = 10,attack = 20, blood = 20) {
			this.init(define,attack,blood)
		}
		init(define,attack,blood) {
			this.define = define;
			this.attack = attack;
			this.blood = blood;
		}
		toString() {
			return `防御力: ${this.define},攻擊力:${this.attack},血量:${this.blood}`
		}
	}
	let houyi = new Hero();
	console.log(`當前狀態 ===> ${houyi}`) 
	//輸出:當前狀態 ===> 防御力:10,攻擊力20,血量20

創建decorateCloth方法,為英雄增加布甲裝備。

function decorateCloth(target,key,descriptor) {
		const method= descriptor.value;
		let moreDef = 100;
		let ret;
		descriptor.value = (...args) => {
			args[0] += moreDef;
			ret = method.apply(target,args);
			return ret;
		}
		return descriptor;
}
class Hero {
		constructor(define = 10,attack = 20, blood = 20) {
			this.init(define,attack,blood)
		}
		@decorateCloth
		init(define,attack,blood) {
			this.define = define;
			this.attack = attack;
			this.blood = blood;
		}
		toString() {
			return `防御力: ${this.define},攻擊力:${this.attack},血量:${this.blood}`
		}
	}
	let houyi = new Hero();
	console.log(`當前狀態 ===> ${houyi}`) 
	//輸出:當前狀態 ===> 防御力:110,攻擊力20,血量20

可以看到輸出結果防御力確實增加了,布甲確實起到了作用。

從上面的代碼可以看出,如果有的時候我們并不需要關心函數的內部實現,僅僅是想調用它的話,裝飾器能夠帶來比較好的可讀性,使用起來也是非常的方便。

學好JavaScript設計模式,一文足矣!

 

代理模式

概念

代理模式是使用者無權訪問目標對象,中間加代理,通過代理做授權和控制,我們經常會用到這個模式,不管實際的開發也好,還是網絡部署當中,都能夠看到它的身影。如:科學上網 谷歌搜索

前端中的實例

1.網頁中的事件代理

其實網頁的事件代理也是非常常考的面試題之一,其實就是把元素綁定到父元素上面,而不是對其下面的每一個子元素都進行相應的綁定,下面舉一個具體的實例:

<div id="item">
	<a href="#">a1</a>
	<a href="#">a2</a>
	<a href="#">a3</a>
	<a href="#">a4</a>
<div>
<button>點擊增加一個a標簽</button>
<script>
	let div1 = document.getElementById('div1')
	div1.addEventListener('click',function(e) {
		let target = e.target
		if(e.nodeName === 'A') {
			alert(target.innerHTML)
		}
	})
</script>

2.jQuery中的$proxy

比如我們經常會遇到這樣一種情況,如下代碼所示

$('#div1').click(function() {
		$(this).addClass('red')
	})
	$('#div1').click(function() {
		setTimeout(function () {
			// this 不符合期望
			$(this).addClass('red');
		},1000);
	})

解決的方法可能有的同學已經想到是先將this賦值給一個變量。

$('#div1').click(function() {
	setTimeout(function () {
		let _this = this;
		// this 不符合期望
		$(_this).addClass('red');
	},1000);
})

是的這種方法是對的,但是這樣就會增加一個變量,所以這里用$proxy解決更好,代碼如下:

$('#div1').click(function() {
	setTimeout($proxy(function () {
		$(this).addClass('red');
	}),1000);
})

觀察者模式

概念

觀察者模式就是只要你作為訂閱者訂閱了某個事件,當事件觸發的時候,發布者就會通知你。這里可以類比我們去咖啡廳點咖啡,當我們點了咖啡之后,就可以去做別的事情,當咖啡完成時,服務員就會叫你來取,你到時候取走咖啡即可。

前端中的實例

1.網頁中的事件綁定

<button id="btn1">btn</button>
<scirpt>
	$('#btn1').click(function() {
		console.log(1)
	})
</script>

這里我們訂閱了btn1的click事件,當幾點btn1所在的元素時,click function就會觸發。

2.Node.js的自定義事件EventEmitter

const EventEmitter = require('events').EventEmitter
const emitter1 = new EventEmitter();
emitter1.on('some',()=> {
	//監聽some事件
	console.log('some event is occured 1')
})
emitter1.on('some',()=> {
	//監聽some事件
	console.log('some event is occured 2')
})
emitter.emit('some')

狀態模式

概念

提到狀態模式就不得不提到有限狀態機,阮一峰總結過有限狀態機的三個特征:

  • 狀態總數(state)是有限的。
  • 任一時刻,只處在一種狀態之中。
  • 某種條件下,會從一種狀態轉變(transition)到另一種狀態。

這里充分說明了狀態模式的重要性。一個對象有狀態變化,每次狀態變化都會觸發一個邏輯,不能總是用if else來控制,更要學會用狀態來進行控制。

前端中的實例

1.ES6中的promise

promise是ES6新增的一個特性,它是異步編程的一種解決方案,比傳統的解決方案更加方便,可以使用.then()操作避免了回調嵌套帶來的回調地獄式的寫法,那么下面就來簡單實現一個promise。

let fsm = new statemachine({
	init:'pending',
	transitions:[
		{
			name:'resolve',
			from:'pending',
			to:'fullfilled'
		},
		{
			name:'reject',
			from:'pending',
			to:'rejected'
		}
	],
	methods:{
		onResolve:function(state,data) {
			data.successList.forEach(fn => fn())
		}
		onReject:function(state,data) {
			data.failList.forEach(fn => fn())
		}
	}
})

這就是一個簡單的promise。一個promise只有三種狀態,所以promise可以說是狀態模式的經典案例。

總結

這篇文章我們主要介紹了5大設計原則和7個設計模式,這7個設計模式是前端使用頻率較高的設計模式,當然還有很多其他的設計模式,由于篇幅原因這里無法全部介紹,

分享到:
標簽:JavaScript
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定