>웹 프론트엔드 >프런트엔드 Q&A >디자인 패턴에 대한 JavaScript 클래식 설명(자세한 예)

디자인 패턴에 대한 JavaScript 클래식 설명(자세한 예)

WBOY
WBOY앞으로
2022-02-08 17:37:281728검색

이 기사는 싱글톤 패턴, 조합 패턴, 관찰자 ​​패턴 등 JavaScript의 디자인 패턴에 대한 관련 지식을 제공합니다. 도움이 되기를 바랍니다.

디자인 패턴에 대한 JavaScript 클래식 설명(자세한 예)

1 디자인 패턴

개념

디자인 패턴은 특정 문제를 해결하기 위해 고안된 최고의 솔루션 집합입니다.
객체 지향 - 객체에 더 많은 주의를 기울입니다. 객체를 정의하고 각 객체에 속성과 메서드를 추가하는 가장 좋은 방법을 찾습니다.
찾은 최고의 솔루션은 디자인 패턴입니다.

다양한 문제에 대해 서로 다른 최상의 솔루션을 제공합니다. 디자인 패턴

일반적인 디자인 패턴:

  • 싱글턴 패턴
  • 컴포지션 패턴
  • 관찰자 패턴
  • 명령 패턴
  • 에이전트 패턴
  • 팩토리 패턴
  • 전략 패턴
  • 어댑터 패턴
  • . . .

1.1 싱글톤 모드

데이터베이스 연결 - 데이터베이스를 작동하려면 여러 기능이 필요함 - 데이터베이스 다시 연결 - 1000개의 기능, 데이터베이스에 1000번 연결

등록 기능, 각 등록은 데이터베이스를 작동해야 함 - 동시에 1000개 time 개인이 등록 중입니다

MySQL 데이터베이스에는 연결 제한이 있습니다. 동시에 최대 200개의 연결만 지원할 수 있습니다.

데이터베이스에 한 번 연결하고 연결을 얻어 여러 번 데이터베이스를 작동합니다. 작동 방법

작동 방법, 데이터베이스 문을 여러 번 실행할 때 동일한 연결을 사용하도록 합니다. - 디자인 패턴을 디자인할 수 있습니다.

디자인 패턴: 클래스를 정의하면 이 새 클래스가 연결을 얻고 데이터베이스 문이 실행될 때마다
싱글턴 모드에서 연결 가져오기에서 이 클래스를 사용할 수 있습니다. 싱글턴 모드: 클래스에서 하나의 개체만 가져올 수 있습니다. 이 클래스를 몇 번 작동하더라도 최종적으로 얻은 모든 연결 개체는 동일한 개체입니다.

클래스에 의해 생성된 모든 객체를 보자. 내부의 모든 속성과 메소드는 정확히 동일합니다. 예를 들어, 클래스를 캡슐화하고 일반적으로 사용되는 일부 작동 기능을 메소드로 배치합니다. 앞으로는 동일한 객체가 매번 이러한 메소드를 호출하는 데 사용됩니다. 일반적으로 클래스에서 생성되는 각 객체는 다릅니다.

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

싱글턴 모드는 두 객체를 동일하게 만드는 것입니다. 즉, 클래스는 항상 하나의 인스턴스 객체만 갖게 됩니다.

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

전역 변수에 노출된 변수 P는 전역 오염을 유발합니다

모든 문제를 해결하려면 클로저를 사용하세요. p 재정의 문제


싱글톤 모드의 핵심 코드:

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

싱글톤 모드의 응용 시나리오는 캡슐화 도구 라이브러리에 있습니다.

예: 도구 라이브러리 캡슐화 및 캡슐화

싱글톤 모드 응용 프로그램 도구 라이브러리 캡슐화

     工具库中会有很多的方法 - 方法每次的使用 应该是同一个对象使用的,而不是应该每次都有一个新对象在使用工具
       // 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 조합 모드

조합 모드는 런처를 만드는 것입니다. 여러 클래스가 인스턴스화되면 동일한 이름의 메서드를 사용하여 시작합니다. 이때 여러 클래스를 함께 시작하는 런처를 만들 수 있습니다.

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

결합 모드 제작 실행기:

class Starter{
    constructor(){
		this.arr = []; // 定义一个数组
    }
    add(className){
        this.arr.push(className); // 将这个多个类放进数组
    }
    run(){
        for(var i=0;i<this.arr.length><p></p>1.4 게시 및 구독 모드<hr>
<h3>https://blog.csdn.net/weixin_44070254/article/details/117574565?spm=1001.2014.3001.5501</h3>
<p>Some 사람들은 구독하고 어떤 사람들은 게시 </p> 게시 구독 패턴: 관찰자가 필요합니다. 관찰자가 관찰된 객체의 상태가 변경되었음을 발견하면 작업을 수행해야 합니다. <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>Observer 패턴이라고도 합니다. 게시-구독 패턴으로. 사람이 어떤 일을 지속적으로 감시하게 한다는 뜻이다. 어떤 일이 어떤 행동을 하려고 할 때 그 사람은 그 행동을 수행하는 기능을 알려준다. <br>예: 이벤트 코드가 작성된 후 이 이벤트는 실제로 페이지에서 사용자의 행동을 지속적으로 모니터링합니다. 사용자가 이 이벤트를 트리거하면 이벤트를 처리하는 함수가 호출됩니다. <p></p>
<pre class="brush:php;toolbar:false">p.addEventListener("click",function(){});
// 这个事件写好以后,就一直在页面中监控用户行为,用户点击这个元素的时候,就调用函数
관찰자 패턴도 비슷한 작업입니다. 관찰자 패턴을 작성하는 목적은 맞춤 이벤트를 요소가 아닌 데이터에 바인딩하는 것입니다.

예: abc 이벤트를 obj에 바인딩

분석:

이벤트를 요소에 바인딩에는 바인딩 방법, 트리거 조건 및 바인딩 해제가 있습니다.

맞춤 이벤트를 개체에 바인딩합니다. 따라서 이 이벤트를 바인딩하는 방법, 트리거하는 방법 및 이벤트 바인딩을 해제하는 방법입니다.

그래서:

이벤트 바인딩을 처리하는 방법이 필요합니다.

    이 이벤트를 트리거하는 방법을 처리할 메서드가 필요합니다.
  • 이 이벤트 바인딩을 해제하는 방법을 처리할 메서드가 필요합니다.
  • 요소의 이벤트, 하나의 이벤트 유형을 여러 핸들러에 바인딩할 수 있습니다.
객체의 사용자 정의 이벤트를 통해 여러 함수를 하나의 이벤트 유형에 바인딩하는 방법입니다.

그래서:

이벤트 유형에 해당하는 처리 기능을 저장하는 공간이 필요합니다.

1.4.1 프로토타입:

class watch{
    bind(){
        
    }
    touch(){
        
    }
    unbind(){
        
    }}var w = new watch();
이때 이 객체에 이벤트와 처리 기능을 바인딩하려면 이벤트 유형과 처리 기능을 매개변수로 요구하므로

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 바인딩

바인딩 메소드에서 매개변수를 수신할지 결정하고 그에 따라 이벤트 유형 및 처리 함수를 저장합니다.

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

이 이벤트에 함수 b를 바인딩하면 원래 a가 덮어쓰여지므로 판단해야 합니다. 먼저 해당 배열에 데이터가 없으면 직접 넣습니다. 있는 경우

bind(type,handle){
    if(!this.obj[type]){
        this.obj[type] = [handle]; // 对象存储方式{"cl":[a]}
    }else{
        this.obj[type].push(handle);
    }  }
를 추가하여 w 객체의 결과를 인쇄합니다.

绑定后的存储结果
디자인 패턴에 대한 JavaScript 클래식 설명(자세한 예)

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="디자인 패턴에 대한 JavaScript 클래식 설명(자세한 예)"></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);}

结果:

带参数的处理函数处理结果
디자인 패턴에 대한 JavaScript 클래식 설명(자세한 예)

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="디자인 패턴에 대한 JavaScript 클래식 설명(자세한 예)"></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)

디자인 패턴에 대한 JavaScript 클래식 설명(자세한 예)

创建被观察者:

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

디자인 패턴에 대한 JavaScript 클래식 설명(자세한 예)


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

위 내용은 디자인 패턴에 대한 JavaScript 클래식 설명(자세한 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제