Maison  >  Article  >  interface Web  >  Explication classique JavaScript des modèles de conception (exemples détaillés)

Explication classique JavaScript des modèles de conception (exemples détaillés)

WBOY
WBOYavant
2022-02-08 17:37:281533parcourir

Cet article vous apporte des connaissances pertinentes sur les modèles de conception en JavaScript, notamment le modèle singleton, le modèle de combinaison, le modèle d'observateur, etc. J'espère qu'il vous sera utile.

Explication classique JavaScript des modèles de conception (exemples détaillés)

1 Design Pattern

Concept

Le Design Pattern est un ensemble de solutions optimales conçues pour résoudre un certain problème.
Orienté objet - faites plus attention aux objets - trouvez la meilleure façon de définir les objets et d'ajouter des propriétés et des méthodes à chaque objet
La meilleure solution trouvée - est un modèle de conception

Pour différents problèmes, nous aurons différents La meilleure solution - Modèles de conception

Modèles de conception courants :

  • Modèle Singleton
  • Modèle de composition
  • Modèle d'observateur
  • Modèle de commande
  • Modèle d'agent
  • Modèle d'usine
  • Modèle de stratégie
  • Modèle d'adaptateur
  • . . .

1.1 Mode Singleton

Connexion à la base de données - plusieurs fonctions doivent faire fonctionner la base de données - reconnecter la base de données - 1000 fonctions, se connecter à la base de données 1000 fois

Fonction d'enregistrement, chaque inscription doit faire fonctionner la base de données - 1000 en même temps heure Les individus s'inscrivent

La base de données MySQL a une limite de connexion : elle ne peut prendre en charge qu'un maximum de 200 connexions en même temps

Nous nous connectons à la base de données une fois, obtenons une connexion et exploitons la base de données plusieurs fois. pour le faire fonctionner

Comment faire fonctionner, laissez plusieurs exécutions d'instructions de base de données utiliser la même connexion - nous pouvons concevoir un modèle de conception

Modèle de conception : définissez une classe, cette nouvelle classe obtiendra une connexion, et chaque fois qu'une instruction de base de données est exécuté à l'avenir, vous pourrez utiliser cette classe à partir d'Obtenir une connexion depuis
Mode Singleton : vous ne pouvez obtenir qu'un seul objet d'une classe - peu importe le nombre de fois que vous utilisez cette classe, tous les objets de connexion finalement obtenus sont le même objet

Laissez tous les objets créés par une classe, toutes les propriétés et méthodes à l'intérieur sont exactement les mêmes. Par exemple, encapsulez une classe et placez certaines fonctions d'exploitation couramment utilisées comme méthodes. À l'avenir, le même objet sera utilisé pour appeler ces méthodes à chaque fois. Normalement, chaque objet créé par une classe est différent.

class Carousel{
    }var a = new Carousel();var b = new Carousel();console.log(a === b); // false

Le mode singleton consiste à rendre les deux objets identiques, c'est-à-dire qu'une classe n'aura toujours qu'un seul objet instance

var single = (function(){
    class Carousel{
       
    }
    var res = undefined;
    return function(){
        if(!res){
           res = new Carousel();
        }
        return res;
    }})();var s1 = single();var s2 = single();console.log(s1 === s2); // true

La variable P exposée aux variables globales provoquera une pollution globale

Utilisez des fermetures pour résoudre chaque problème. problème de redéfinition de p


Le code de base du mode singleton :

function Person(){}function fn(Person){
    var p;
    return function(){
        if(!p){
            p = new Person;
        }
        return p;
    }}var f = fn(Person)var p1 = f()var p2 = f()

Le scénario d'application du mode singleton se trouve dans la bibliothèque de l'outil d'encapsulation.

Exemple : Encapsuler et encapsuler une bibliothèque d'outils

Application en mode Singleton Encapsuler une bibliothèque d'outils

     工具库中会有很多的方法 - 方法每次的使用 应该是同一个对象使用的,而不是应该每次都有一个新对象在使用工具
       // var t = new Tool;
        // t.setCookie('username', 'zs', 20);
        const Tool = (function () {
            class Tool {
                constructor() {
                    if (window.getComputedStyle) {
                        this.flag = true;
                    } else {
                        this.flag = false;
                    }
                }
                /获取节点属性                getStyle(ele, attr) {
                    if (this.flag) {
                        return window.getComputedStyle(ele)[attr];
                    } else {
                        return ele.currentStyle[attr];
                    }
                }

                getStyle(ele, attr) {
                     尝试一段代码   不知道会不会报错
                     尝试成功 后面代码没有什么事
                    尝试失败 会报错 被cathch 捕获到  会将错误信息放到err参数里  catch{} 里可以处理这个错误 也可以不处理这个错误对上面的错误代码进行补救  错误不会再浏览器里报错                    try {
                        return window.getComputedStyle(ele)[attr];
                    } catch (err) {
                        return ele.currentStyle[attr];
                    }
                }
                // 设置节点css属性
                setStyle(ele, styleObj) {
                    for (let attr in styleObj) {

                        ele.style[attr] = styleObj[attr];
                    }
                }
                // 设置cookie
                setCookie(key, value, second, path = '/') {
                    let data = new Date();
                    date.setTime(date.getTime() - 8 * 3600 * 1000 + second * 1000);
                    document.cookie = `${key}=${value};expires=${date};path=${path}`;
                }
            }
            var tool;
            return (function () {
                if (!tool) {
                    tool = new Tool();
                }
                return tool;
            })();
        })();

1.3 Mode combinaison

Le mode combinaison consiste à créer un lanceur. Une fois que plusieurs classes sont instanciées, elles utilisent une méthode du même nom pour démarrer. À ce stade, vous pouvez créer un lanceur pour démarrer plusieurs classes ensemble.

class Carousel{
    init(){
        console.log("轮播图开始运行");
    }}class Tab{
    init(){
        console.log("选项卡开始运行");
    }}class Enlarge{
    init(){
		console.log("放大镜开始运行");
    }}// 这3个类要运行起来需要各自实例化,并调用每个类中的init方法,此时就可以使用组合模式做一个启动器

Lanceur de production en mode combiné :

class Starter{
    constructor(){
		this.arr = []; // 定义一个数组
    }
    add(className){
        this.arr.push(className); // 将这个多个类放进数组
    }
    run(){
        for(var i=0;i<this.arr.length><p></p>1.4 Mode publication et abonnement<hr>
<h3>https://blog.csdn.net/weixin_44070254/article/details/117574565?spm=1001.2014.3001.5501</h3> <p>Certaines personnes s'abonnent et d'autres publier </p> Modèle d'abonnement de publication : un observateur est nécessaire. Une personne observée est nécessaire. Si l'observateur constate que l'état de l'objet observé a changé, il doit définir une tâche : <p></p>
<pre class="brush:php;toolbar:false">class Observer{
    // 观察者有名字和任务
    constructor(name,task){
        this.name = name        this.task = task    }}// 定义班主任var bzr = new Observer('班主任',function(state){
    console.log("因为"+state+",所以"+this.name+"罚站");})// 定义了一个年级主任var zr = new Observer('年级主任',function(state){
    console.log("因为"+state+",所以"+this.name+"要找班主任");})// 被观察者class Subject{
    // 有自己的状态
    constructor(state){
        this.state = state        // 观察者们
        this.observer = [];
    }
    // 添加被观察者
    add(...arr){
        this.observer = this.observer.concat(arr)
    }
    // 改变状态
    changeSate(state){
        this.state = state        // 触发观察者的任务
        for(let i=0;i<this.observer.length><br>Modèle d'observateur, également connu. comme modèle de publication-abonnement. Cela signifie qu'une personne surveille constamment une certaine chose lorsque la chose est sur le point d'exécuter un certain comportement, la personne notifiera une fonction pour exécuter l'opération du comportement. <br>Exemple : Une fois le code de l'événement écrit, cet événement surveille en permanence le comportement de l'utilisateur sur la page. Une fois que l'utilisateur déclenche cet événement, une fonction est appelée pour gérer l'événement. <p></p>
<pre class="brush:php;toolbar:false">p.addEventListener("click",function(){});
// 这个事件写好以后,就一直在页面中监控用户行为,用户点击这个元素的时候,就调用函数
Le modèle d'observateur est une opération similaire. Le but de l'écriture du modèle d'observateur est de lier un événement personnalisé à des données non-élémentaires.

Exemple : lier un événement abc à un obj

Analyse :

Lier un événement à un élément. Il existe des méthodes de liaison, des conditions de déclenchement et une dissociation.

Liez un événement personnalisé à un objet. Alors, comment lier cet événement, comment le déclencher et comment dissocier cet événement.

Donc :

Besoin d'une méthode pour gérer la liaison d'événement.

    Besoin d'une méthode pour gérer comment déclencher cet événement.
  • Besoin d'une méthode pour gérer comment dissocier cet événement.
  • Événements d'éléments, un type d'événement peut être lié à plusieurs gestionnaires.
Comment lier plusieurs fonctions à un type d'événement via des événements personnalisés d'objets.

Donc :

nécessite un espace pour stocker les fonctions de traitement correspondant au type d'événement.

1.4.1 Prototype :

class watch{
    bind(){
        
    }
    touch(){
        
    }
    unbind(){
        
    }}var w = new watch();
À ce stade, si vous souhaitez lier des événements et des fonctions de traitement à cet objet, le type d'événement et la fonction de traitement sont requis comme paramètres, donc les paramètres réels doivent être transmis lors de l'appel de

var w = new watch();w.bind("cl",a); // 给w对象绑定cl事件类型,执行a函数w.bind("cl",b); // 给w对象绑定cl事件类型,执行b函数function a(){
    console.log("事件处理函数a");}function b(){
    console.log("事件处理函数b");}

1.4.2 Liaison Déterminez

pour recevoir des paramètres dans la méthode de liaison et stockez le type d'événement et la fonction de traitement en conséquence :

constructor(){
    this.obj = {} // 存储格式:{事件类型:[函数1,函数2]}}bind(type,handle){
    this.obj[type] = [handle]; // 对象存储方式{"cl":[a]}}

Si vous liez une fonction b à cet événement, l'original a sera écrasé, vous devez donc juger d'abord, s'il n'y a pas de données dans le tableau correspondant, mettez-les directement s'il y en a, ajoutez

bind(type,handle){
    if(!this.obj[type]){
        this.obj[type] = [handle]; // 对象存储方式{"cl":[a]}
    }else{
        this.obj[type].push(handle);
    }  }
pour imprimer le résultat de l'objet w :

.

绑定后的存储结果
Explication classique JavaScript des modèles de conception (exemples détaillés)

1.4.3 触发

触发这个事件需要传入触发哪个事件类型

touch(type){
    // 首先要判断,这个事件类型是否绑定,没有绑定不能触发
    if(!this.obj[type]){
        return false;
    }else{
        // 将这个事件的所有绑定的处理函数一起调用
        for(var i=0;i<this.obj><p>测试:</p>
<table>
<thead><tr class="firstRow"><th>触发测试</th></tr></thead>
<tbody>
<tr><td><img src="https://img.php.cn/upload/article/000/000/067/723219bbf42dba49705fd0fe49beab7d-1.png" alt="Explication classique JavaScript des modèles de conception (exemples détaillés)"></td></tr>
<tr><td><br></td></tr>
</tbody>
</table>
<p>这两个处理函数都没有参数,如果要传入参数的时候该怎么处理?</p>
<p>触发事件的时候就要传入实参</p>
<pre class="brush:php;toolbar:false">w.touch("cl","张三",20);

触发事件的方法就应该处理这些参数

touch(type,...arr){ // 因为参数不定长,所以使用合并运算符
    // 首先要判断,这个事件类型是否绑定,没有绑定不能触发
    if(!this.obj[type]){
        return false;
    }else{
        // 处理参数:模拟系统事件的参数事件对象,将所有参数都集中在一个对象中
        var e = {
            type:type,
            args:arr        }
        // 将这个事件的所有绑定的处理函数一起调用
        for(var i=0;i<this.obj><p>添加一个带参数的处理函数,并触发事件执行:</p>
<pre class="brush:php;toolbar:false">w.bind("cl",c); // 给w对象绑定cl事件类型,执行c函数w.touch("cl","张三",20);function c(e){
    console.log("我是处理函数c,打印:姓名"+e.name+",年龄"+e.age);}

结果:

带参数的处理函数处理结果
Explication classique JavaScript des modèles de conception (exemples détaillés)

1.4.5 解绑

解绑也需要知道解绑的事件类型和处理函数

unbind(type,handle){
    // 先判断是否绑定了这个事件
    if(!this.obj[type]){
        return false;
    }else{
        // 从数组中将这个处理函数删除
        for(var i=0;i<this.obj><p>解绑测试:</p>
<table>
<thead><tr class="firstRow"><th>解绑测试结果</th></tr></thead>
<tbody>
<tr><td><img src="https://img.php.cn/upload/article/000/000/067/723219bbf42dba49705fd0fe49beab7d-3.png" alt="Explication classique JavaScript des modèles de conception (exemples détaillés)"></td></tr>
<tr><td><br></td></tr>
</tbody>
</table>
<p>如果绑定事件的时候使用的匿名函数,就无法进行解绑了,所以再添加一个解绑事件所有处理函数的方法:</p>
<pre class="brush:php;toolbar:false">clear(type){
    if(!this.obj[type]){
        return false;
    }else{
        // 直接从对象中将这个属性删除
        delete this.obj[type];
    } }

1.5 观察者模式

观察者模式跟发布订阅模式不一样的地方在于,要有观察者和被观察者。

创建观察者:

// 创建观察者class Observer{
    // 观察者有姓名和技能 - 技能是一个函数
    constructor(name,skill){
        this.name = name;
        this.skill = skill    }}// 创建观察者var bzr = new Observer('班主任',function(state){
    console.log('因为'+state+'叫家长')})var xz = new Observer('校长',function(state){
    console.log('因为'+state+'叫班主任')})console.log(bzr,xz)

Explication classique JavaScript des modèles de conception (exemples détaillés)

创建被观察者:

// 创建被观察者
    class Subject{
        // 被观察者有状态 和 观察者列表
        constructor(state){
            this.state = state            this.observers = []
        }
        // 添加观察者
        addObserver(observer){
            var index = this.observers.findIndex(v=>v === observer)
            if(index{
                    v.skill(this.state)
                })
            }
        }
        // 删除观察者
        delObserver(observer){
            var index = this.observers.findIndex(v=>v === observer)
            if(index>=0){
                this.observers.splice(index,1)
            }
        }
    }
    // 创建被观察者
    var xm = new Subject('学习')
    // 添加观察者
    xm.addObserver(bzr)
    xm.addObserver(xz)
    xm.addObserver(bzr)
    console.log(xm)
    // 改变状态
    xm.setState('玩游戏')

Explication classique JavaScript des modèles de conception (exemples détaillés)


1.6 策略模式

一个问题有多种解决方案,且随时还可以有更多的解决方案,就是策略模式。例如:一个商品在售卖的时候,会有多种折扣方式,慢100减10元,满200减30元等…

商品活动:
满100减10
满200减30
满300打8折

策略模式:将折扣放在闭包中保存起来 - 通过闭包对折扣进行增删改查操作

正常的函数表达方式:

function fn(type,price){
    if(type === '100_10'){
       return price -= 10
    }else if(type === '200_30'){
       return price -= 0
    }else{
        return '没有这种折扣'
    }}fn('100_10',160)

这种方式,在添加折扣或删除折扣的时候总是需要修改原函数。

策略模式代码:

var calcPrice = (function(){
    // 以闭包的形式存储折扣数据
    var sale = {
        '100_10':function(price){
            return price -= 10
        },
        '200_20':function(price){
            return price -= 20
        }
    }
    function calcPrice(type,price){
        // 闭包中使用折扣
        if(type in sale){
            return sale[type](price)
        }else{
            return '没有这个折扣'
        }
    }
    // 折扣函数添加属性 - 添加折扣
    calcPrice.add = function(type,fn){
        if(type in sale){
            console.log('折扣存在')
        }else{
            sale[type] = fn        }
    }
    // 删除折扣
    calcPrice.del = function(type){
        if(type in sale){
            delete sale[type]
        }else{
            console.log('折扣不存在')
        }
    }
    return calcPrice})()var p = calcPrice('100_10',200)calcPrice.add('200_320',function(price){
    return price -= 50})calcPrice.del('200_330')var p = calcPrice('200_320',200)console.log(p)

相关推荐:javascript学习教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer