body分為塊級和行內(nèi)
<div>qwer<br/>zxcv</div>
<div style="background-color: green;">qwer</div>
span style="background-color: green;">zxcv</span>
<p>hahahahah</p>
<p>hahahahahaaa</p>
h1~h6y依次變小
<div>默認(rèn)文字字體</div>
<h1>再再再再再粗一點(diǎn)</h1>
<h2>再再再再粗一點(diǎn)</h2>
<h3>再再再粗一點(diǎn)</h3>
<h4>再再粗一點(diǎn)</h4>
<h5>再粗一點(diǎn)</h5>
<h6>粗一點(diǎn)</h6>
<a href="http://www.baidu.com" title="baidu">百度</a>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>野雞平臺</title>
</head>
<body>
<h1>章節(jié)</h1>
<a href="#i1" title="第一章">第一章 寂寞的春天</a>
<a href="#i2" title="第二章">第二章 寂寞的夏天</a>
<a href="#i3" title="第三章">第三章 寂寞的秋天</a>
<a href="#i4" title="第四章">第四章 寂寞的冬天</a>
<h1>內(nèi)容</h1>
<div style="height: 1000px;" id="i1">
<h3>第一章 寂寞的春天</h3>
<p>春暖花開,萬物復(fù)蘇,又到了交配的季節(jié)。</p>
</div>
<div style="height: 1000px;" id="i2">
<h3>第二章 寂寞的夏天</h3>
<p>夏天夏天悄悄過去留下小咪咪</p>
</div>
<div style="height: 1000px;" id="i3">
<h3>第三章 寂寞的秋天</h3>
<p>今年的秋天真是寂寞呀?。?!</p>
</div>
<div style="height: 1000px;" id="i4">
<h3>第四章 寂寞的冬天</h3>
<p>下雪</p>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>野雞平臺</title>
</head>
<body>
<ul>
<li>周杰倫</li>
<li>林俊杰</li>
<li>王力宏</li>
</ul>
<ol>
<li>鐵錘</li>
<li>鋼彈</li>
<li>狗蛋</li>
</ol>
<dl>
<dt>河北省</dt>
<dd>邯鄲</dd>
<dd>石家莊</dd>
<dt>山西省</dt>
<dd>太原</dd>
<dd>平遙</dd>
</dl>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>6666</title>
</head>
<body>
<table border="3"> <!--border 選擇表格樣式-->>
<thead>
<tr>
<th>姓名</th>
<th>年齡</th>
<th>愛好</th>
</tr>
</thead>
<tbody>
<tr>
<td>xxxx</td>
<td>18</td>
<td>看書</td>
</tr>
<tr>
<td rowspan="3">aaaa</td> <!--rowspan 合并單元格-->>
<td>18</td>
<td>吃飯</td>
</tr>
<tr>
<td>33</td>>
<td>heiheihei</td>>
</tr>>
</tbody>
</table>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>6666</title>
</head>
<body>
<!--顯示本地圖片,找不到圖片則顯示alt中的文字-->
<img src="img/lover.png" alt="美女">
<!--顯示網(wǎng)絡(luò)圖片-->
<img src="https://images.cnblogs.com/cnblogs_com/wupeiqi/662608/t_212313579359018.png" alt="妹子">
</body>
</html>
type
<button type="button"> 按鈕 </button>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>666666</title>
</head>
<body>
<h3>文本框</h3>
<input type="text">
<h3>密碼框</h3>
<input type="password">
<h3>單選框</h3>
<input type="radio" name="gender">男
<input type="radio" name="gender">女
<h3>復(fù)選框</h3>
<input type="checkbox">籃球
<input type="checkbox">足球
<input type="checkbox">橄欖球
<h3>上傳文件</h3>
<input type="file">
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML學(xué)習(xí)</title>
</head>
<body>
<h3>單選</h3>
<select>
<option>上海</option>
<option>北京</option>
<option>深圳</option>
</select>
<h3>多選</h3>
<select multiple>
<option>上海</option>
<option>北京</option>
<option>深圳</option>
</select>
</body>
</html>
<!DOCTYPE html>
臥槽,無情呀
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>HTML學(xué)習(xí)</title>
</head>
<body>
<textarea>文本內(nèi)容寫在這里...</textarea>
</body>
</body>
</html>
用于提交數(shù)據(jù)到后臺
// 提交表單之后,實(shí)際上會將表單中的數(shù)據(jù)構(gòu)造成一種特殊的結(jié)構(gòu),發(fā)送給后臺,類似于:
{
user:用戶輸入的姓名,
pwd:用戶輸入的密碼,
...
}
<script src="https://lf3-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>
序列定義:
文字前面的符號或者序列
特點(diǎn):
塊元素 ,獨(dú)立成行,行間距 , 行縮進(jìn)
類別:
包括兩種,一種是有序的叫ol,一種是無序的ul
兩者共同點(diǎn):
這兩個都同樣嵌套li。
無序標(biāo)簽屬性 :
type disc 實(shí)心圓(默認(rèn)屬性) circle空心圓 square實(shí)心四方
有序標(biāo)簽屬性:
type =1 a A i I
start="n"從第n個數(shù)開始計數(shù)
嵌套關(guān)系,UL可以嵌套UL,原則是繼續(xù)縮進(jìn)
部分講設(shè)計模式的文章都是使用的Java、C++這樣的以類為基礎(chǔ)的靜態(tài)類型語言,作為前端開發(fā)者,js這門基于原型的動態(tài)語言,函數(shù)成為了一等公民,在實(shí)現(xiàn)一些設(shè)計模式上稍顯不同,甚至簡單到不像使用了設(shè)計模式,有時候也會產(chǎn)生些困惑。
設(shè)計模式 Design Pattern 是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計經(jīng)驗的總結(jié),使用設(shè)計模式是為了可重用代碼、讓代碼更容易被他人理解并且保證代碼可靠性。
設(shè)計模式分類(23種設(shè)計模式)
創(chuàng)建型
結(jié)構(gòu)型
行為型
看完了上述設(shè)計模式后,把它們的關(guān)鍵詞特點(diǎn)羅列出來,以后提到某種設(shè)計模式,進(jìn)而聯(lián)想相應(yīng)的關(guān)鍵詞和例子,從而心中有數(shù)。
工廠模式定義一個用于創(chuàng)建對象的接口,這個接口由子類決定實(shí)例化哪一個類。該模式使一個類的實(shí)例化延遲到了子類。而子類可以重寫接口方法以便創(chuàng)建的時候指定自己的對象類型。
class Product {
constructor(name) {
this.name = name
}
init() {
console.log('init')
}
fun() {
console.log('fun')
}
}
class Factory {
create(name) {
return new Product(name)
}
}
// use
let factory = new Factory()
let p = factory.create('p1')
p.init()
p.fun()
當(dāng)被應(yīng)用到錯誤的問題類型上時,這一模式會給應(yīng)用程序引入大量不必要的復(fù)雜性.除非為創(chuàng)建對象提供一個接口是我們編寫的庫或者框架的一個設(shè)計上目標(biāo),否則我會建議使用明確的構(gòu)造器,以避免不必要的開銷。
由于對象的創(chuàng)建過程被高效的抽象在一個接口后面的事實(shí),這也會給依賴于這個過程可能會有多復(fù)雜的單元測試帶來問題。
class jQuery {
constructor(selector) {
super(selector)
}
add() {
}
// 此處省略若干API
}
window.$ = function(selector) {
return new jQuery(selector)
}
在大型應(yīng)用中,我們可能需要將應(yīng)用分割成小一些的代碼塊,并且只在需要的時候才從服務(wù)器加載一個模塊。為了簡化,Vue 允許你以一個工廠函數(shù)的方式定義你的組件,這個工廠函數(shù)會異步解析你的組件定義。Vue 只有在這個組件需要被渲染的時候才會觸發(fā)該工廠函數(shù),且會把結(jié)果緩存起來供未來重渲染。例如:
Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// 向 `resolve` 回調(diào)傳遞組件定義
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})
單例模式
一個類只有一個實(shí)例,并提供一個訪問它的全局訪問點(diǎn)。
class LoginForm {
constructor() {
this.state = 'hide'
}
show() {
if (this.state === 'show') {
alert('已經(jīng)顯示')
return
}
this.state = 'show'
console.log('登錄框顯示成功')
}
hide() {
if (this.state === 'hide') {
alert('已經(jīng)隱藏')
return
}
this.state = 'hide'
console.log('登錄框隱藏成功')
}
}
LoginForm.getInstance = (function () {
let instance
return function () {
if (!instance) {
instance = new LoginForm()
}
return instance
}
})()
let obj1 = LoginForm.getInstance()
obj1.show()
let obj2 = LoginForm.getInstance()
obj2.hide()
console.log(obj1 === obj2)
適配器模式
將一個類的接口轉(zhuǎn)化為另外一個接口,以滿足用戶需求,使類之間接口不兼容問題通過適配器得以解決。
class Plug {
getName() {
return 'iphone充電頭';
}
}
class Target {
constructor() {
this.plug = new Plug();
}
getName() {
return this.plug.getName() + ' 適配器Type-c充電頭';
}
}
let target = new Target();
target.getName(); // iphone充電頭 適配器轉(zhuǎn)Type-c充電頭
// 自己封裝的ajax, 使用方式如下
ajax({
url: '/getData',
type: 'Post',
dataType: 'json',
data: {
test: 111
}
}).done(function() {})
// 因為歷史原因,代碼中全都是:
// $.ajax({....})
// 做一層適配器
var $ = {
ajax: function (options) {
return ajax(options)
}
}
<template>
<div id="example">
<p>Original message: "{{ message }}"</p> <!-- Hello -->
<p>Computed reversed message: "{{ reversedMessage }}"</p> <!-- olleH -->
</div>
</template>
<script type='text/javascript'>
export default {
name: 'demo',
data() {
return {
message: 'Hello'
}
},
computed: {
reversedMessage: function() {
return this.message.split('').reverse().join('')
}
}
}
</script>
適配器與代理模式相似
裝飾者模式
class Cellphone {
create() {
console.log('生成一個手機(jī)')
}
}
class Decorator {
constructor(cellphone) {
this.cellphone = cellphone
}
create() {
this.cellphone.create()
this.createShell(cellphone)
}
createShell() {
console.log('生成手機(jī)殼')
}
}
// 測試代碼
let cellphone = new Cellphone()
cellphone.create()
console.log('------------')
let dec = new Decorator(cellphone)
dec.create()
獨(dú)的類。現(xiàn)在要給每種自行車都裝上前燈、尾 燈和鈴鐺這3 種配件。如果使用繼承的方式來給 每種自行車創(chuàng)建子類,則需要 4×3 = 12 個子類。 但是如果把前燈、尾燈、鈴鐺這些對象動態(tài)組 合到自行車上面,則只需要額外增加3 個類
是為一個對象提供一個代用品或占位符,以便控制對它的訪問
假設(shè)當(dāng)A 在心情好的時候收到花,小明表白成功的幾率有
60%,而當(dāng)A 在心情差的時候收到花,小明表白的成功率無限趨近于0。 小明跟A 剛剛認(rèn)識兩天,還無法辨別A 什么時候心情好。如果不合時宜地把花送給A,花 被直接扔掉的可能性很大,這束花可是小明吃了7 天泡面換來的。 但是A 的朋友B 卻很了解A,所以小明只管把花交給B,B 會監(jiān)聽A 的心情變化,然后選 擇A 心情好的時候把花轉(zhuǎn)交給A,代碼如下:
let Flower = function() {}
let xiaoming = {
sendFlower: function(target) {
let flower = new Flower()
target.receiveFlower(flower)
}
}
let B = {
receiveFlower: function(flower) {
A.listenGoodMood(function() {
A.receiveFlower(flower)
})
}
}
let A = {
receiveFlower: function(flower) {
console.log('收到花'+ flower)
},
listenGoodMood: function(fn) {
setTimeout(function() {
fn()
}, 1000)
}
}
xiaoming.sendFlower(B)
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
let ul = document.querySelector('#ul');
ul.addEventListener('click', event => {
console.log(event.target);
});
</script>
處理請求速度可能有差別,非直接訪問存在開銷
裝飾者模式實(shí)現(xiàn)上和代理模式類似
外觀模式
為子系統(tǒng)的一組接口提供一個一致的界面,定義了一個高層接口,這個接口使子系統(tǒng)更加容易使用
let addMyEvent = function (el, ev, fn) {
if (el.addEventListener) {
el.addEventListener(ev, fn, false)
} else if (el.attachEvent) {
el.attachEvent('on' + ev, fn)
} else {
el['on' + ev] = fn
}
};
let myEvent = {
// ...
stop: e => {
e.stopPropagation();
e.preventDefault();
}
};
參考: 大話設(shè)計模式
觀察者模式
定義了一種一對多的關(guān)系,讓多個觀察者對象同時監(jiān)聽某一個主題對象,這個主題對象的狀態(tài)發(fā)生變化時就會通知所有的觀察者對象,使它們能夠自動更新自己,當(dāng)一個對象的改變需要同時改變其它對象,并且它不知道具體有多少對象需要改變的時候,就應(yīng)該考慮使用觀察者模式。
// 主題 保存狀態(tài),狀態(tài)變化之后觸發(fā)所有觀察者對象
class Subject {
constructor() {
this.state = 0
this.observers = []
}
getState() {
return this.state
}
setState(state) {
this.state = state
this.notifyAllObservers()
}
notifyAllObservers() {
this.observers.forEach(observer => {
observer.update()
})
}
attach(observer) {
this.observers.push(observer)
}
}
// 觀察者
class Observer {
constructor(name, subject) {
this.name = name
this.subject = subject
this.subject.attach(this)
}
update() {
console.log(`${this.name} update, state: ${this.subject.getState()}`)
}
}
// 測試
let s = new Subject()
let o1 = new Observer('o1', s)
let o2 = new Observer('02', s)
s.setState(12)
document.body.addEventListener('click', function() {
console.log('hello world!');
});
document.body.click()
過度使用會導(dǎo)致對象與對象之間的聯(lián)系弱化,會導(dǎo)致程序難以跟蹤維護(hù)和理解
允許一個對象在其內(nèi)部狀態(tài)改變的時候改變它的行為,對象看起來似乎修改了它的類
// 狀態(tài) (弱光、強(qiáng)光、關(guān)燈)
class State {
constructor(state) {
this.state = state
}
handle(context) {
console.log(`this is ${this.state} light`)
context.setState(this)
}
}
class Context {
constructor() {
this.state = null
}
getState() {
return this.state
}
setState(state) {
this.state = state
}
}
// test
let context = new Context()
let weak = new State('weak')
let strong = new State('strong')
let off = new State('off')
// 弱光
weak.handle(context)
console.log(context.getState())
// 強(qiáng)光
strong.handle(context)
console.log(context.getState())
// 關(guān)閉
off.handle(context)
console.log(context.getState())
提供一種方法順序一個聚合對象中各個元素,而又不暴露該對象的內(nèi)部表示。
class Iterator {
constructor(conatiner) {
this.list = conatiner.list
this.index = 0
}
next() {
if (this.hasNext()) {
return this.list[this.index++]
}
return null
}
hasNext() {
if (this.index >= this.list.length) {
return false
}
return true
}
}
class Container {
constructor(list) {
this.list = list
}
getIterator() {
return new Iterator(this)
}
}
// 測試代碼
let container = new Container([1, 2, 3, 4, 5])
let iterator = container.getIterator()
while(iterator.hasNext()) {
console.log(iterator.next())
}
對于集合內(nèi)部結(jié)果常常變化各異,不想暴露其內(nèi)部結(jié)構(gòu)的話,但又想讓客戶代碼透明的訪問其中的元素,可以使用迭代器模式
橋接模式
橋接模式(Bridge)將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。
class Color {
constructor(name){
this.name = name
}
}
class Shape {
constructor(name,color){
this.name = name
this.color = color
}
draw(){
console.log(`${this.color.name} ${this.name}`)
}
}
//測試
let red = new Color('red')
let yellow = new Color('yellow')
let circle = new Shape('circle', red)
circle.draw()
let triangle = new Shape('triangle', yellow)
triangle.draw()
class TrainOrder {
create () {
console.log('創(chuàng)建火車票訂單')
}
}
class HotelOrder {
create () {
console.log('創(chuàng)建酒店訂單')
}
}
class TotalOrder {
constructor () {
this.orderList = []
}
addOrder (order) {
this.orderList.push(order)
return this
}
create () {
this.orderList.forEach(item => {
item.create()
})
return this
}
}
// 可以在購票網(wǎng)站買車票同時也訂房間
let train = new TrainOrder()
let hotel = new HotelOrder()
let total = new TotalOrder()
total.addOrder(train).addOrder(hotel).create()
如果通過組合模式創(chuàng)建了太多的對象,那么這些對象可能會讓系統(tǒng)負(fù)擔(dān)不起。
原型模式
原型模式(prototype)是指用原型實(shí)例指向創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象。
class Person {
constructor(name) {
this.name = name
}
getName() {
return this.name
}
}
class Student extends Person {
constructor(name) {
super(name)
}
sayHello() {
console.log(`Hello, My name is ${this.name}`)
}
}
let student = new Student("xiaoming")
student.sayHello()
原型模式,就是創(chuàng)建一個共享的原型,通過拷貝這個原型來創(chuàng)建新的類,用于創(chuàng)建重復(fù)的對象,帶來性能上的提升。
策略模式
定義一系列的算法,把它們一個個封裝起來,并且使它們可以互相替換
<html>
<head>
<title>策略模式-校驗表單</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
</head>
<body>
<form id = "registerForm" method="post" action="http://xxxx.com/api/register">
用戶名:<input type="text" name="userName">
密碼:<input type="text" name="password">
手機(jī)號碼:<input type="text" name="phoneNumber">
<button type="submit">提交</button>
</form>
<script type="text/javascript">
// 策略對象
const strategies = {
isNoEmpty: function (value, errorMsg) {
if (value === '') {
return errorMsg;
}
},
isNoSpace: function (value, errorMsg) {
if (value.trim() === '') {
return errorMsg;
}
},
minLength: function (value, length, errorMsg) {
if (value.trim().length < length) {
return errorMsg;
}
},
maxLength: function (value, length, errorMsg) {
if (value.length > length) {
return errorMsg;
}
},
isMobile: function (value, errorMsg) {
if (!/^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|17[7]|18[0|1|2|3|5|6|7|8|9])\d{8}$/.test(value)) {
return errorMsg;
}
}
}
// 驗證類
class Validator {
constructor() {
this.cache = []
}
add(dom, rules) {
for(let i = 0, rule; rule = rules[i++];) {
let strategyAry = rule.strategy.split(':')
let errorMsg = rule.errorMsg
this.cache.push(() => {
let strategy = strategyAry.shift()
strategyAry.unshift(dom.value)
strategyAry.push(errorMsg)
return strategies[strategy].apply(dom, strategyAry)
})
}
}
start() {
for(let i = 0, validatorFunc; validatorFunc = this.cache[i++];) {
let errorMsg = validatorFunc()
if (errorMsg) {
return errorMsg
}
}
}
}
// 調(diào)用代碼
let registerForm = document.getElementById('registerForm')
let validataFunc = function() {
let validator = new Validator()
validator.add(registerForm.userName, [{
strategy: 'isNoEmpty',
errorMsg: '用戶名不可為空'
}, {
strategy: 'isNoSpace',
errorMsg: '不允許以空白字符命名'
}, {
strategy: 'minLength:2',
errorMsg: '用戶名長度不能小于2位'
}])
validator.add(registerForm.password, [ {
strategy: 'minLength:6',
errorMsg: '密碼長度不能小于6位'
}])
validator.add(registerForm.phoneNumber, [{
strategy: 'isMobile',
errorMsg: '請輸入正確的手機(jī)號碼格式'
}])
return validator.start()
}
registerForm.onsubmit = function() {
let errorMsg = validataFunc()
if (errorMsg) {
alert(errorMsg)
return false
}
}
</script>
</body>
</html>
運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度對象的復(fù)用。系統(tǒng)只使用少量的對象,而這些對象都很相似,狀態(tài)變化很小,可以實(shí)現(xiàn)對象的多次復(fù)用。由于享元模式要求能夠共享的對象必須是細(xì)粒度對象,因此它又稱為輕量級模式,它是一種對象結(jié)構(gòu)型模式
let examCarNum = 0 // 駕考車總數(shù)
/* 駕考車對象 */
class ExamCar {
constructor(carType) {
examCarNum++
this.carId = examCarNum
this.carType = carType ? '手動檔' : '自動檔'
this.usingState = false // 是否正在使用
}
/* 在本車上考試 */
examine(candidateId) {
return new Promise((resolve => {
this.usingState = true
console.log(`考生- ${ candidateId } 開始在${ this.carType }駕考車- ${ this.carId } 上考試`)
setTimeout(() => {
this.usingState = false
console.log(`%c考生- ${ candidateId } 在${ this.carType }駕考車- ${ this.carId } 上考試完畢`, 'color:#f40')
resolve() // 0~2秒后考試完畢
}, Math.random() * 2000)
}))
}
}
/* 手動檔汽車對象池 */
ManualExamCarPool = {
_pool: [], // 駕考車對象池
_candidateQueue: [], // 考生隊列
/* 注冊考生 ID 列表 */
registCandidates(candidateList) {
candidateList.forEach(candidateId => this.registCandidate(candidateId))
},
/* 注冊手動檔考生 */
registCandidate(candidateId) {
const examCar = this.getManualExamCar() // 找一個未被占用的手動檔駕考車
if (examCar) {
examCar.examine(candidateId) // 開始考試,考完了讓隊列中的下一個考生開始考試
.then(() => {
const nextCandidateId = this._candidateQueue.length && this._candidateQueue.shift()
nextCandidateId && this.registCandidate(nextCandidateId)
})
} else this._candidateQueue.push(candidateId)
},
/* 注冊手動檔車 */
initManualExamCar(manualExamCarNum) {
for (let i = 1; i <= manualExamCarNum; i++) {
this._pool.push(new ExamCar(true))
}
},
/* 獲取狀態(tài)為未被占用的手動檔車 */
getManualExamCar() {
return this._pool.find(car => !car.usingState)
}
}
ManualExamCarPool.initManualExamCar(3) // 一共有3個駕考車
ManualExamCarPool.registCandidates([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) // 10個考生來考試
模板方法模式由兩部分結(jié)構(gòu)組成,第一部分是抽象父類,第二部分是具體的實(shí)現(xiàn)子類。通常在抽象父類中封裝了子類的算法框架,包括實(shí)現(xiàn)一些公共方法和封裝子類中所有方法的執(zhí)行順序。子類通過繼承這個抽象類,也繼承了整個算法結(jié)構(gòu),并且可以選擇重寫父類的方法。
class Beverage {
constructor({brewDrink, addCondiment}) {
this.brewDrink = brewDrink
this.addCondiment = addCondiment
}
/* 燒開水,共用方法 */
boilWater() { console.log('水已經(jīng)煮沸=== 共用') }
/* 倒杯子里,共用方法 */
pourCup() { console.log('倒進(jìn)杯子里===共用') }
/* 模板方法 */
init() {
this.boilWater()
this.brewDrink()
this.pourCup()
this.addCondiment()
}
}
/* 咖啡 */
const coffee = new Beverage({
/* 沖泡咖啡,覆蓋抽象方法 */
brewDrink: function() { console.log('沖泡咖啡') },
/* 加調(diào)味品,覆蓋抽象方法 */
addCondiment: function() { console.log('加點(diǎn)奶和糖') }
})
coffee.init()
使多個對象都有機(jī)會處理請求,從而避免請求的發(fā)送者和接受者之間的耦合關(guān)系,將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止
// 請假審批,需要組長審批、經(jīng)理審批、總監(jiān)審批
class Action {
constructor(name) {
this.name = name
this.nextAction = null
}
setNextAction(action) {
this.nextAction = action
}
handle() {
console.log( `${this.name} 審批`)
if (this.nextAction != null) {
this.nextAction.handle()
}
}
}
let a1 = new Action("組長")
let a2 = new Action("經(jīng)理")
let a3 = new Action("總監(jiān)")
a1.setNextAction(a2)
a2.setNextAction(a3)
a1.handle()
將一個請求封裝成一個對象,從而讓你使用不同的請求把客戶端參數(shù)化,對請求排隊或者記錄請求日志,可以提供命令的撤銷和恢復(fù)功能。
// 接收者類
class Receiver {
execute() {
console.log('接收者執(zhí)行請求')
}
}
// 命令者
class Command {
constructor(receiver) {
this.receiver = receiver
}
execute () {
console.log('命令');
this.receiver.execute()
}
}
// 觸發(fā)者
class Invoker {
constructor(command) {
this.command = command
}
invoke() {
console.log('開始')
this.command.execute()
}
}
// 倉庫
const warehouse = new Receiver();
// 訂單
const order = new Command(warehouse);
// 客戶
const client = new Invoker(order);
client.invoke()
在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)。這樣以后就可將該對象恢復(fù)到保存的狀態(tài)。
//備忘類
class Memento{
constructor(content){
this.content = content
}
getContent(){
return this.content
}
}
// 備忘列表
class CareTaker {
constructor(){
this.list = []
}
add(memento){
this.list.push(memento)
}
get(index){
return this.list[index]
}
}
// 編輯器
class Editor {
constructor(){
this.content = null
}
setContent(content){
this.content = content
}
getContent(){
return this.content
}
saveContentToMemento(){
return new Memento(this.content)
}
getContentFromMemento(memento){
this.content = memento.getContent()
}
}
//測試代碼
let editor = new Editor()
let careTaker = new CareTaker()
editor.setContent('111')
editor.setContent('222')
careTaker.add(editor.saveContentToMemento())
editor.setContent('333')
careTaker.add(editor.saveContentToMemento())
editor.setContent('444')
console.log(editor.getContent()) //444
editor.getContentFromMemento(careTaker.get(1))
console.log(editor.getContent()) //333
editor.getContentFromMemento(careTaker.get(0))
console.log(editor.getContent()) //222
解除對象與對象之間的緊耦合關(guān)系。增加一個中介者對象后,所有的 相關(guān)對象都通過中介者對象來通信,而不是互相引用,所以當(dāng)一個對象發(fā)生改變時,只需要通知 中介者對象即可。中介者使各對象之間耦合松散,而且可以獨(dú)立地改變它們之間的交互。中介者 模式使網(wǎng)狀的多對多關(guān)系變成了相對簡單的一對多關(guān)系(類似于觀察者模式,但是單向的,由中介者統(tǒng)一管理。)
class A {
constructor() {
this.number = 0
}
setNumber(num, m) {
this.number = num
if (m) {
m.setB()
}
}
}
class B {
constructor() {
this.number = 0
}
setNumber(num, m) {
this.number = num
if (m) {
m.setA()
}
}
}
class Mediator {
constructor(a, b) {
this.a = a
this.b = b
}
setA() {
let number = this.b.number
this.a.setNumber(number * 10)
}
setB() {
let number = this.a.number
this.b.setNumber(number / 10)
}
}
let a = new A()
let b = new B()
let m = new Mediator(a, b)
a.setNumber(10, m)
console.log(a.number, b.number)
b.setNumber(10, m)
console.log(a.number, b.number)
解釋器模式
給定一個語言, 定義它的文法的一種表示,并定義一個解釋器, 該解釋器使用該表示來解釋語言中的句子。
class Context {
constructor() {
this._list = []; // 存放 終結(jié)符表達(dá)式
this._sum = 0; // 存放 非終結(jié)符表達(dá)式(運(yùn)算結(jié)果)
}
get sum() {
return this._sum;
}
set sum(newValue) {
this._sum = newValue;
}
add(expression) {
this._list.push(expression);
}
get list() {
return [...this._list];
}
}
class PlusExpression {
interpret(context) {
if (!(context instanceof Context)) {
throw new Error("TypeError");
}
context.sum = ++context.sum;
}
}
class MinusExpression {
interpret(context) {
if (!(context instanceof Context)) {
throw new Error("TypeError");
}
context.sum = --context.sum;
}
}
/** 以下是測試代碼 **/
const context = new Context();
// 依次添加: 加法 | 加法 | 減法 表達(dá)式
context.add(new PlusExpression());
context.add(new PlusExpression());
context.add(new MinusExpression());
// 依次執(zhí)行: 加法 | 加法 | 減法 表達(dá)式
context.list.forEach(expression => expression.interpret(context));
console.log(context.sum);
表示一個作用于某對象結(jié)構(gòu)中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。
// 訪問者
class Visitor {
constructor() {}
visitConcreteElement(ConcreteElement) {
ConcreteElement.operation()
}
}
// 元素類
class ConcreteElement{
constructor() {
}
operation() {
console.log("ConcreteElement.operation invoked");
}
accept(visitor) {
visitor.visitConcreteElement(this)
}
}
// client
let visitor = new Visitor()
let element = new ConcreteElement()
element.accept(visitor)
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。