Heim  >  Artikel  >  Web-Frontend  >  Klassische JavaScript-Erklärung von Entwurfsmustern (detaillierte Beispiele)

Klassische JavaScript-Erklärung von Entwurfsmustern (detaillierte Beispiele)

WBOY
WBOYnach vorne
2022-02-08 17:37:281533Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über Entwurfsmuster in JavaScript, einschließlich Singleton-Muster, Kombinationsmuster, Beobachtermuster usw. Ich hoffe, er wird Ihnen hilfreich sein.

Klassische JavaScript-Erklärung von Entwurfsmustern (detaillierte Beispiele)

1 Entwurfsmuster

Konzept

Entwurfsmuster sind eine Reihe optimaler Lösungen, die zur Lösung eines bestimmten Problems entwickelt wurden.
Objektorientiert – Objekten mehr Aufmerksamkeit schenken – den besten Weg finden, Objekte zu definieren und jedem Objekt Eigenschaften und Methoden hinzuzufügen
Die beste gefundene Lösung ist ein Entwurfsmuster

Für verschiedene Probleme werden wir unterschiedliche haben Die beste Lösung – Entwurfsmuster

Gemeinsame Entwurfsmuster:

  • Singleton-Muster
  • Kompositionsmuster
  • Beobachtermuster
  • Befehlsmuster
  • Agent-Muster
  • Fabrikmuster
  • Strategiemuster
  • Adaptermuster
  • . . .

1.1 Singleton-Modus

Datenbankverbindung – mehrere Funktionen müssen die Datenbank betreiben – Datenbank erneut verbinden – 1000 Funktionen, 1000 Mal eine Verbindung zur Datenbank herstellen

Registrierungsfunktion, jede Registrierung muss die Datenbank betreiben – 1000 gleichzeitig Zeit, in der sich Einzelpersonen registrieren

Die MySQL-Datenbank hat ein Verbindungslimit: Sie kann nur maximal 200 Verbindungen gleichzeitig unterstützen

Wir stellen einmal eine Verbindung zur Datenbank her, stellen eine Verbindung her und betreiben die Datenbank mehrmals. Verwenden Sie diese einzelne Verbindung um es zu bedienen

Wie man es bedient: Lassen Sie mehrere Ausführungen von Datenbankanweisungen dieselbe Verbindung verwenden – wir können ein Entwurfsmuster entwerfen

Entwurfsmuster: Definieren Sie eine Klasse, diese neue Klasse erhält eine Verbindung und jedes Mal, wenn eine Datenbankanweisung ausgeführt wird In der Zukunft ausgeführt, können Sie diese Klasse von verwenden. Eine Verbindung abrufen von
Singleton-Modus: Sie können nur ein Objekt von einer Klasse abrufen – egal wie oft Sie diese Klasse bedienen, alle letztendlich erhaltenen Verbindungsobjekte sind dasselbe Objekt

Lassen Sie alle von einer Klasse erstellten Objekte alle Eigenschaften und Methoden darin genau gleich sein. Kapseln Sie beispielsweise eine Klasse und fügen Sie einige häufig verwendete Betriebsfunktionen als Methoden ein. In Zukunft wird jedes Mal dasselbe Objekt zum Aufrufen dieser Methoden verwendet.

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

Der Singleton-Modus besteht darin, die beiden Objekte gleich zu machen, das heißt, eine Klasse hat immer nur ein Instanzobjekt

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

Variable P, die globalen Variablen ausgesetzt ist, führt zu globaler Verschmutzung

Verwenden Sie Abschlüsse, um jedes Problem zu lösen Problem der Neudefinition von p


Der Kerncode des Singleton-Modus:

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()

Das Anwendungsszenario des Singleton-Modus befindet sich in der Kapselungstoolbibliothek.

Beispiel: Kapseln und kapseln Sie eine Werkzeugbibliothek.

Anwendung im Singleton-Modus. Werkzeugbibliothek kapseln. Nachdem mehrere Klassen instanziiert wurden, verwenden sie zum Starten eine Methode mit demselben Namen. Zu diesem Zeitpunkt können Sie einen Launcher erstellen, um mehrere Klassen gemeinsam zu starten.

     工具库中会有很多的方法 - 方法每次的使用 应该是同一个对象使用的,而不是应该每次都有一个新对象在使用工具

Kombinierter Produktionsstarter:
       // 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.4 Veröffentlichungs- und Abonnementmodus

https://blog.csdn.net/weixin_44070254/article/details/117574565?spm=1001.2014.3001.5501

Manche Leute abonnieren und einige Leute Veröffentlichen

Abonnementmuster veröffentlichen: Es wird ein Beobachter benötigt. Wenn der Beobachter feststellt, dass sich der Zustand des beobachteten Objekts geändert hat, muss er einen Beobachter definieren:
class Carousel{
    init(){
        console.log("轮播图开始运行");
    }}class Tab{
    init(){
        console.log("选项卡开始运行");
    }}class Enlarge{
    init(){
		console.log("放大镜开始运行");
    }}// 这3个类要运行起来需要各自实例化,并调用每个类中的init方法,此时就可以使用组合模式做一个启动器

Beobachtermuster als Publish-Subscribe-Muster. Es bedeutet, dass eine Person eine bestimmte Sache ständig überwacht. Wenn die Sache im Begriff ist, ein bestimmtes Verhalten auszuführen, benachrichtigt die Person eine Funktion, um die Aktion des Verhaltens auszuführen.

Beispiel: Nachdem der Ereigniscode geschrieben wurde, überwacht dieses Ereignis tatsächlich kontinuierlich das Verhalten des Benutzers auf der Seite. Sobald der Benutzer dieses Ereignis auslöst, wird eine Funktion aufgerufen, um das Ereignis zu verarbeiten.

class Starter{
    constructor(){
		this.arr = []; // 定义一个数组
    }
    add(className){
        this.arr.push(className); // 将这个多个类放进数组
    }
    run(){
        for(var i=0;i<this.arr.length><p>Das Beobachtermuster ist eine ähnliche Operation. Der Zweck des Schreibens des Beobachtermusters besteht darin, ein benutzerdefiniertes Ereignis an Nichtelementdaten zu binden. <br><br>Beispiel: Binden Sie ein abc-Ereignis an ein Objekt. </p>
<p>Analyse: </p>
<p>Binden Sie ein Ereignis an ein Element. Es gibt Bindungsmethoden, Auslösebedingungen und Entbindung. </p>
<p>Binden Sie ein benutzerdefiniertes Ereignis an ein Objekt. Also, wie man dieses Ereignis bindet, wie man es auslöst und wie man die Bindung dieses Ereignisses aufhebt. </p>
<p>Also: </p>
<p></p>Sie benötigen eine Methode zur Handhabung der Ereignisbindung. <p></p>Benötigen Sie eine Methode, um zu handhaben, wie dieses Ereignis ausgelöst wird. <p></p>Benötigen Sie eine Methode, um die Bindung dieses Ereignisses aufzuheben. <p></p>
<ul>Ereignisse von Elementen, ein Ereignistyp kann an mehrere Handler gebunden werden. <li>So binden Sie mehrere Funktionen durch benutzerdefinierte Ereignisse von Objekten an einen Ereignistyp. <li>Also: <li> benötigt einen Platz zum Speichern der dem Ereignistyp entsprechenden Verarbeitungsfunktionen. </ul>
<p>1.4.1 Prototyp: </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><p>Wenn Sie zu diesem Zeitpunkt Ereignisse und Verarbeitungsfunktionen an dieses Objekt binden möchten, sind der Ereignistyp und die Verarbeitungsfunktion als Parameter erforderlich, sodass beim Aufruf von </p>
<pre class="brush:php;toolbar:false">p.addEventListener("click",function(){});
// 这个事件写好以后,就一直在页面中监控用户行为,用户点击这个元素的时候,就调用函数
die tatsächlichen Parameter übergeben werden müssen

1.4.2 Bindung Bestimmen Sie

, um Parameter in der Bindungsmethode zu empfangen, und speichern Sie den Ereignistyp und die Verarbeitungsfunktion entsprechend:

class watch{
    bind(){
        
    }
    touch(){
        
    }
    unbind(){
        
    }}var w = new watch();

Wenn Sie eine Funktion b an dieses Ereignis binden, wird das ursprüngliche a überschrieben, daher sollten Sie dies beurteilen Erstens: Wenn das entsprechende Array keine Daten enthält, fügen Sie diese direkt ein. Wenn ja, fügen Sie

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");}

hinzu, um das Ergebnis des w-Objekts auszudrucken:

绑定后的存储结果
Klassische JavaScript-Erklärung von Entwurfsmustern (detaillierte Beispiele)

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="Klassische JavaScript-Erklärung von Entwurfsmustern (detaillierte Beispiele)"></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);}

结果:

带参数的处理函数处理结果
Klassische JavaScript-Erklärung von Entwurfsmustern (detaillierte Beispiele)

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="Klassische JavaScript-Erklärung von Entwurfsmustern (detaillierte Beispiele)"></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)

Klassische JavaScript-Erklärung von Entwurfsmustern (detaillierte Beispiele)

创建被观察者:

// 创建被观察者
    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('玩游戏')

Klassische JavaScript-Erklärung von Entwurfsmustern (detaillierte Beispiele)


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学习教程

Das obige ist der detaillierte Inhalt vonKlassische JavaScript-Erklärung von Entwurfsmustern (detaillierte Beispiele). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen