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?