前端面試——設計模式

 

1、單例模式

定義:是保證一個類只有一個實例,並且提供一個訪問它的全局訪問點。

需求:一些對象我們往往只需要一個,比如線程池、全局緩存、瀏覽器中的window對象、登錄浮窗等。

優點:

1、可以用來劃分命名空間,減少全局變量的數量 

2、可以被實例化,且實例化一次,再次實例化生成的也是第一個實例

 

 

 

class CreateUser{
    constructor(name){
        this.name = name;
        this.getName();
    }
    getName(){
        return this.name;
    }
}
var  ProxyMode = (function(){
    var instance = null;
    return function(name){
        if(!instance){
            instance = new CreateUser(name);
        }
        return instance;
    }
})();
var a= new ProxyMode('aaa');//CreateUser {name: "aaa"}
var b= new ProxyMode('bbb');//CreateUser {name: "aaa"}結果都是第一個對象複製代碼

 

 2、觀察者模式

定義:對象間的一種一對多的依賴關係。

需求:當一個對象的狀態發生變化時,所有依賴於他的對象都將得到通知。

優點:時間上的解耦,對象之間的解耦。

 

 

 

var targetObj = {
    name:'aa'
}
var targetObj2 = {
    name:'aa'
}
// 定義值改變時的處理函數(觀察者)
function observer(oldVal, newVal) {
    // 其他處理邏輯...
    targetObj2.name = newVal
    console.info(newVal);
}

// 定義name屬性及其set和get方法(name屬性爲被觀察者)
Object.defineProperty(targetObj, 'name', {
    enumerable: true,
    configurable: true,
    get: function() {
        return name;
    },
    set: function(val) {
        observer(name, val)
        name = val
    }
});

targetObj.name = '11';
targetObj.name = '22';
console.log(targetObj2.name)複製代碼

 

3、發佈者/訂閱者模式

在網上看到一個對發佈者/訂閱者模式與觀察者模式,比較精闢的總結:

有中間商賺差價的是發佈者/訂閱者模式,無中間商賺差價的是觀察者模式。

 

 

 

function Publish(){
    let s =[];
    this.add= function(sMember){
        let isExist = s.some(function(item){
            if(item == sMember){
                return true;
            }else{
                return false;
            }
        })
        if(!isExist){
            s.push(sMember);
        }
    }
    this.send = function(data){
        s.forEach(function(fn){
            fn(data);
        })
        return this;
    }
}

let a = function(data){
    console.log(data);
}
let a = function(data){
    console.log(data);
}
let p = new Publish();
p.add(a);
p.add(b);
p.send('sadasdsa');複製代碼

 

4、工廠模式:

定義:將其成員對象的實例化推遲到子類來實現的類。

需求:創建對象的流程賦值的時候,比如依賴於很多設置文件等 ;處理大量具有相同屬性的小對象;注:不能濫用

優點:不暴露創建對象的具體邏輯,而是將將邏輯封裝在一個函數中。     

 

 

 

function createObjet(name ,age){
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.run = function (){
         return this.name + this.age;
    }
    return obj;
}
var a = createObjet('lao',22);複製代碼

 

5、模塊模式

 

 

 

var Person = (function() {
    var name = 'xxx'
    function sayName() {
        console.log(name)
    }
    return{
        name: name,
        sayName: sayName
    }
})()複製代碼

 

6、代理模式

使用ES6中的proxy實現

 

 

 

const handler = {
    get: function() {
        console.log('doing');
    }
}

const initialObj = {
    id: 1,
    name: 'cc'
}

const proxiedObj = new Proxy(initialObj, handler);

console.log(proxiedObj.name);複製代碼

 

7、策略模式

策略模式的本意將算法的使用與算法的實現分離開來,避免多重判斷調用哪些算法。適用於有多個判斷分支的場景,如解決表單驗證的問題。

 

 

 

// 對於vip客戶
function vipPrice() {
    this.discount = 0.5;
}
 
vipPrice.prototype.getPrice = function(price) {
  return price * this.discount;
}
// 對於老客戶
function oldPrice() {
    this.discount = 0.3;
}
 
oldPrice.prototype.getPrice = function(price) {
    return price * this.discount;
}
// 對於普通客戶
function Price() {
    this.discount = 1;
}
 
Price.prototype.getPrice = function(price) {
    return price ;
}

// 上下文,對於客戶端的使用
function Context() {
    this.name = '';
    this.strategy = null;
    this.price = 0;
}
 
Context.prototype.set = function(name, strategy, price) {
    this.name = name;
    this.strategy = strategy;
    this.price = price;
}
Context.prototype.getResult = function() {
    console.log(this.name + ' 的結賬價爲: ' + this.strategy.getPrice(this.price));
}

var context = new Context();
var vip = new vipPrice();
context.set ('vip客戶', vip, 200);
context.getResult();   // vip客戶 的結賬價爲: 100

var old = new oldPrice();
context.set ('老客戶', old, 200);
context.getResult();  // 老客戶 的結賬價爲: 60

var Price = new Price();
context.set ('普通客戶', Price, 200);
context.getResult();  // 普通客戶 的結賬價爲: 200複製代碼

 

接下去的幾種模式設計到繼承這方面

8、構造函數模式

  function Car(name, year, country){
    this.name = name;
    this.year = year;
    this.country = country;
  }
  Car.prototype.sayName = function(){
    return this.name;
  }
  var mycar = new Car("BMW", 2017, "Germany");
  console.log(mycar);複製代碼

9、混合模式

 

 

 

function Parent(name){
    this.name = name;
}
Parent.protoType.sayName = function(){
    console.log('parent name:',this.name);
}
Parent.protoType.doSomeThing = function(){
    console.log('parent doSomeThing');
}
function Child(name,fatherName){
    Parent.call(this,faterName);
    this.name = name;
}
Child.protoType = Parent.protoType;
Child.protoType.constructor = Child;
Child.protoType.sayNmae =  function(){
    console.log('child name:',this.name);
}
var child = new Child('son');
child.sayName();
child.doSomeThing();
//通過原型鏈實現對象屬性和方法的繼承,而通過構造函數來實現實例屬性的繼承。複製代碼

 

10、中間者模式

 

 

 

function Parent(name){
    this.name = name;
}
Parent.protoType.sayName = function(){
    console.log('parent name:',this.name);
}
Parent.protoType.doSomeThing = function(){
    console.log('parent doSomeThing');
}
function Child(name,fatherName){
    Parent.call(this,faterName);
    this.name = name;
}
function create(proto){
    function F(){}
    F.proto=proto;
    return new F();
}
Child.protoType = create(Parent.protoType);
Child.protoType.sayNmae =  function(){
    console.log('child name:',this.name);
}
Child.protoType.constructor = Child;
//用F(){}去替代父類執行構造函數
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章