JavaScript 풀기 02: OOJS 파트 4 - 디자인 패턴

클래스나 개체가 복잡할수록 관리 및/또는 확장하기가 더 어려워집니다. 디자인 패턴은 OOP의 일반적인 문제에 대한 일반적인 솔루션입니다.

디자인 패턴에 대한 훌륭한 책과 훌륭한 블로그가 있지만 대부분 유형 언어를 다루지만dofactory.com JS에서 23가지 디자인 패턴을 다루는 전용 시리즈가 있습니다. 이 기사에서 디자인 패턴을 다룬다면 확실히 정의를 내리지 않을 것입니다. 그것들은 자신의 책을 받을 자격이 있습니다. 즉, 그것들이 얼마나 풍부하고 광범위한지, 단지 여러분의 싹을 적시기 위해 각 카테고리에서 하나씩 다룰 것입니다.

디자인 패턴은 Structural, Creational, Behavioral 디자인 패턴으로 분류됩니다.

창조 – 효율적이고 유연한 객체 생성



Creational은 효율적이고 유연하며 재사용 가능한 개체를 만들기 위한 수단/패턴을 제공합니다. 저는 팩토리 메서드만 다룰 것입니다. 이 범주에서 이미 친숙한 패턴 중 하나는 프로토타입 메서드입니다. 다른 개체에서 개체를 만들고,

공장 방법



클라이언트는 개체 생성을 공장에 위임합니다.

클라이언트를 객체의 사용자로 생각하고 팩토리를 공급자로 생각하십시오.

클라이언트는 자신이 원하는 개체가 무엇인지 알고 있고 팩토리에 해당 특정 개체를 만들고 반환하도록 지시할 수 있습니다. 클라이언트는 클라이언트가 예상하는 API를 준수하는 한 개체가 만들어진 방법과 위치를 알 필요가 없습니다. 어떤 의미에서 그것은 실제 공장입니다.

우리 고객이 Nike 매장이고 공장 방식이 Nike 공장이라고 가정해 보겠습니다. 매장은 특정 Nike 신발을 공장에 주문합니다. 주문에 따라 설명과 필요를 준수하는 Nike 유형.

  // Factory 
 // create Nike Airforce 1 object
class Nike_Air_Force1 {

   constructor(name, type){
      this.name = name;
      this.type = type;

    }

 print(){

  console.log(this.name, this.type)

 }

}



// class to create Air Max object 

class Nike_Air_MAX1{

 constructor(name, type){

  this.name = name

  this.type = type

 }

 print(){

 console.log(this.name, this.type)

 }

}

// Factory, receives a message from the client, and decide which shoe(object to create and return)

// actual factory method

class factory{

 // factory api, all the client provides is the type of object needed

// the factory handles the rest and return a relevant object

 createNike = (type) => {

 switch(type){

   case "AirForce":

      return new Nike_Air_Force1("Air force 1", "low")

   case "Max":

      return new Nike_Air_MAX1("Air Max 1", "THE ORIGINAL")

   default:

     break

   }

 }

}


// end of factory 


// client 

let fact = new factory()  // client access to the factory

let force = fact.createNike("AirForce")  // place order and a
// relevant object(created from the class) is returned

force.print();



행동 - 객체 간의 의사 소통을 용이하게 함



아마도 가장 유용한 패턴일 것입니다. 저는 그것들을 많이 사용했습니다. 서로에 대해 알지 못한 채 서로 대화해야 하는 여러 객체로 작업할 때 새로운 가능성을 열어줍니다(느슨하게 결합됨).

관찰자 패턴 –



wiki에서 이 설명을 찾았고 구현은 "subject"라는 개체가 관찰자라고 하는 종속 항목 목록을 유지 관리하고 메서드 중 하나를 호출하여 자동으로 상태 변경을 알리는 패턴으로 정의된 사양을 따릅니다.

위키 구현이 다소 부족합니다. 여기에서 좀 더 개선할 것입니다.

class Subject{
    subs = [] // maintains a list of its dependents called observers

    state = {name: "The 100"}  // when it changes subs will be notified

     subscribe(fn){

        this.subs.push(fn) // subscribing

      // we return a function that has a reference to our function we

      //subscribed with(fn), the returned function can be used to unsubscribe

   // which is basically removing the pushed function out of the subs list

  return (

      () => {

     console.log(fn, 'unsubing')

       this.subs = this.subs.filter(l => l !== fn) // unsubscribing

       }

  )

 }


// notifying the subscribers of any change in the state

 change(){

   this.subs.forEach((subscriberFn)=> {

     subscriberFn(this.state); // notifying all subs and passing new state

 })

 }

// changing/setting state 
setName(name){

 this.state.name = name // change state

 this.change()  // notify all subs of the change

}

}


// usage 
 let sub = new Subject()

// returns an unsubing function

let unsub = sub.subscribe((state)=> {

 console.log(state.name) // code here will be executed when the state of "subject" changes

})

// changing state

sub.setName("GOT") // GOT will be logged

sub.setName("House of The Dragon") // same

// unsubscribing

unsub()

console.log(sub.subs) // should log an empty array



간단하죠? 아직 강력합니다. 위에서 간단한 상태 관리자를 만들 수 있습니다. 물론 연속 스트림 구독 등과 같은 관찰 가능 항목에 대한 뉘앙스가 있으며 RxJS와 같은 전용 패키지가 있습니다.

구조 –



의미 있고 응집력 있고 유연한 구조를 형성하기 위해 서로 다른 개체를 함께 가져옵니다.

파사드 패턴 –



많은 관련 개체를 캡슐화하는 단일 지점 API인 포괄적인 개체를 만듭니다.

Façade 그룹 관련 개체, 일반적으로 서로 상호 작용하거나 순서대로 호출되는 개체.

포괄적인 설명을 위해 반응 후크에 대한 파사드도 구현하는 thisarticle를 제안합니다.

그 예를 들어, 완벽한 커피를 만들기 위해 함께 작동하는 물체는 어떻습니까?


// objects to be called/used in sequence
 class Ratio{

  coffee_ratio(){

    console.log("picking perfect coffee ration")

  }

 }

  class Brewing{

     pick_method(){

        console.log("picking brewing method")

    }

}


 class Water{

     Ideal_temperature(){

      console.log("reached ideal temp")

      this.brew_with_ideal_temp()

    }

    brew_with_ideal_temp(){

        console.log("brewing with ideal water temp")

    }

 }

 class Time{

    brew_time(){

    console.log("brewing the correct amount of time")

    }

 }




커피를 만들려면 새 커피를 만들 때마다 각 개체를 만들고 필요한 각 메서드를 호출해야 합니다. 파사드 패턴은 반복적이고 유사한 패턴을 따르기 때문에 이 모든 단계를 수행할 단일 개체를 만들지 않는 이유를 말합니다. 시간.

 class CoffeeFacade{
                 // con take objects to be used
        constructor(Ratio, Brewing, Water, Time ){

                this.Ratio = Ratio;

                this.Brewing = Brewing;

                this.Water = Water;

                this.Time = Time

        }

        // using the objects in sequence
    makeCoffe(){

            this.Ratio.coffee_ratio();

            this.Brewing.pick_method();

            this.Water.Ideal_temperature();

            this.Time.brew_time()

    }

 }


// usage



커피를 만들려면 매번 새로 시작하고 필요한 모든 개체를 만드는 대신 커피가 필요할 때마다 파사드에서 단일 커피 만들기 방법을 호출하면 됩니다. 이것은 강력합니다.


 let coffeMaker = new CoffeeFacade(new Ratio(), new Brewing(), new Water(), new Time())

 coffeMaker.makeCoffe()  // to make a new coffee



결론



디자인 패턴은 당신의 코드를 극적으로 향상시킬 것입니다. 나는 그것들에 익숙해지는 것을 제안합니다.

다음 시리즈에서는 OOJS의 마지막 기사로 상속을 다룬 다음 비동기 코드로 이동합니다.

좋은 웹페이지 즐겨찾기