几种常用设计模式的简单示例

简介: 模式是在某一背景下某个问题的一种解决方案。

9.png


前言


模式是在某一背景下某个问题的一种解决方案。


设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。


为了保证代码的可靠性、提高代码的复用率、使代码更容易被维护和阅读,我们需要了解并合理使用设计模式。


日常开发中,一些特定的场景下你的处理方法可能并不是很理想,往往这时借助一些设计模式可以让你优雅而高效的实现这些逻辑,下面就介绍一些虽然不是最全的但一定是最常用的设计模式。


单例模式:


定义:一个类只返回一个实例,一旦创建再次调用就直接返回。


使用场景:比如自定义弹窗,无论你程序中多少调用,都只应创建一个弹窗对象。


class CreateUser {
    constructor(name) {
        this.name = name;
        this.getName();
    }
    getName() {
        return this.name;
    }
};
const ProxyMode = (() => {
    let instance = null;
    return (name) => {
        if(!instance) {
            instance = new CreateUser(name);
        }
        return instance;
    }
})();
let a = ProxyMode('vn');
let b = ProxyMode('lb');
console.log(a, b);   // vn  vn    单例模式只会创建一次实例


策略模式:


定义:定义一个策略类只专注与各方法算法实现,定义一个接口调用这些方法。


特点:代码优雅,可读性高。


// 策略类
const levelObj = {
    "A": money => money * 4,
    "B": money => money * 3,
    "C": money => money * 2
}
// 环境类  封装调用接口
const getMoney = (level, money) => levelObj[level](money);
console.log(getMoney('A', 200))   // 800


代理模式:


定义:为一个对象提供一个代用品或占位符,以便控制对它的访问。


使用场景:比如图片懒加载,先缓存动态 loading,必要时传入 src。


const imgFunc = (() => {
    let imgNode = document.createElement('img');
    document.body.appendChild(imgNode);
    return {
        setSrc: (src) => {
            imgNode.src = src;
        }
    }
})();
const ProxyImg = (() => {
    let img = new Image();
    img.onload = () => {
        let node = document.getElementsByTagName('img')
        imgFunc.setSrc(img.src);
    }
    return {
        setSrc: (src) => {
            imgFunc.setSrc('../C3photo/jacky/1.jpg');
            img.src = src;
        }
    }
})();
ProxyImg.setSrc('../C3photo/jacky/2.jpg');


装饰者模式:


定义:装饰者模式能够在不改变对象自身的基础上,在运行程序期间给对象动态地添加职责。


使用场景:类似于拦截器,添加对象的前置和后置事件等。


Function.prototype.before = function(beforefn) {
    let _self = this;                          
    return function () {
        beforefn.apply(this, arguments);
        return _self.apply(this, arguments);
    }
}
Function.prototype.after = function(afterfn) {
    let _self = this;
    return function(){
        let ret = _self.apply(this, arguments);
        afterfn.apply(this, arguments);
        return ret;
    }
}
let func = function() {
    console.log('2');
}
//func1和func3为挂载函数
let func1 = function() {
    console.log('1');
}
let func3 = function() {
    console.log('3');
}
func = func.before(func1).after(func3);
func();   // 1  2  3


发布订阅模式:


定义:订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event  Channel),当发布者(Publisher)发布该事件(Publish  Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。


使用场景:微信公众号的订阅


let eventEmitter = {
    list: {}, 
    on(event, fn) {
        // 订阅
        let _this = this;
        _this.list[event] = _this.list[event] || [];
        _this.list[event].push(fn);
        return _this;
    },
    emit() {
        // 发布
        let _this = this;
        let event = [].shift.call(arguments),
            fns = _this.list[event];
        if (fns && fns.length) {
            fns.forEach((fn) => fn.apply(_this, arguments));
        }
        return _this;
    },
    off(event, fn) {
        // 取消订阅
        let _this = this;
        let fns = _this.list[event];
        if (!fns) return false;
        if (!fn) {
            fns.length = 0;
        } else {
            for (let i = 0; i < fns.length; i++) {
                if (fns[i] === fn || fns[i].fn === fn) {
                    fns.splice(i, 1);
                    break;
                }
            }
        }
    }
};
const user1 = (content) => {
    console.log("用户1订阅了:", content);
};
const user2 = (content) => {
    console.log("用户2订阅了:", content);
};
const user3 = (content) => {
    console.log("用户3订阅了:", content);
};
// 订阅
eventEmitter.on("article1", user1);
eventEmitter.on("article1", user2);
eventEmitter.on("article2", user3);
eventEmitter.emit("article1", "Javascript 发布-订阅模式");
eventEmitter.emit("article2", "Javascript 观察者模式");
eventEmitter.off("article1", user1);
eventEmitter.emit("article1", "Javascript 发布-订阅模式");
//用户1订阅了: Javascript 发布-订阅模式
//用户2订阅了: Javascript 发布-订阅模式
//用户3订阅了: Javascript 观察者模式
//用户2订阅了: Javascript 发布-订阅模式


总结


学习设计模式不仅可以使我们用好这些成功的设计模式,更重要的是可以使我们深入理解面向对象的设计思想。


~本文完,感谢阅读!


学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!


你来,怀揣期望,我有墨香相迎! 你归,无论得失,唯以余韵相赠!


知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!




相关文章
|
6月前
|
设计模式 Java 数据库连接
【重温设计模式】代理模式及其Java示例
【重温设计模式】代理模式及其Java示例
|
3月前
|
设计模式 存储 Java
掌握Java设计模式的23种武器(全):深入解析与实战示例
掌握Java设计模式的23种武器(全):深入解析与实战示例
|
6月前
|
设计模式 Java 数据库连接
【重温设计模式】代理模式及其Java示例
【重温设计模式】代理模式及其Java示例
60 2
|
设计模式 存储 算法
Java 23种设计模式介绍以及代码示例 第三篇行为型设计模式
使用行为型设计模式可以帮助我们更好地组织和管理对象之间的交互行为,提高代码的可重用性、可扩展性和维护性。下面是一些在Java中使用行为型设计模式的理由: 1. 利于代码的重用:通过使用行为型设计模式,我们可以将通用的行为逻辑封装到可重用的组件中,减少重复编写代码的工作量。 2. 降低耦合度:行为型设计模式将对象之间的交互行为解耦,使得各个对象之间的依赖性降低,从而提高了系统的灵活性和可维护性。 3. 提高代码的可扩展性:通过使用行为型设计模式,我们可以方便地添加新的行为或修改现有的行为,而不需要修改已有的代码,减少了对原有代码的影响。 4. 提高代码的可读性:行为型设计模式将不同的行为
75 0
|
设计模式 缓存 Java
Java 23种设计模式介绍以及代码示例 第二篇结构型设计模式
结构型设计模式是一种在软件开发中常用的设计模式之一,它可以帮助我们更好地组织和管理代码结构,使得代码更加灵活、可扩展和易于维护。以下是使用结构型设计模式的一些主要原因: 1. 解耦和组件化:结构型设计模式可以帮助我们解耦各个组件之间的依赖关系,使得它们可以独立地进行修改、扩展和重用。这样使得系统的不同部分可以以更高的内聚性和低耦合性组合在一起,促进了系统的模块化和组件化。
56 0
|
设计模式 Java
Java 23种设计模式介绍以及代码示例 第一篇创建型设计模式
代码组织和可读性:创建型设计模式提供了一种结构化的方式来组织代码,使得代码更加清晰、易读。它们定义了对象的创建和使用的规范,从而使代码逻辑更加明确,易于理解和维护。 2. 对象创建的灵活性和可扩展性:创建型设计模式将对象创建的过程抽象出来,通过使用相应的模式,可以在不修改现有代码的情况下,改变对象的创建方式或者增加新的对象创建方式。这提供了一定的灵活性和可扩展性,使得系统更易于扩展和维护。
107 0
|
设计模式 Java API
Java 外观设计模式讲解和代码示例
Java 外观设计模式讲解和代码示例
74 0
|
设计模式 API Python
Python 外观设计模式讲解和代码示例
Python 外观设计模式讲解和代码示例
61 0
|
设计模式 算法 安全
C++常用的11种设计模式解释及示例
C++常用的11种设计模式解释及示例
|
设计模式 缓存 算法
Java设计模式:深入解析与应用示例
引言 设计模式是一种在特定上下文中反复出现的可重用解决方案,用于处理软件设计中常见的问题。掌握设计模式不仅可以帮助我们编写出更优雅、更易于理解和维护的代码,而且也是Java面试中的常考知识点。在本文中,我们将探讨几种常见的设计模式,包括它们的定义、使用场景和Java实现。
293 0
下一篇
无影云桌面