adapter-Bất kỳ ví dụ thực tế nào về Mẫu Bộ điều hợp [đã đóng]


84

Tôi muốn chứng minh việc sử dụng Mẫu Bộ điều hợp cho nhóm của mình. Tôi đã đọc nhiều sách và bài báo trực tuyến. Mọi người đều trích dẫn một ví dụ hữu ích để hiểu khái niệm (Hình dạng, Thẻ nhớ, Bộ chuyển đổi Điện tử, v.v.), nhưng không có nghiên cứu điển hình thực tế.

Bạn có thể vui lòng chia sẻ bất kỳ nghiên cứu điển hình nào về Mẫu điều hợp không?

ps Tôi đã thử tìm kiếm các câu hỏi hiện có trên stackoverflow, nhưng không tìm thấy câu trả lời nên đăng nó dưới dạng một câu hỏi mới. Nếu bạn biết đã có câu trả lời cho điều này, thì hãy chuyển hướng.


4
Vâng nếu bạn muốn demo nó. Bạn nên có sẵn một ví dụ về nó trong môi trường của bạn, trên thực tế là một số. Nếu không, tại sao bạn muốn demo nó?
Tony Hopkinson

1
Một số ví dụ ở đây. stackoverflow.com/questions/1673841/…
r4.

1
@TonyHopkinson Mục tiêu là làm cho mọi người biết đến mẫu thiết kế này bằng ví dụ thực tế.
AksharRoop

10
@AksharRoop. Design Pattern được hiểu là một giải pháp cho một vấn đề, không phải là một giải pháp tìm kiếm một vấn đề. Ví dụ tốt nhất là một trong "thế giới" của riêng bạn.
Tony Hopkinson

1
@TonyHopkinson Tôi có thể đã sử dụng thuật ngữ chứng minh không chính xác ở đây, nhưng ý tôi là giải thích khái niệm về mô hình này bằng ví dụ điển hình. Tôi đồng ý tôi nên tìm ra một trong hệ thống của riêng tôi ...
AksharRoop

Câu trả lời:


77

Nhiều ví dụ về Bộ điều hợp là tầm thường hoặc không thực tế ( Rectangle vs. LegacyRectangle, Ratchet vs. Socket , SquarePeg vs RoundPeg , Duck vs. Turkey ). Tệ hơn nữa, nhiều người không hiển thị nhiều Bộ điều hợp cho các Bộ điều hợp khác nhau ( ai đó đã trích dẫn Arrays.asList của Java làm ví dụ về mẫu bộ điều hợp ). Việc chỉ thích ứng một giao diện của một lớp để hoạt động với lớp khác dường như là một ví dụ yếu của mẫu Bộ điều hợp GoF. Mẫu này sử dụng tính kế thừa và đa hình, vì vậy người ta sẽ mong đợi một ví dụ tốt để hiển thị nhiều cách triển khai bộ điều hợp cho các bộ điều hợp khác nhau .

Các ví dụ tốt nhất tôi thấy là trong Chương 26 của Áp dụng UML và Patterns: Giới thiệu về Phân tích Object-Oriented và Thiết kế và Phát triển lặp (3rd Edition) . Các hình ảnh sau đây là từ tài liệu hướng dẫn được cung cấp trên trang FTP cho cuốn sách.

Phần đầu tiên cho thấy cách một ứng dụng có thể sử dụng nhiều triển khai (bộ điều hợp) giống nhau về chức năng (ví dụ: máy tính thuế, mô-đun kế toán, dịch vụ ủy quyền tín dụng, v.v.) nhưng có các API khác nhau. Chúng tôi muốn tránh mã hóa cứng mã lớp miền của mình để xử lý các cách khác nhau có thể có để tính thuế, đăng bán hàng, ủy quyền yêu cầu thẻ tín dụng, v.v. Đó là tất cả các mô-đun bên ngoài có thể khác nhau và chúng tôi không thể sửa đổi mã. Bộ điều hợp cho phép chúng tôi thực hiện mã hóa cứng trong bộ điều hợp, trong khi mã lớp miền của chúng tôi luôn sử dụng cùng một giao diện (giao diện IW AnythingAdapter).

Hình 26.1

Chúng tôi không thấy trong hình trên những người thích nghi thực sự. Tuy nhiên, hình sau cho thấy cách thực hiện một lệnh gọi đa hình postSale(...)trong giao diện IAccountingAdapter, dẫn đến việc đăng bán qua SOAP lên hệ thống SAP.

Hình 26.2


ví dụ này sử dụng phiên là khá tốt quá (mặc dù việc thực hiện không phải là hoàn toàn đúng, tôi nghĩ rằng, sử dụng tĩnh học): community.sitepoint.com/t/phpunit-testing-cookies-and-sessions/...
Alejandro Moreno

và dĩ nhiên, việc thực hiện trong PHP: github.com/alex-moreno/DesignPatternsPHP/tree/master/Adapter
Alejandro Moreno

50

Làm thế nào để biến một người Pháp thành một người bình thường ...

 public interface IPerson
    {
        string Name { get; set; }
    }

    public interface IFrenchPerson
    {
        string Nom { get; set; }
    }

    public class Person : IPerson
    {
        public string Name { get; set; }
    }

    public class FrenchPerson : IFrenchPerson
    {
        public string Nom { get; set; }
    }

    public class PersonService
    {
        public void PrintName(IPerson person)
        {
            Debug.Write(person.Name);
        }
    }

    public class FrenchPersonAdapter : IPerson
    {
        private readonly IFrenchPerson frenchPerson;

        public FrenchPersonAdapter(IFrenchPerson frenchPerson)
        {
            this.frenchPerson = frenchPerson;
        }

        public string Name 
        {
            get { return frenchPerson.Nom; }
            set { frenchPerson.Nom = value; }
        }
    } 

Thí dụ

    var service = new PersonService();
    var person = new Person();
    var frenchPerson = new FrenchPerson();

    service.PrintName(person);
    service.PrintName(new FrenchPersonAdapter(frenchPerson));

19
Tôi là người Pháp và tôi cảm thấy bị xúc phạm khi bạn không coi tôi là người thật. (JK)
ZeroUltimax

13
@ZeroUltimax Tôi khá chắc chắn rằng mã này sẽ không được biên dịch ở Quebec.
Fuhrmanator

Bất kỳ lập trình viên nào không có kiến ​​thức về Bộ điều hợp, sẽ giải quyết vấn đề một cách dễ dàng. Kiến thức về lý thuyết bộ điều hợp giúp tiết kiệm thời gian hoặc làm cho giải pháp tốt hơn như thế nào? Điểm cuối cùng là sử dụng một lớp đặc biệt, thay vì chỉ sử dụng một phương thức?
Rowan Gontier

Điều gì sẽ xảy ra nếu bạn không kiểm soát giao diện và cần điều chỉnh một trong các lớp của mình sang thư viện của bên thứ ba? Nhiều lý do chính đáng khác nằm ngoài phạm vi của câu trả lời này.
CountZero

3
Đây là ví dụ vui nhất - và có thể là một trong những ví dụ dễ tiếp cận nhất - về cách sử dụng mẫu Bộ điều hợp mà tôi từng xem qua.
Mass Dot Net

42

Chuyển đổi một Giao diện thành một Giao diện khác.

Bất kỳ ví dụ thực tế nào về Mẫu Bộ điều hợp

Để kết nối nguồn điện, chúng tôi có các giao diện khác nhau trên toàn thế giới. Sử dụng Adapter chúng ta có thể kết nối dễ dàng như khôn ngoan.

nhập mô tả hình ảnh ở đây


Dưới đây là một số mã tương ứng với rằng: codeproject.com/Tips/595716/Adapter-Design-Pattern-in-Cplusplus
Raghav Navada


13

Đây là một ví dụ mô phỏng chuyển đổi analog datasang digit data.

Nó cung cấp một bộ điều hợp để chuyển đổi dữ liệu số thực sang dữ liệu nhị phân, nó có thể không hữu ích trong thế giới thực, nó chỉ giúp giải thích khái niệm về mẫu bộ điều hợp.


AnalogSignal.java

package eric.designpattern.adapter;

public interface AnalogSignal {
    float[] getAnalog();

    void setAnalog(float[] analogData);

    void printAnalog();
}

DigitSignal.java

package eric.designpattern.adapter;

public interface DigitSignal {
    byte[] getDigit();

    void setDigit(byte[] digitData);

    void printDigit();
}

FloatAnalogSignal.java

package eric.designpattern.adapter;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FloatAnalogSignal implements AnalogSignal {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private float[] data;

    public FloatAnalogSignal(float[] data) {
        this.data = data;
    }

    @Override
    public float[] getAnalog() {
        return data;
    }

    @Override
    public void setAnalog(float[] analogData) {
        this.data = analogData;
    }

    @Override
    public void printAnalog() {
        logger.info("{}", Arrays.toString(getAnalog()));
    }
}

BinDigitSignal.java

package eric.designpattern.adapter;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BinDigitSignal implements DigitSignal {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private byte[] data;

    public BinDigitSignal(byte[] data) {
        this.data = data;
    }

    @Override
    public byte[] getDigit() {
        return data;
    }

    @Override
    public void setDigit(byte[] digitData) {
        this.data = digitData;
    }

    @Override
    public void printDigit() {
        logger.info("{}", Arrays.toString(getDigit()));
    }
}

AnalogToDigitAdapter.java

package eric.designpattern.adapter;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>
 * Adapter - convert analog data to digit data.
 * </p>
 * 
 * @author eric
 * @date Mar 8, 2016 1:07:00 PM
 */
public class AnalogToDigitAdapter implements DigitSignal {
    public static final float DEFAULT_THRESHOLD_FLOAT_TO_BIN = 1.0f; // default threshold,
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private AnalogSignal analogSignal;
    private byte[] digitData;
    private float threshold;
    private boolean cached;

    public AnalogToDigitAdapter(AnalogSignal analogSignal) {
        this(analogSignal, DEFAULT_THRESHOLD_FLOAT_TO_BIN);
    }

    public AnalogToDigitAdapter(AnalogSignal analogSignal, float threshold) {
        this.analogSignal = analogSignal;
        this.threshold = threshold;
        this.cached = false;
    }

    @Override
    public synchronized byte[] getDigit() {
        if (!cached) {
            float[] analogData = analogSignal.getAnalog();
            int len = analogData.length;
            digitData = new byte[len];

            for (int i = 0; i < len; i++) {
                digitData[i] = floatToByte(analogData[i]);
            }
        }

        return digitData;
    }

    // not supported, should set the inner analog data instead,
    @Override
    public void setDigit(byte[] digitData) {
        throw new UnsupportedOperationException();
    }

    public synchronized void setAnalogData(float[] analogData) {
        invalidCache();
        this.analogSignal.setAnalog(analogData);
    }

    public synchronized void invalidCache() {
        cached = false;
        digitData = null;
    }

    @Override
    public void printDigit() {
        logger.info("{}", Arrays.toString(getDigit()));
    }

    // float -> byte convert,
    private byte floatToByte(float f) {
        return (byte) (f >= threshold ? 1 : 0);
    }
}

Mã - Trường hợp thử nghiệm

AdapterTest.java

package eric.designpattern.adapter.test;

import java.util.Arrays;

import junit.framework.TestCase;

import org.junit.Test;

import eric.designpattern.adapter.AnalogSignal;
import eric.designpattern.adapter.AnalogToDigitAdapter;
import eric.designpattern.adapter.BinDigitSignal;
import eric.designpattern.adapter.DigitSignal;
import eric.designpattern.adapter.FloatAnalogSignal;

public class AdapterTest extends TestCase {
    private float[] analogData = { 0.2f, 1.4f, 3.12f, 0.9f };
    private byte[] binData = { 0, 1, 1, 0 };
    private float[] analogData2 = { 1.2f, 1.4f, 0.12f, 0.9f };

    @Test
    public void testAdapter() {
        AnalogSignal analogSignal = new FloatAnalogSignal(analogData);
        analogSignal.printAnalog();

        DigitSignal digitSignal = new BinDigitSignal(binData);
        digitSignal.printDigit();

        // adapter
        AnalogToDigitAdapter adAdapter = new AnalogToDigitAdapter(analogSignal);
        adAdapter.printDigit();
        assertTrue(Arrays.equals(digitSignal.getDigit(), adAdapter.getDigit()));

        adAdapter.setAnalogData(analogData2);
        adAdapter.printDigit();
        assertFalse(Arrays.equals(digitSignal.getDigit(), adAdapter.getDigit()));
    }
}

Sự phụ thuộc - thông qua maven

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.2</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.13</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.13</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.16</version>
    </dependency>

Làm thế nào để kiểm tra

Chỉ cần chạy thử nghiệm đơn vị.


7

Mẫu bộ điều hợp hoạt động như một cầu nối giữa hai giao diện không tương thích. Mẫu này liên quan đến một lớp duy nhất được gọi là bộ điều hợp chịu trách nhiệm giao tiếp giữa hai giao diện độc lập hoặc không tương thích.

Ví dụ trong thế giới thực có thể là trình dịch ngôn ngữ hoặc bộ sạc di động. Thêm ở đây trong video youtube này:

Youtube - Mẫu thiết kế bộ điều hợp: Giới thiệu


3

Bạn có thể sử dụng mẫu thiết kế Bộ điều hợp khi bạn phải xử lý các giao diện khác nhau có hành vi tương tự (thường có nghĩa là các lớp có hành vi tương tự nhưng với các phương thức khác nhau). Ví dụ về nó sẽ là một lớp để kết nối với TV Samsung và một lớp khác để kết nối với TV Sony. Chúng sẽ chia sẻ các hành vi chung như mở menu, bắt đầu phát lại, kết nối với mạng, v.v. nhưng mỗi thư viện sẽ có cách triển khai khác nhau (với các tên phương thức và chữ ký khác nhau). Các triển khai cụ thể của nhà cung cấp khác nhau này được gọi là Adaptee trong sơ đồ UML.

Vì vậy, trong mã của bạn (gọi là khách hàng trong sơ đồ UML), thay vì cứng mã các cuộc gọi phương pháp của từng nhà cung cấp (hoặc Adaptee ), sau đó bạn có thể tạo ra một giao diện chung (gọi là Target trong sơ đồ UML) để bọc những hành vi và làm việc tương tự chỉ với một loại đối tượng.

Các Adapters sau đó sẽ thực hiện các mục tiêu giao diện ủy phương pháp các cuộc gọi của nó đến Adaptees được truyền cho các bộ điều hợp qua constructor.

Để bạn nhận ra điều này trong mã Java, tôi đã viết một dự án rất đơn giản bằng cách sử dụng chính xác ví dụ đã đề cập ở trên bằng cách sử dụng bộ điều hợp để xử lý nhiều giao diện TV thông minh. Mã nhỏ, được ghi chép đầy đủ và có thể tự giải thích vì vậy hãy tìm hiểu kỹ về nó để xem cách triển khai trong thế giới thực sẽ như thế nào.

Chỉ cần tải xuống mã và nhập nó vào Eclipse (hoặc IDE yêu thích của bạn) dưới dạng một dự án Maven. Bạn có thể thực thi mã bằng cách chạy org.example.Main.java . Hãy nhớ rằng điều quan trọng ở đây là hiểu cách các lớp và giao diện được lắp ráp với nhau để thiết kế mẫu. Tôi cũng tạo ra một số giả Adaptees trong gói com.thirdparty.libs . Hy vọng nó giúp!

https://github.com/Dannemann/java-design-patterns


2

Một ví dụ thực tế là Qt-Dbus.

Qt-dbus có một tiện ích để tạo bộ điều hợp và mã giao diện từ tệp xml được cung cấp. Dưới đây là các bước để làm như vậy.

 1. Create the xml file - this xml file should have the interfaces 
that can be viewed by the qdbus-view in the system either on 
the system or session bus.

    2.With the utility - qdbusxml2cpp , you generate the interface adaptor code. 
This interface adaptor does the demarshalling of the data that is 
received from the client. After demarshalling, it invokes the 
user defined - custom methods ( we can say as adaptee).

    3. At the client side, we generate the interface from the xml file. 
This interface is invoked by the client. The interface does the 
marshalling of the data and invokes the adaptor interface. As told 
in the point number 2, the adaptor interface does the demarshalling 
and calls the adaptee - user defined methods.

Bạn có thể xem ví dụ đầy đủ về Qt-Dbus ở đây -

http://www.tune2wizard.com/linux-qt-signals-and-slots-qt-d-bus/


2

Bạn có thể tìm thấy một triển khai PHP của mẫu Bộ điều hợp được sử dụng để bảo vệ chống lại các cuộc tấn công tiêm tại đây:

http://www.php5dp.com/category/design-patterns/adapter-composition/

Một trong những khía cạnh thú vị của mẫu Bộ điều hợp là nó có hai loại: Bộ điều hợp lớp dựa trên đa kế thừa và bộ điều hợp đối tượng dựa trên thành phần. Ví dụ trên dựa vào thành phần.


Liên kết php5dp.com/category/design-patterns/adapter-composition không hoạt động nữa
FantomX1

2

Các mẫu thiết kế bộ điều hợp giúp chuyển đổi giao diện của một lớp thành giao diện của khách hàng mong đợi.

Ví dụ: Bạn có một dịch vụ trả về thời tiết (tính bằng độ C) bằng cách chuyển tên thành phố làm giá trị đầu vào. Bây giờ, giả sử rằng khách hàng của bạn muốn chuyển mã zip làm đầu vào và mong đợi nhiệt độ của thành phố đổi lại. Ở đây bạn cần một bộ điều hợp để đạt được điều này.

public interface IWetherFinder {
    public double getTemperature(String cityName);
}

class WeatherFinder implements IWetherFinder{
   @Override
   public double getTemperature(String cityName){
     return 40;
   }
}

interface IWeatherFinderClient
{
   public double getTemperature(String zipcode);
}  

public class WeatherAdapter implements IWeatherFinderClient {

    @Override
    public double getTemperature(String zipcode) {

        //method to get cityname by zipcode 
        String cityName = getCityName(zipcode);

        //invoke actual service
        IWetherFinder wetherFinder = new WeatherFinder();
        return wetherFinder.getTemperature(cityName);
    }

    private String getCityName(String zipCode) {
        return "Banaglore";
    }
}

0

Một ví dụ thực tế có thể là báo cáo tài liệu trong một ứng dụng. Mã đơn giản như ở đây.

Tôi nghĩ rằng bộ điều hợp rất hữu ích cho cấu trúc lập trình.

class WordAdaptee implements IReport{
    public void report(String s) {
        System.out.println(s +" Word");
    }
}

class ExcellAdaptee implements IReport{
    public void report(String s) {
        System.out.println(s +" Excel");
    }
}


class ReportAdapter implements IReport{
    WordAdaptee wordAdaptee=new WordAdaptee();
    @Override
    public void report(String s) {
        wordAdaptee.report(s);
    }
}

interface IReport {
    public void report(String s);
}

public class Main {
    public static void main(String[] args) {

        //create the interface that client wants
        IReport iReport=new ReportAdapter();

        //we want to write a report both from excel and world
        iReport.report("Trial report1 with one adaptee");  //we can directly write the report if one adaptee is avaliable 

        //assume there are N adaptees so it is like in our example
        IReport[] iReport2={new ExcellAdaptee(),new WordAdaptee()};

        //here we can use Polymorphism here  
        for (int i = 0; i < iReport2.length; i++) {
            iReport2[i].report("Trial report 2");
        }
    }
}

Kết quả sẽ là:

Trial report1 with one adaptee Word
Trial report 2 Excel
Trial report 2 Word

1
Đây thực sự là một proxy. Bộ điều hợp và bộ điều hợp có giao diện khác nhau. Họ không triển khai cùng một giao diện. Đó là những gì một proxy làm.
dvallejo

Đây không phải là mẫu Bộ điều hợp. Mẫu bộ điều hợp được sử dụng để triển khai giao diện đích mà bộ điều hợp không triển khai.
FedericoG

0

Sử dụng Bộ điều hợp khi bạn có giao diện không thể thay đổi nhưng bạn cần sử dụng. Hãy xem bạn là chàng trai mới vào văn phòng và bạn không thể khiến những sợi tóc hoa râm tuân theo các quy tắc của mình - bạn phải thích nghi với quy tắc của họ. Đây là một ví dụ thực tế từ một dự án thực tế mà tôi đã làm việc trong một thời gian nào đó mà giao diện người dùng là một.

Bạn có một ứng dụng đọc tất cả các dòng trong tệp thành cấu trúc dữ liệu Danh sách và hiển thị chúng dưới dạng lưới (chúng ta hãy gọi giao diện lưu trữ dữ liệu bên dưới là IDataStore). Người dùng có thể điều hướng qua các dữ liệu này bằng cách nhấp vào các nút "Trang đầu tiên", "Trang trước", "Trang tiếp theo", "Trang cuối cùng". Mọi thứ đều hoạt động tốt.

Bây giờ ứng dụng cần được sử dụng với nhật ký sản xuất quá lớn để đọc vào bộ nhớ nhưng người dùng vẫn cần điều hướng qua nó! Một giải pháp sẽ là triển khai Cache lưu trữ trang đầu tiên, trang tiếp theo, trang trước và trang cuối cùng. Những gì chúng tôi muốn là khi người dùng nhấp vào "Trang tiếp theo", chúng tôi trả lại trang từ bộ nhớ cache và cập nhật bộ nhớ cache; khi họ nhấp vào trang cuối cùng, chúng tôi sẽ trả lại trang cuối cùng từ bộ nhớ cache. Ở chế độ nền, chúng tôi có một luồng phim làm tất cả những điều kỳ diệu. Làm như vậy, chúng tôi chỉ có bốn trang trong bộ nhớ thay vì toàn bộ tệp.

Bạn có thể sử dụng bộ điều hợp để thêm tính năng bộ đệm mới này vào ứng dụng của mình mà người dùng không nhận ra. Chúng tôi mở rộng IDataStore hiện tại và gọi nó là CacheDataStore. Nếu tệp cần tải lớn, chúng tôi sử dụng CacheDataStore. Khi chúng tôi đưa ra yêu cầu cho các trang Đầu tiên, Tiếp theo, Trước đó và Cuối cùng, thông tin sẽ được chuyển đến Bộ nhớ cache của chúng tôi.

Và ai biết được, ngày mai ông chủ muốn bắt đầu đọc các tệp từ một bảng cơ sở dữ liệu. Tất cả những gì bạn làm vẫn là mở rộng IDataStore thành SQLDataStore như bạn đã làm với Cache, thiết lập kết nối ở chế độ nền. Khi họ nhấp vào Trang tiếp theo, bạn tạo truy vấn sql cần thiết để tìm nạp vài trăm hàng tiếp theo từ cơ sở dữ liệu.

Về cơ bản, giao diện ban đầu của ứng dụng không thay đổi. Chúng tôi chỉ đơn giản là điều chỉnh các tính năng hiện đại và thú vị để hoạt động trong khi vẫn giữ được giao diện cũ.


Tôi không hiểu? Có vẻ như bạn vừa sử dụng một giao diện hiện có và thực hiện các phương pháp? Đâu là giao diện khác nhau mà bạn cần thích ứng và lớp bộ điều hợp?
berimbolo

@berimbolo Sự nhầm lẫn của bạn là hợp lệ vì ví dụ trên không nói rõ về mẫu bộ điều hợp.
rahil008

0

Ví dụ của @Justice o không nói rõ về mẫu bộ điều hợp. Mở rộng câu trả lời của anh ấy - Chúng tôi có IDataStore giao diện hiện tại mà mã người tiêu dùng của chúng tôi sử dụng và chúng tôi không thể thay đổi nó. Bây giờ chúng ta được yêu cầu sử dụng một lớp mới thú vị từ thư viện XYZ để thực hiện những gì chúng ta muốn triển khai, nhưng nhưng, chúng ta không thể thay đổi lớp đó để mở rộng IDataStore của mình, đã thấy vấn đề chưa? Tạo một lớp mới - ADAPTOR, thực hiện giao diện mà mã người dùng của chúng ta mong đợi, tức là IDataStore và bằng cách sử dụng lớp từ thư viện có các tính năng mà chúng ta cần có - ADAPTEE, với tư cách là một thành viên trong ADAPTOR của chúng ta, chúng ta có thể đạt được những gì chúng ta muốn.



0

Một ví dụ từ khung công tác Yii sẽ là: Yii sử dụng bộ đệm ẩn nội bộ bằng cách sử dụng ICache giao diện. https://www.yiiframework.com/doc/api/1.1/ICache

chữ ký của ai giống như: -

abstract public boolean set(string $id, mixed $value, integer $expire=0, ICacheDependency $dependency=NULL)
abstract public mixed get(string $id)

Giả sử, bạn muốn sử dụng bên trong một dự án Yii, thư viện bộ đệm symfony https://packagist.org/packages/symfony/cache với giao diện bộ đệm của nó, bằng cách định nghĩa dịch vụ này trong cấu hình các thành phần dịch vụ Yii (bộ định vị dịch vụ) https: / /github.com/symfony/cache-contracts/blob/master/CacheInterface.php

    public function get(string $key, callable $callback, float $beta = null, array &$metadata = null);

Chúng ta thấy, symfony cache có giao diện chỉ có một phương thức get, thiếu một phương thức set và một chữ ký khác cho một phương thức get, vì Symfony sử dụng phương thức get cũng như một setter khi cung cấp tham số có thể gọi thứ hai.

Vì lõi Yii sử dụng nội bộ bộ nhớ cache / giao diện Yii này, nên rất khó (mở rộng Yii / YiiBase) nếu không muốn nói là không thể ở nhiều nơi, để ghi lại các lệnh gọi vào giao diện đó.

Thêm vào đó, bộ nhớ cache Symfony không phải là lớp của chúng tôi, vì vậy chúng tôi không thể viết lại giao diện của nó để phù hợp với giao diện bộ nhớ cache Yii.

Vì vậy, đây là mẫu bộ điều hợp để giải cứu. Chúng tôi sẽ viết một ánh xạ = một bộ điều hợp trung gian sẽ ánh xạ các cuộc gọi giao diện bộ nhớ cache Yii đến giao diện bộ nhớ cache Symfony

Sẽ giống như thế này

    class YiiToSymfonyCacheAdapter implements \Yii\system\caching\ICache
    {
        private \Symfony\Contracts\Cache\CacheInterface $symfonyCache;

        public function __construct(\Symfony\Contracts\Cache\CacheInterface $symfonyCache)
        {
            $this->symfonyCache = $symfonyCache;
        }

      
      public boolean set(string $id, mixed $value, integer $expire=0, ICacheDependency 
       $dependency=NULL) 
      {

          // https://symfony.com/doc/current/cache.html
          return $this->symfonyCache->get(
              $id, 
              function($item) { 
              // some logic .. 
               return $value; 
              }
          );

//          https://github.com/symfony/cache/blob/master/Adapter/MemcachedAdapter.php
// if a class could be called statically, the adapter could call statically also eg. like this
//          return \Symfony\Component\Cache\Adapter\MemcacheAdapter::get(
//              $id, 
//              function($item) { 
//              // some logic .. 
//               return $value; 
//              }
          );
       }

       public mixed get(string $id) 
       {
           // https://github.com/symfony/cache/blob/master/Adapter/FilesystemAdapter.php 
           // if a class could be called statically, the adapter could call statically also eg. like this
           // \Symfony\Component\Cache\Adapter\FileSystemAdapter::get($id)
           return $this->symfonyCache->get($id) 
       }
    } 


-1

Đây là một ví dụ về triển khai bộ điều hợp:

interface NokiaInterface {
    chargementNokia(x:boolean):void
}


class SamsungAdapter implements NokiaInterface {
//nokia chargement adapted to samsung
    chargementNokia(x:boolean){
        const old= new SamsungCharger();
        let y:number = x ? 20 : 1;
        old.charge(y);
      }
}


class SamsungCharger {
      charge(x:number){
            console.log("chrgement x ==>", x);
      }
}


function main() {
      //charge samsung with nokia charger
      const adapter = new SamsungAdapter();
      adapter.chargementNokia(true);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.