JSとデザインパターン-第6章🚀


目次
* 🤓 INTRODUCTION
* 🔌 ABOUT ADAPTER PATTERN
* 📊 STOCK MARKET EXAMPLE
* 👀 VISUAL REPRESENTATION
* 🧪 CHEMICAL COMPOUND EXAMPLE
* ⚒ APPLICABILITY
* ✅ PROS
* ❌ CONS
* 🙏 THANK YOU

🤓 導入

Welcome, my dear codedudes and codedudettes, to yet another Codespresso JS and Design Patterns blog! 👩‍💻 I hope you are all having a great day! Before we start I want to remind you that I am posting (almost daily) blogs about Computer Science and Computer Programming right here on Dev.to; If you have any ambiguities, or even If you just want to connect you can follow me, and contact me via , , ☕ ko-fi または電子メールを介して.私はあなたのためにここで話して、議論して、多分あなたにいくつかのポインタを示します.また、接続したい、あなたから学ぶ、または多分何かを教えて、私は好きなことをするだけで楽しい時を過す.
今日はアダプタパターンについて話しています.🚀

🔌 アダプタパターンについて

The Adapter Pattern is a structural design pattern that allows objects with incompatible interfaces to collaborate. It can convert an interface of the class into an interface that another class expects. That way it allows classes to function together which normally couldn't be possible due to their incompatible interfaces.

📊 株式市場例

Imagine that you need to create a stock market monitoring application. The app downloads the stock data from multiple sources in XML format and then displays nice-looking charts and diagrams for the user. At some point, you decide to improve the app by importing some 3rd-party analytics library. But, you encounter the problem. The 3rd-party library only works with data in JSON format.

🤔 What should we do?

  • Proposition: We could change the library to work with XML.

Yes, we could do it. But that might break some existing code that relies on the library, or worse, you might not have the library's source code in the first place, making this approach impossible.

💡 REVELATION
To solve this problem, we could create an adapter. The special object that converts the interface of one object in a way that another object can understand it. An adapter will wrap one of the objects to hide the complexity of the conversion happening behind the scenes. The wrapped object isn't even aware of the adapter.

⚙ HOW DOES IT WORK?

  • The adapter gets an interface, compatible with one of the existing objects
  • Using this interface, the existing object can safely call the adapter's methods
  • Upon receiving a call, the adapter passes the request to the second object, but in a format and order that the second object expects

In the Stock Market example, we could create XML-to-JSON adapters for every class of the analytics library that your code works with directly. Then, we can adjust our code to communicate with the library only via these adapters. When an adapter receives a call, it will translate all incoming XML data into a JSON structure and it will pass the call to the appropriate methods of a wrapped analytics object.

👀 視覚表現


  • target -クライアントクラスで使用される特定のインターフェイスを定義します

  • アダプター-クラスのインターフェイスに向かってクラスアダプターのインターフェイスを適応

  • Adaptee -適応する既存のインターフェイスを定義します

  • クライアント-ターゲットクラスのインターフェイスを必要とするオブジェクトを検索する
  • 興味深い現実世界の例を使って説明しましょう.

    🧪 化合物例

    This real-world example shows the use of the chemical-compound databank. The complex chemical compounds access the databank via an interface provided by an interface of the Adapter class.

    Let's dive into the code. 🚀 (❗ As always, read the comments)

    //Target - It defines the specific interface that is used by the Client class
    class Compound{
       //setting up initial valules - self explanatory :)
       constructor(name){
          this.name = name;
          this.bolingPoint = -1;
          this.meltingPoint = -1;
          this.molecularWeight = -1;
          this.molecularFormula = -1;
       }
    
       //setting compound name
       setCompound(name){
          this.name = name;
       }
    
       //name getter
       display(){ return this.name; }
    }
    
    
    //Adapter - It adapts the interface of the class Adaptee towards the interface of the class
    class RichCompound extends Compound{
       constructor(name){
          super(name);
       }
       /* This function creates Chemical Databank for each 
       new Rich compound that we are creating*/
       display(){
         //creating a new chemical databank
         this.bank = new ChemicalDatabank();
         //getting the boiling point based on the chemical name and indicator B === "Boiling"
         var boilingPoint = this.bank.getCriticalPoint(this.name, "B");
         //getting the melting point based on the chemical name and indicator M === "Melting"
         var meltingPoint = this.bank.getCriticalPoint(this.name, "M");
         //getting the molecular weight based on the chemical name
         var molecularWeight = this.bank.getMolecularWeight(this.name);
         //getting the molecular formula based on the chemical name
         var molecularFormula = this.bank.getMolecularStructure(this.name);
    
         //displaying all necessary information
         console.log("%c%s",
            "color: black; background: lightgreen; font-size: 24px; border: 1px solid lightgreen; border-radius: 5px; padding: 5px;"
            ,`🧪 Name: ${super.display()}`);
         console.log(`👩‍🔬 Formula: ${molecularFormula}`);
         console.log(`🏋️‍♀️ Weight: ${molecularWeight}`);
         console.log(`❄ Melting Pt: ${meltingPoint}\u00B0C`);
         console.log(`🔥 Boiling Pt: ${boilingPoint}\u00B0C`);
       }
    }
    
    //Adaptee - It defines an existing interface that should be adapted
    class ChemicalDatabank{
      //databank - taken from the 'legacy API'
      getCriticalPoint(compound, point){
         var temperature = 0.0;
         //freezing point
         if (point == "M"){
            switch(compound.toLowerCase()){
               case "water": temperature = 0.0; break;
               case "benzene": temperature = 5.5; break;
               case "alcohol": temperature = -114.1; break;
            }
         }else{ //boiling point
            switch(compound.toLowerCase()){
               case "water": temperature = 100.0; break;
               case "benzene": temperature = 80.1; break;
               case "alcohol": temperature = 78.3; break;
            }
         }
         return temperature;
      }
    
      getMolecularStructure(compound){
         var structure = "";
         switch(compound.toLowerCase()){
            case "water": structure = "H2O"; break;
            case "benzene": structure = "C6H6"; break;
            case "alcohol": structure = "C2H6O2"; break;
         }
         return structure;
      }
    
      getMolecularWeight(compound){
         var weight = 0.0;
         switch(compound.toLowerCase()){
            case "water": weight = 18.015; break;
            case "benzene": weight = 78.1134; break;
            case "alcohol": weight = 46.0688; break;
         }
         return weight;
      }
    }
    
    //unadapted compound
    var unadaptedCompound = new Compound("Unknown");
    console.log("%c%s",
            "color: black; background: red; font-size: 24px; border: 1px solid red; border-radius: 5px; padding: 5px;",`❌ Unadapted compound: ${ unadaptedCompound.display()}`);
    
    //adapted compounds
    var water = new RichCompound("Water");
    water.display();
    
    var benzene = new RichCompound("Benzene");
    benzene.display();
    
    var alcohol = new RichCompound("Alcohol");
    alcohol.display();
    

    Pretty interesting, right? 😎 Don't hesitate to play with the code.

    ⚒ 適用性

    • You can use the Adapter pattern when you want to use some existing class, but its interface isn't compatible with the rest of your code. The adapter pattern, lets you create a middle-layer class that serves as a translator between your code and legacy class, a 3rd-party library, or any other class with a weird interface.
    • Use the pattern when you want to reuse several existing subclasses that lack some common functionality that can't be added to the superclass. You could extend each subclass and put the missing functionality into new child classes. However, you'll need to duplicate the code across all of these new classes, which is not good.

    ✅ 長所

    • Single Responsibility Principle. You can separate the interface or data conversion code from the primary business logic of the program.
    • Open/Closed Principle. You can introduce new types of adapters into the program without breaking the existing client code, as long as they work with the adapters through the client interface.

    ❌ 短所

    • The overall complexity of the code increases because you need to introduce a set of new interfaces and classes. Sometimes it’s simpler just to change the service class so that it matches the rest of your code.

    🙏 読んでくれてありがとう!

    References:
    School notes...
    refactoring
    コメントを残してください、あなたについて、あなたの仕事について教えてください、あなたの考えをコメントし、私と接続するか、または.
    ☕ 私をサポートし、私を集中保つ!

    楽しい時間をハッキング!😊