斑碼教育web前端課堂筆記-第63天-設計模式第一天
阿新 • • 發佈:2021-01-17
設計模式第一天
一、設計模式
軟體中的名詞:
- 工具庫:一些常用方法的封裝,這些方法之間彼此沒有聯絡,jQuery、underscore
- 框架:程式碼的半成品,彼此之間存在非常緊密的聯絡, vue
- 架構:一套大型專案的設計思路
- 設計模式: 前人的經驗,代表了最佳的實踐方式。GOF。 最初設計模式有23種,目前遠超23種。
1.1 設計模式簡介
他是一套編目分明,廣為人知,可複用的程式碼經驗的總結,代表了軟體設計的最佳實踐方式。
1.2 設計原則
- 開閉原則: 對擴充套件開放,對修改關閉
- 單一職責原則:一個類只負責一個事
- 裡式替換原則:一個父類能用的地方,子類一定可以使用
- 依賴倒置原則:抽象不應該依賴於細節,細節依賴於抽象
- 介面隔離原則:使用多個專門介面取代單一介面
- 迪米特原則: 一個類實現的功能不應該依賴於其他類
- 合成複用原則:儘可能使用物件的組合(contiain)和聚合(has),而不是繼承(is)
高內聚低耦合,擴充套件開放,修改關閉。
1.3 設計模式的分類
- 建立型設計模式: 解決物件的建立問題
- 結構型設計模式: 解決物件和類的組合問題
- 行為型設計模式:解決物件和類的耦合,職責分配的問題
二、工廠模式
解決物件的建立問題
2.1 簡單工廠
建立一個產生物件的函式
demo:
// 獲得#box物件
var box = document.getElementById ('box');
// 獲得class
var container = document.getElementsByClassName('container')[0];
// 獲得li物件
var lis = document.getElementsByTagName('li');
// jquery中 $('css選擇器')
// 簡單工廠
function $(selector) {
return document.querySelectorAll(selector);
}
// 通過工廠獲得物件
console.log($('#box'));
console.log($('.container' ));
console.log($('li'));
var xiaoming = {
name: '小明',
age: 13,
sex: '男'
}
var lili = {
name: '莉莉',
age: 18,
sex: '女'
}
var zhangsan = {
name: '張三',
age: 20,
sex: '男'
}
function people(name, age, sex) {
var obj = {
name: name,
age: age,
sex: sex
}
return obj;
}
var lisi = people('李四', 20, '男');
var meimei = people('美美', 20, '女');
2.2 寄生增強工廠
定義一個新的工廠,在該工廠內例項化其他工廠,並對其進行增強改造
demo:
<script>
// 產生人類
function People(name, sex, age) {
this.name = name;
this.sex = sex;
this.age = age;
}
// 說話
People.prototype.say = function() {
console.log('i can say');
}
function factory(name, sex, age) {
// 寄生
var people = new People(name, sex, age);
// 增強
people.code = function() {
console.log('我可以程式設計');
}
people.money = 10000000000;
return people;
}
var xiaoming = factory('小明', '男', 18);
console.log(xiaoming);
</script>
2.3 工廠方法
通過一個工廠管理很多個工廠
demo:
<script>
// 建立人的工廠
function People(name, sex, age) {
this.name = name;
this.sex = sex;
this.age = age;
}
// 建立狗狗的工廠
function Dog(name, sex, age) {
this.name = name;
this.sex = sex;
this.age = age;
}
// 建立美女的工廠
function Girl(name, sex, age) {
this.name = name;
this.sex = sex;
this.age = age;
}
// 封裝工廠,可以根據引數的不同調用不同工廠
function FactoryMethod(type, name, sex, age) {
if (type == 'people') {
return new People(name, sex, age);
} else if (type == 'dog') {
return new Dog(name, sex, age);
} else if (type == 'girl') {
return new Girl(name, sex, age);
}
}
var xiaoming = FactoryMethod('people', '小明', '男', 20);
var wangcai = FactoryMethod('dog', '旺財', '公', 3);
var xiaomei = FactoryMethod('girl', '小美', '女', 22);
console.log(xiaoming);
console.log(wangcai);
console.log(xiaomei);
</script>
三、原型和繼承
3.1 原型和原型鏈
原型是每一個函式都擁有的屬性(prototype),該屬性指向了一個公共的物件,該物件形成一個公共的區域,該區域內的所有屬性和方法可以被函式產生的例項所訪問到。為了減少記憶體的佔用,設計類的時候,要將方法寫在原型中,同樣,所有物件共用的屬性也需要寫在原型中。
由於函式也是物件,物件擁有原型物件,形成原型鏈,屬性和方法的查詢遵循原型鏈的自下而上的查詢規則。
3.2 繼承
-
鏈式繼承
將子類的原型指向父類的例項
-
建構函式繼承
解決重複問題 父類.apply(this, arguments)
-
組合繼承: 鏈式繼承 + 建構函式繼承
-
寄生繼承
A是父類 B是子類 function x(A, B) { function F() {} F.prototype = A.prototype; B.prototype = new F(); }
-
寄生組合繼承: 寄生 + 建構函式
3.3 安全類
安全類: 不管使用new還是直接呼叫,返回的都是例項化得到的物件
demo:
<script>
// 產生人類
function People(name, sex, age) {
// 判斷該物件是否由People所產生
if (!(this instanceof People)) {
return new People(name, sex, age);
}
this.name = name;
this.sex = sex;
this.age = age;
}
// 說話
People.prototype.say = function() {
console.log('i can say');
}
var xiaoming = new People('小明', '男', 20);
console.log(xiaoming);
var xiaomei = People('小美', '女', 22);
console.log(xiaomei);
</script>
四、單例設計模式
一個類只產生一個例項化物件
分析:
- 類是函式
- 建構函式不能暴露在全域性下,但是還需要能夠使用----閉包
閉包:
函式內部返回一個函式,該函式引用了函式內部的變數,導致變數不能夠被釋放,延長了變數的宣告週期,和全域性相同,但是由於這個變數屬於函式內的區域性變數,在全域性中不能夠被訪問到的,只能通過向外暴露的函式來訪問該變數
閉包:
function demo() {
var a = 1; // 此時的a只能通過返回的函式進行訪問,保護了,限制了a的訪問方式
return function() {
console.log(a++);
}
}
var f1 = demo();
f1(); // 1
f1(); // 2
var f2 = demo();
f2(); // 1
f2(); // 2
var fn = (function() {
var a = 1;
return function() {
console.log(a++);
}
})();
fn();
fn();
fn();
4.1 簡單單例
demo:
var Single = (function() {
// 產生人類
function People(name, sex, age) {
this.name = name;
this.sex = sex;
this.age = age;
}
// 說話
People.prototype.say = function () {
console.log('i can say');
}
// 生成一個物件
var obj = new People();
// console.log(obj);
// 返回函式
return function(name, sex, age) {
// obj.name = name;
// obj.sex = sex;
// obj.age = age;
People.apply(obj, arguments);
return obj;
}
})()
var xiaoming = Single('小明', '男', 20);
console.log(xiaoming);
var xiaomei = Single('小美', '女', 22);
console.log(xiaomei);
console.log(xiaomei == xiaoming);
4.2 惰性單例
按需例項化,只有呼叫一次才會例項化類
demo:
var Single = (function() {
// 產生人類
function People(name, sex, age) {
this.name = name;
this.sex = sex;
this.age = age;
}
// 說話
People.prototype.say = function () {
console.log('i can say');
}
// 生成一個物件
var obj = null;
// 返回函式
return function(name, sex, age) {
if (obj instanceof People) {
People.apply(obj, arguments);
return obj;
} else {
return obj = new People(name, sex, age);
}
}
})()
var xiaoming = Single('小明', '男', 20);
console.log(xiaoming);
var xiaomei = Single('小美', '女', 22);
console.log(xiaomei);
console.log(xiaomei == xiaoming);
五、常量
字面量:儲存一個值,值是一個基礎型別的值,值不會改變
常量:值不能被修改
demo:
<script>
// ES6
// const a = 1;
// a = 2;
// ES3
var fn = (function() {
var obj = {
a: 1,
b: 2,
c: 3,
d: {
name: 'xxoo'
}
}
return function(k) {
return obj[k];
}
})()
// 常量只針對於非引用型別有效
// 上面的a,b,c就是三個變數
console.log(fn('a'));
console.log(fn('b'));
console.log(fn('c'));
// 無效
fn('d').name = 'abc';
console.log(fn('d'));
// ES5---凍結物件,屬性值為引用型別的時候,引用型別可以進行增刪改查
var obj = {
a: 1,
b: 2,
c: 3,
d: {
name: 'xxoo'
}
}
// 凍結物件
Object.freeze(obj);
console.log(obj.a);
console.log(obj.b);
console.log(obj.c);
obj.a = 123;
console.log(obj.a);
obj.d.name = 'abc';
obj.d.sex = 'abc';
console.log(obj.d);
obj.d = {a: 1};
console.log(obj.d);
</script>