Recently, I have more time, so I should write more and improve my organizational ability and written expression ability. After all, good copywriting is also very necessary. Today’s introduction is to the adapter pattern of the structural pattern, and the object pattern of the adapter pattern is the basis for subsequent structural models.

Definition:

Converting the interface of one class into another that the customer wants makes it possible for classes that would otherwise not work together due to interface incompatibilities. There are three main types of adapter patterns: class adapter patterns, object adapter patterns, and interface adapter patternsCopy the code

It is clear from the definition that the function of the adapter pattern is transformation.

For example, different countries have different socket standards. If you want to use Chinese appliances, you need adapters to transfer.

The adapter pattern involves three roles: Source: An object or type that needs to be adapted, equivalent to a plug. Adapter: An intermediate object that connects a target to a source, equivalent to a plug converter. Target: A desired Target, equivalent to a socket.Copy the code

The class adapter

The relationship between Adapter and Adaptee is inheritance, which determines that this is a class Adapter pattern.Copy the code
/ / source open class Adaptee {fun method1 () {the v (" = = = = = = = ", "1")}}Copy the code
Interface Target {fun method1() fun method2()}Copy the code
/ / Adapter class Adapter: Adaptee (), Target {override fun an () {the v (" = = = = = = = ", "method 2")}}Copy the code

This calls method1() directly in Adaptee.

var adapter = Adapter()
adapter.method1()
adapter.method2()
Copy the code

## Object adapter

As with the class adapter pattern, we concatenate the Adaptee with Target to enable the client to use the Adaptee class. But instead of inheriting an Adaptee, we're encapsulating an Adaptee into an Adapter. Here the Adaptee and Adapter are combinedCopy the code
Class ObjectAdapter(adaptee: Adaptee):Target { private var adaptee = adaptee override fun method1() { adaptee.method1() } override fun method2() { Log.v("========"," object mode method 2")}}Copy the code

Usage:

var adapter = ObjectAdapter(Adaptee())
adapter.method1()
adapter.method2()
Copy the code

Differences between class adapters and object adapters

Class adapters inherit directly from Adaptee, so they cannot adapt subclasses of Adaptee. Object adapters use a composite approach, so Adaptee and its descendants can be adapted. In addition, object adapters are very convenient for adding new lines, and the added behavior applies to all sources simultaneously. Based on the principle of composition/aggregation over inheritance, using an object adapter is a better choice. But it should be done on a case-by-case basis, and in some cases it may be appropriate to use a class adapter, but the best one is the best one.Copy the code

Interface adapter

The interface needs to implement too many methods, use whether useful or not have to implement, use adapter first default to achieve some functions, just to achieve the need to achieve the function.Copy the code

Use abstract class to do a transfer implementation, the specific way is not introduced here.

Let’s see how it’s used in a project

class Task(num:Long):Callable<Long> { private var num = num override fun call(): Long { var r: Long = 0 for (n in 1.. num) { r += n } Log.v("========","Result: $r") return r } }Copy the code

To compute and in Task, you want to run this functionality in a Thread. The code is as follows:

Callable<Long> callable = new Task(123450000L);
Thread thread = new Thread(callable); // compile error!
thread.start();
Copy the code

Found compilation however! Thread receives the Runnable interface, but does not receive the Callable interface.

One solution is to rewrite the Task class to implement a Runnable instead of a Callable, but this is not a good idea because the Task is likely to be referred to elsewhere as a Callable, and rewriting the interface of the Task will cause the rest of the working code to fail to compile.

Instead of rewriting the Task class, use an Adapter that “turns” the Callable interface into a Runnable interface so that it can compile properly:

class RunnableAdapter(callable: Callable<Long>) : Runnable {
    var callable = callable

    override fun run() {
        try {
            callable.call()
        } catch (e: Exception) {

        }
    }
}
Copy the code
var callable = Task(1000L)
var thread = Thread(RunnableAdapter(callable))
thread.start()
Copy the code

Result: Result: 500500

By the way, am I using an object adapter pattern or a class adapter pattern?