1. Adapters in your life

What comes to mind when you think of adapters? Nothing is better than the power adapter, which is used in the daily use of computers, mobile phones and other electronic equipment will have a power adapter, the role is to convert the output of high voltage AC power in the socket into the low voltage DC power required by the electronic equipment. In addition, in addition to the standard voltage is different in various regions of the world, most of the power plug shape is also different, so there is a kind of adapter, used to connect the plug, such as Hong Kong’s standard socket is triangular square head, you need an adapter to connect the conversion.

In a nutshell, the function of an adapter is to allow devices that would otherwise not work together to work together without changing their behavior. In a broader sense, the docking docks used for various interfaces on laptops, the language translators you might use when traveling abroad, and the drivers for various video/sound cards/hard drives can all be understood as adapters.

2. Adapter mode

2.1 Adapter pattern definition

The definition in Head First design Patterns is as follows:

Adapter pattern: Transforms the interface of one class into another interface that the customer expects. Adapters allow classes with incompatible interfaces to work together.

There are three main roles in the adapter pattern:

  • TargetTarget interface/object
  • AdapteeThe object being adapted
  • AdapterThe adapter

That is, through the Adapter Adapter Adaptee is wrapped into an object that supports the Target interface Target, so that the original Target can be completed by the object wrapped by the Adapter can also support, so the Adapter is also called Wrapper.

For example, the gb triangular socket is generally triangular flat head, and the Hong Kong version of the power adapter is triangular square head, in the mainland is not good, need to get a converter, the Hong Kong version of the power adapter inserted in the converter and then the converter inserted in the GB socket, can work normally. The gb socket above corresponds to the Target interface role, the Hong Kong version triangular square plug is adapted to the object, additional dedicated adapter will gb triangular flat head into the Hong Kong version triangular square head.

2.2 Types of adapters

Adapters can be divided into two types based on how they are implemented: class adapters (inheritance) and object adapters (composition). The class diagram is as follows:

The class adapter implements the target interface through inheritance, which is subclassing. In languages that support multiple inheritance (C++, Python), the class adapter inherits both the parent class and the Target class. Since multiple inheritance is not supported in languages like Objective-C and Java, the Target Interface is usually the Protocol/Interface.

Object adapters access adaptive objects as needed in methods that implement the target interface by composing – treating the adaptive objects as attributes of the adapter.

Class adapters vs object adapters

The class adapter Object adapter
implementation inheritance combination
scope The matched class only The adaptor class and its subclasses
other + easy to overload, can override the behavior of the adaptor if necessary. + structurally simpler, no additional attributes are required to point to the target. + Can choose to delegate part of the work to the match, more flexible. – Additional attributes are required to point to the target.

2.3 Advantages and disadvantages of adapters

  • The consumer (client) is decoupled by binding to the interface rather than to the implementation.
  • Let unrelated classes work together without invading the original code and isolating the impact of the original system.
  • Too much use of adapters can lead to unstructured code (overuse of any pattern can be problematic)

2.4 Application Scenarios of adapters

  • With legacy code, projects are expected to consistently use new features and support existing classes. Head First Design Patterns CH 7. Examples of iterators and enumerations
  • Extend new functionality to facilitate access to new third-party libraries. → Eg. Everyone Knows Design Patterns e-reader extends PDF reading support by adapting third-party PDF parsing libraries.

3. Adapter mode in iOS

On iOS, Apple typically implements the adapter through a protocol (Target). For example, the common UITableViewDataSource, UITableViewDelegate, wraps a class that cannot provide data/responserelated events to a UITableView as a data source/proxy, which is clearly a class adapter. Refer to Raywenderlich for detailed practice introduction.

3.1 Attribute wrappers@propertyWrapper

Using attribute wrappers in Swift when you need to add the same logical code for attributes greatly reduces the effort. Property wrappers can be applied to structures, enumerations, or classes.

A TwelveOrLess attribute wrapper can be defined as follows:

TwelveOrLess @propertyWrapper struct TwelveOrLess {private storage number private var number = 0 // Package value var wrappedValue: Int {get {return number} set {number = min(newValue, 12)}}} // Use *TwelveOrLess* to define a small rectangle. The length and width are less than or equal to a certain value. struct SmallRectangle { @TwelveOrLess var height: Int @TwelveOrLess var width: Int rectangle = SmallRectangle() Int rectangle = SmallRectangle() Int rectangle = SmallRectangle() Int rectangle = SmallRectangle() Int rectangle = SmallRectangle() Rectangle. Height = 25 print(rectangle. Height)Copy the code

* The following is my personal understanding and may not be correct.

@propertwrapper can also be understood as a protocol that requires objects to implement Set/Get methods that wrap properties:

protocol PropertyWrapperProtocol {
    var wrappedValue : Int { set get }
}
Copy the code

TwelveOrLess implements PropertyWrapperProtocol to implement an adapter that returns a number within a limited range. If you try to set a number beyond the preset maximum value, it will only be saved as the maximum value. Analogies to a power adapter will be input to a low voltage adapter with high voltage. Of course the property adapter in Swift is more powerful and flexible, see the Swift GG translation documentation – Property wrapper.

3.2 Applying the proxy adapterUIApplicationDelegateAdaptor

IOS 14 new UIApplicationDelegateAdaptor for packaging the application of the original UIKit agent UIApplicationDelegate (NSApplicationDelegateAdaptor for AppKit, WKExtensionDelegateAdaptor for WatchKit), in order to access application in SwiftUI agent.

@propertyWrapper struct UIApplicationDelegateAdaptor<DelegateType> where DelegateType : NSObject, DelegateType : UIApplicationDelegate
Copy the code

You can see from @propertywrapper that this is actually a specific application scenario for a propertyWrapper. An object of type NSObject that follows the UIApplicationDelegate protocol is passed to the generic DelegateType, guessing that some internal operations are being performed by delegating to the proxy object, which is obviously an object adapter. Use it like this (see HackingWithSwift, StackOverflow: swiftui-app-life-cycle-ios14-what-put-appdelegate-code) :

class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        print("do something")
        return true
    }
}

@main
struct testApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
Copy the code

There are other iOS related adapter application examples to share and discuss.

That’s all you have learned so far about the adapter pattern. (some places with the illustration to understand more intuitive, seems to be almost what, some days together with the sample code 🙂

reference

  1. Raywenderlich – How To Use the Adapter Pattern. Contains a complete example demonstrating how to implement a generic horizontal scroll view using the protocol (data source & delegate broker).
  2. Bloodline – iOS design patterns – Adapter introduction is quite comprehensive.
  3. Head First Design Patterns CH 7. Adapter patterns versus appearance patterns. ① Use the socket as an example to parse the adapter; ② In the object-oriented Adapter section ‘Existing system → Adapter -) vendor class‘Examples are graphic; Example: Java uses EnumerationIterator to follow the new iteratorIteratorInterface to replace earlier enumerationsEnumerationIn addition to determining whether there is an element and accessing the next element, iterators also support removing elements.
  4. Chapter 13 in Everyone Knows Design Patterns – Understanding design patterns from life. (1) Examples of mortise and tenon structures in ancient Chinese buildings, different mortise and tenon slots work together; ② Example: a support.txt and.epub format e-reader project, through the adapter adaptation of a third party PDF parsing library to support PDF reading.

extension

  • Generally, an adapter wraps only one adapted object. Is there a scenario where an adapter ‘wraps’ multiple adapted objects? There are! That is the Facade Pattern.
  • In addition to changing the plug shape/current voltage, some power adapters provide additional features such as status indicators, extended USB ports, etc. These features are implemented through the Decorator Pattern. (Decorators add features, adapters transform interfaces)