【JS】Javascript设计模式初窥(一)

注:部分代码及名词摘自《Javascript设计模式》,《设计模式:可复用面向对象的软件基础》

什么是设计模式?

设计模式是解决程序设计中的常见问题的可复用方案,是编写出美观、结构化和组织良好代码代码的前提,其三法则为适合性、实用性、适用性,以下代码均采用ES6语法

一 、模块模式

 对象拥有共有/私有方法和变量,屏蔽全局作用域中特殊的部分,降低冲突

const testModule = (function() {
    // 私有变量
    let count = 0

    // 私有函数
    const privateFn = () => {
        console.log("log...")
    }
    
    // 公有属性和方法,通过一个立即执行函数闭合代码 return 公有API
    return {
        type: "num: ", 
        Fn: privateFn // 私有函数的公有形式别名
        add: () => ++count,
        get: () => {
            // 执行私有方法并返回私有变量
            return privateFn(), count
        }
    }
})()

testModule.add()
console.log(testModule.type + testModule.get()) // -> num: 1

 只有模块才能享受私有函数,可执行UA测试,针对不同情况例如兼容IE只需提供一个对应的代码路径

增强:Mixed(引入混出)

const testModule = (function(_JQ) {
    _JQ.fn.extend({
        alertWhileClick: function () {
            $(this).click(function () {
                alert($(this).val());
            });
        }
    });

    return _JQ
})(jQuery)

改进:揭示模块模式

const testModule = (function() {

    let privateName = "yun"
        publicSex   = "Ms."
   
    function publicGetName(){
        privateFun()
    }

    function privateFun(){
        return privateName
    }

    function publicSetName(sName){
        privateName = sName
    }
    
    // 将暴露的公有指针指向到私有函数和属性上
    return {
       get: publicGetName,
       set: publicSetName,
       greeting: publicSex 
    }
})()

封装更加简洁,并且支持私有数据,在模块中代码的公有部分能访问私有部分,外界则无法接触类的私有部分。

二、单例模式

限制类的实例化次数只能为一,已存在的情况下简单返回对对象的引用

const mySingleton = (function() {
    // 保存对象的引用
    let instance;
    
    function init() {
        // 私有属性及方法
        let privateNum = Math.random()
        const privateFun = () => privateNum

        // 对外暴露的公有属性及方法
        return {
            type: "Number",
            getNum: privateFun
        }
    }

    return {
        // 获取判断,不存在则初始化赋值,存在即简单返回引用
        getInstance: () => {
            if(!instance){
                instance = init()
            }

            return instance
        }
    }
})()

const singleA = mySingleton.getInstance()
const singleB = mySingleton.getInstance()

// 判断两次值为一样则成功
console.log(singleA .getNum() == singleB.getNum()) // -> true  

延迟构建:协调对象

const mySingleton = (function() {
    // 模拟初始化
    function Penson(options) {
        options = options || {}
        this.name = "yun"
        this.friend = options.friend || "liu"
    }

    let instance;

    // 静态属性
    let _static = {
        type: "Object",
        getInstance: (options) => {
            if(!instance){
                instance = new Penson(options)
            }

            return instance
        }
    }

    return _static
})()
const singleA = mySingleton.getInstance({
     friend: "touda"
})
console.log(singleA.friend) // -> touda

需要一个对象来协调其他对象,加强紧密耦合

二、观察者模式

一个对象维持一系列依赖于它的对象,负责通知任何变更的状态

  1. Subjie (目标)

  2. Observer (观察者)

  3. ConcreteSubject (具体目标) 

  4. ConcreteObserver (具体观察者)

/*
* 1. 模拟一个目标可能拥有的一系列依赖Observer
* 2. 模拟目标在观察者列表上添加、删除、通知的能力
* 3. 定义一个框架来创建新的Observer
*/

// 观察者列表
function ObserverList() {
    this.list = []
}

// 行为列表
ObserverList.prototype.add = function(value) {
    this.list.push(value)
}

ObserverList.prototype.get = function(index) {
    return this.list[index]
}

ObserverList.prototype.count = function() {
    return this.list.length
}


// 使用extension扩展对象
function extend(object, extension) {
    for (const key in object) {
        extension[key] = object[key]
    }
}

// 为对象添加属性形成链式调用并分隔原型方法
function Observer() {

    // 分配行为
    this.update = function () {
        // ...
    }
}

// 目标
function Subject(){
    this.observers = new ObserverList()
}

Subject.prototype.addObserver = function(oElm) {
    this.observers.add(oElm)
}

Subject.prototype.Notify = function(context) {
    for (let index = 0; index < this.observers.count(); index++) {
        this.observers.get(index).update(context)  //获取具体观察者执行update属性方法
    }
}
<button id="add">Add</button>

<input type="checkbox" id="control">
<label for="control">全选</label>

<div id="container"></div>
let checkbox  = document.getElementById("control"),
    container = document.getElementById("container"),
    addBtn    = document.getElementById("add");

// 利用Subject扩展checkbox为目标
extend(new Subject(), checkbox)

// 通知到观察者
checkbox.onclick = ({target}) => {
    checkbox.Notify(target.checked)
}

addBtn.onclick = addNewObserver

function addNewObserver() {
    // 创建新的checkbox
    let check = document.createElement("input")
    check.type = "checkbox"
    
    // 利用Observer扩展checkbox
    extend(new Observer(), check)
    
    // 自定义更新行为
    check.update = function(value){
        this.checked = value
    }
    
    // 添加新的观察者并附件到容器
    checkbox.addObserver(check)
    container.appendChild(check)
}

.....未完待续

 

 

 

 

                   

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值