Adapter Pattern

📢 This article was translated by gemini-2.5-flash

Adapter Pattern: Class Structural / Object Structural Patterns

Intent

Convert the interface of a class into another interface clients expect. The Adapter pattern allows classes with incompatible interfaces to work together.

Structure

  1. Class Adapter uses multiple inheritance to match one interface to another.

image

  1. Object Adapter relies on object composition.

image

Here’s what each part does:

  • Target defines the domain-specific interface that Client uses.
  • Client collaborates with objects conforming to the Target interface.
  • Adaptee defines an existing interface that needs adapting.
  • Adapter adapts Adaptee’s interface to the Target interface.

Applicability

Use the Adapter pattern when:

  • You want to use an existing class, but its interface doesn’t match what you need.
  • You want to create a reusable class that can work with other unrelated or unforeseen classes (i.e., those whose interfaces might not be compatible).
  • (Object Adapter only) You want to use an existing subclass, but it’s impractical to subclass every one to match their interfaces. An object adapter can adapt its parent class’s interface.

Example 1

In a software system, an Address class has been designed and implemented to display address information. Now, there’s a requirement to provide a Dutch-language interface for address display. To meet this, and anticipating future language interfaces, the Adapter pattern is chosen. Here’s the class diagram:

适配器模式-例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class Adapter {
    public static void main(String[] args) {
        Address address = new Address();
        DutchAddress dutchAddress = new DutchAddressAdapter(address);
        System.out.println("The DutchAddress");
        test(dutchAddress);
    }
    
    static void test(DutchAddress dutchAddress){
        dutchAddress.plaats();
        dutchAddress.postcode();
        dutchAddress.straat();
    }
}

class Address{
    public void street(){/* code omitted */}
    public void zip(){/* code omitted */}
    public void city(){/* code omitted */}
}

class DutchAddress{
    public void straat(){/* code omitted */}
    public void postcode(){/* code omitted */}
    public void plaats(){/* code omitted */}
}

class DutchAddressAdapter extends DutchAddress{
    private Address address;
    public DutchAddressAdapter(Address address){
        this.address=address;
    }

    @Override
    public void straat() {
        address.street();
    }

    @Override
    public void postcode() {
        address.zip();
    }

    @Override
    public void plaats() {
        address.city();
    }
}

Example 2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Since Java doesn't support multiple inheritance, the following is an Object Adapter.
public class main{
     public static void main(String[] args) {
        Target target = new Adapter();
        target.Request();
    }
}

class Target{
    public void Request(){
        System.out.println("hello");
    }
}

class Adapter extends Target{
    private Adaptee a = new Adaptee();

    @Override
    public void Request(){
        a.SpecificRequest();
    }
}

class Adaptee{
    public void SpecificRequest(){
        System.out.println("hi");
    }
}