게시/구독 모드 초기 탐색

8854 단어
  • 소스 코드가 필요한 경우 여기를 클릭
  • 소프트웨어 개발은 일부 실제 문제를 해결하는 데 쓰이는 것으로 서로 다른 실제 문제에 대해 서로 다른 해법을 가질 수 있다.이러한 해법을 추출하고 추상적으로 소프트웨어 공학에 응용하면 디자인 모델이 형성된다.게시/구독 모드는 제가 Vue 쌍방향 데이터 귀속의 원리를 볼 때 접한 것입니다. 여러분들이 Vue 쌍방향 데이터 귀속의 원리를 분석할 때 게시/구독 모드를 언급할 것입니다. 저는 이전에 이런 디자인 모드를 배운 적이 없기 때문에 그 글들은 이해할 수 없습니다.그래서 저는 발표/구독 모델의 실현 원리를 먼저 보고 뒤에 공부를 하기로 했습니다. 그래서 이 요약도 했습니다.
    게시/구독 모드의 현실 모델
    게시/구독 모드가 현실에서 가장 흔히 볼 수 있는 응용은 신문과 잡지를 구독하고 우유와 꽃 등 장면을 구독하는 것이다.신문 잡지를 구독하는 것을 예로 들면, 만약 당신이 어떤 간행물에 관심이 있다면, 잡지사에 가서 그것들을 구독할 수 있다. 구독한 간행물이나 잡지가 새로운 간행물이 나오면, 잡지 사회는 최신 간행물을 집까지 배달해 준다.이것이 바로 생활 속에서 흔히 볼 수 있는 게시/구독 모델입니다. 이 모델에서 당신은 구독자이고 잡지사는 게시자입니다.전단 개발에서 발표/구독 모델은 가장 광범위하게 응용되는 모델이라고 할 수 있지만 우리가 의식하지 못했을 뿐이다.가장 일반적인 응용 프로그램은 이벤트 처리 함수보다 낫다.
    document.addEventListener("click",(e) => console.log("memeda~"));
    
    우리는 document에 클릭 이벤트를 추가했는데 클릭 이벤트를 구독했고 클릭 이벤트가 터치될 때 우리가 전송한 리셋 함수를 호출하는 것으로 이해할 수 있다.이곳의 구독자는 document 대상이고 게시자는 브라우저의 이벤트 조회이다. 브라우저가 이벤트 조회를 진행할 때document 대상의 클릭 이벤트가 터치된 것을 발견하면 해당 대상에게 알리고 귀속 이벤트에 전송된 답장 수를 실행한다.
    게시/구독 모드에서 해결된 문제
    위에서 신문을 구독하는 것을 예로 들면, 당신이 어떤 신문을 구독한 후, 매일 잡지사에 가서 새로 나온 잡지가 있는지 없는지를 볼 필요가 없고, 잡지사가 새로운 잡지를 낸 후에 잡지를 집 앞까지 배달할 필요가 있다.만약 아직도 많은 사람들이 당신과 함께 이 신문을 구독한다면, 만약 이 사람들이 매일 잡지사에 가서 자신이 구독한 신문이 갱신되었는지 물어보면 사용자와 잡지사에 모두 혼란스러울 것이다.따라서 게시/구독 모델이 해결하는 첫 번째 문제는 주동적으로 전송하는 메커니즘을 실현한 것이다. 구독자는 발표자의 소식이 업데이트되었는지 빈번하게 물어보지 않고 발표자는 업데이트 후에 새로운 소식을 구독자에게 전달할 수 있다.또 게시/구독 모드에서는 구독자와 게시자를 격리했다.예를 들어 당신이 구독한 신문이 잡지사의 구체적인 어느 부서에서 담당하는지 알 필요가 없다. 심지어 잡지사가 사무실 주소를 바꾸면 잡지사는 여전히 최신 신문을 당신의 입구까지 배달할 수 있다.요약하자면 게시/구독 모드는 주로 다음과 같은 두 가지 문제를 해결합니다.
  • 발표자가 자발적으로 메시지를 전송하는 문제
  • 구독자와 게시자에 대한 격리 결합
  • 게시/구독자 모드에서 실현할 기능
    신문 구독이라는 현실 생활의 예에서 알 수 있듯이 발표/구독자 모델을 실현하려면 다음과 같은 기능을 갖추어야 한다.
  • 가입 기능
  • Push 기능
  • 주문 취소 기능
  • 구독 기능에 대해 우리는 서로 다른 잡지사의 서로 다른 간행물을 구독할 수 있는데, 사람마다 상황이 다를 수 있다.푸시 기능에 대해서는 게시자가 구독자별 구독 정보를 대상으로 서로 다른 내용을 푸시할 것을 요구한다.구독 취소 기능에 대해 구독자는 특정한 잡지사에서 구독한 특정한 간행물이나 특정한 간행물을 취소할 수 있도록 요구한다.우리는 먼저 가장 간단한 것부터 한 걸음 한 걸음 이 발표/구독자 모델을 실현한다.
    가장 간단한 게시/구독자 모드
    발표/구독자 모델을 실현하려면 두 가지 종류가 필요하다. 하나는 발표자 클래스, 하나는 구독자 클래스이다.게시자의 실례에 대해 최소한subs 속성이 있어야 구독자 정보를 저장할 수 있고, 하나listen 방법은 subs에 구독자를 추가할 수 있으며, 또 하나trigger 방법은 메시지를 전달할 수 있다.물론 이런 실례나 방법의 이름은 스스로 정의할 수 있고 엄격한 요구가 없다.구독자의 실례에 대해 최소한update 방법으로 게시자가 보낸 메시지를 수신하고 응답하도록 요구한다.물론 이 방법의 이름도 스스로 정의할 수 있다.먼저 게시자와 구독자의 인터페이스 대상PublisherSubscriber을 정의한다.
    interface Subscriber{
        update();
    }
    
    interface Publisher{
        subs:Subscriber[];
        listen(sub:Subscriber);
        trigger();
    }
    
    인터페이스가 정의된 후에 이 두 인터페이스를 실현하는 게시자 클래스와 구독자 클래스를 각각 정의한다.
    class SomePublisher implements Publisher{
        subs = [];
        //   subs         
        listen(sub:Subscriber){
            this.subs.push(sub);
        }
        //     
        trigger(){
            this.subs.forEach(sub => sub.update())
        }
    }
    
    class SomeSubscriber implements Subscriber{
        name:string;
        constructor(name){
            this.name = name;
        }
        //              
        update(){
            console.log(`${this.name}:      ~`)
        }
    }
    
    다음은 클래스의 인스턴스화 및 메소드 호출입니다.
    //        
    const pub1 = new SomePublisher();
    //        
    const sub1 = new SomeSubscriber("   1")
    const sub2 = new SomeSubscriber("   2")
    const sub3 = new SomeSubscriber("   3")
    //        
    pub1.listen(sub1);
    pub1.listen(sub2);
    pub1.listen(sub3);
    //     
    pub1.trigger();
    
    컴파일된 코드를 실행하려면 Node를 사용하십시오. 결과는 다음과 같습니다.
       1:      ~
       2:      ~
       3:      ~
    
    위에서 우리는 가장 간단한 게시/구독 모델을 실현했다.
    메시지 푸시 구분
    위에서 실현된 게시/구독 모드에서 게시자가 trigger 함수를 호출하여 알림을 보낼 때 모든 구독자에게 알림을 보낸다. 서로 다른 구독자가 서로 다른 구독을 할 수 있음을 고려하지 않고 어떤 메시지가 업데이트되면 구독자에게 알림을 보낸다.다음은 서로 다른 구독 수요에 적응하기 위해 위의 코드를 개선합니다.먼저 Publisher 인터페이스 정의를 수정합니다.
    interface Publisher{
        // Map          ,            
        subs:Map;
        listen(column:string,sub:Subscriber);
        trigger(column:string);
    }
    
    그런 다음 클래스SomePublisher를 수정합니다.
    class SomePublisher implements Publisher{
        subs:Map;
        constructor(){
            this.subs = new Map();
        }
        //   subs         
        listen(column:string,sub:Subscriber){
            if(!this.subs.has(column)){
                this.subs.set(column,[]);
            }
            this.subs.get(column).push(sub);
        }
        //     
        trigger(column:string){
            if(!this.subs.has(column)) return;
            //                
            const columnSubs = this.subs.get(column);
            //          (          )
            columnSubs.forEach(sub => sub.update(column));
        }
    }
    
    수정SomeSubscriber클래스, 개선update방법으로 매개 변수를 받아들일 수 있도록:
    class SomeSubscriber implements Subscriber{
        name:string;
        constructor(name){
            this.name = name;
        }
        //              
        update(column:string){
            console.log(`${this.name}:     ${column}     ~`)
        }
    }
    
    다음은 클래스의 인스턴스화 및 메소드 호출입니다.
    //        
    const pub1 = new SomePublisher();
    //        
    const sub1 = new SomeSubscriber("   1")
    const sub2 = new SomeSubscriber("   2")
    const sub3 = new SomeSubscriber("   3")
    //        
    pub1.listen("  ",sub1);
    pub1.listen("  ",sub2);
    pub1.listen("  ",sub3);
    //     
    pub1.trigger("  ")
    pub1.trigger("  ")
    pub1.trigger("  ")
    
    컴파일된 코드를 실행하려면 Node를 사용하십시오. 결과는 다음과 같습니다.
       1:            ~
       2:            ~
       3:            ~
    
    참고: ES6의 Map 객체가 사용되므로 TypeScript 코드를 컴파일할 때 다음과 같은 속성을 지정해야 합니다.
    tsc .\main.ts --target ES6
    
    구독 해지
    다음은 구독 취소target 방법을 실현합니다.우선 unsubscribe 인터페이스를 보완하고 Subscriber 필드를 씁니다. 이 필드는 구독을 취소할 때 사용합니다. 이름이 중복될까 봐 걱정되면 name 등 유일한 값으로 설정할 수 있습니다. 저는 유일한 처리를 하지 않았습니다.
    interface Subscriber{
        update(column:string);
        name:string;
    }
    
    완벽id 인터페이스, 추가Publisher 방법 제약:
    interface Publisher{
        // Map          ,            
        subs:Map;
        listen(column:string,sub:Subscriber);
        trigger(column:string);
        unsubscribe(column:string,sub:Subscriber);
    }
    
    완벽unsubscribe클래스:
    class SomePublisher implements Publisher{
        subs:Map;
        constructor(){
            this.subs = new Map();
        }
        //   subs         
        listen(column:string,sub:Subscriber){
            if(!this.subs.has(column)){
                this.subs.set(column,[]);
            }
            this.subs.get(column).push(sub);
        }
        //     
        trigger(column:string){
            if(!this.subs.has(column)) return;
            //                
            const columnSubs = this.subs.get(column);
            //          (          )
            columnSubs.forEach(sub => sub.update(column));
        }
    
        //     
        unsubscribe(column:string,sub:Subscriber){
            let columnSubs = this.subs.get(column);
            const { name } = sub;
            //          
            columnSubs = columnSubs.filter(sub => sub.name !== name);
            this.subs.set(column,columnSubs);
        }
    }
    
    다음은 클래스의 인스턴스화 및 메소드 호출입니다.
    //        
    const pub1 = new SomePublisher();
    //        
    const sub1 = new SomeSubscriber("   1")
    const sub2 = new SomeSubscriber("   2")
    const sub3 = new SomeSubscriber("   3")
    //        
    pub1.listen("  ",sub1);
    pub1.listen("  ",sub2);
    pub1.listen("  ",sub3);
    //     
    pub1.trigger("  ")
    pub1.trigger("  ")
    pub1.trigger("  ")
    console.log("==================")
    //     
    pub1.unsubscribe("  ",sub1);
    //     
    pub1.trigger("  ")
    pub1.trigger("  ")
    pub1.trigger("  ")
    
    컴파일된 코드를 실행하려면 Node를 사용하십시오. 결과는 다음과 같습니다.
       1:            ~
       2:            ~
       3:            ~
    ==================
       2:            ~
       3:            ~
    
    현재, 우리는 비교적 완전한 게시/구독 모델을 실현했다.
    JavaScript 스타일의 게시/구독 모드
    앞에서 우리가 실현한 게시/구독 모드는 자바 스타일입니다. 구독을 진행할 때 SomePublisher 방법에 구독자 대상 인용을 보내야 합니다. 이 대상은 메시지 전송에 사용할 수 있는 listen 방법을 제공해야 합니다.구독자 대상 인용의 목적은 게시자가 메시지를 발표할 때 이 대상의 어떤 방법을 호출할 수 있도록 하는 것이다. 따라서 자바스크립트 스타일에서 우리는 update시에 어떤 함수를 전송할 수 있고 게시자가 메시지를 발표할 때 이 함수를 호출하면 된다.예를 들어, 가입할 때 다음과 같이 매개변수를 전달할 수 있습니다.
    pub1.listen("  ",function(column:string){
        doSomething();
    });
    
    그리고 listen 방법에 상응하는 변경을 하여 특정한 항목의 구독자 목록에 이 함수를 저장하고 특정한 항목에 새로운 소식이 있을 때 차례대로 이 함수를 호출하며 구체적인 코드는 여기에 붙이지 않겠습니다.물론 직접 전입 함수 방식을 채택하면 listen 집합의 구조와 subs에 대해 어느 정도 수정이 필요할 수 있다.나는 개인적으로 본문에서 소개한 전입 대상의 방식을 더욱 좋아한다.
    끝나다

    좋은 웹페이지 즐겨찾기