设计模式 结合Alamofire

27 篇文章 0 订阅

设计模式 结合Alamofire

单例模式

保证一个类仅有一个实例。

单例一旦创建,对象指针保存在静态区,单例对象在堆中分配的内存空间只有等程序结束才能释放,所以过多的单例会增大内存的小号。如果不是应用程序的生命周期短,就不应该使用单例。一般是伴随着程序的出生和结束的,所以一般使用单例模式来封装网络请求。

public let AF = Session.default
网络状态监听管理器
public static let `default` = NetworkReachabilityManager()

public static let `default`: HTTPHeaders = [.defaultAcceptEncoding,
                                                .defaultAcceptLanguage,
                                                .defaultUserAgent]
适配器模式

类适配器中适配器继承于被适配者,适配器方法中调用父类的方法进行适配

监听请求的整体流程,EventMonitor统一对外回调我们关心的接口,只需要继承EventMonitor,调用里面的函数接口,不需要知道代码的实现逻辑

class GitNetworkLogger: EventMonitor {
   /// 请求完成,开始解析响应数据
  func requestDidFinish(_ request: Request) {
    print(request.description)
  }
}
let networkLogger = GitNetworkLogger()

return Session(
        configuration: configuration,
        interceptor: interceptor,
        cachedResponseHandler: responseCacher,
        eventMonitors: [networkLogger]
)

桥接模式

将抽象部分与它的实现部分分离,使它们都可以独立地变化。paramsEncoder是一个很好的例子

/// 参数编码,有些情况需要把参数编码到URL中,包含了转义相关的知识
public protocol ParameterEncoder {
  /// 把Parameters类型的参数编码进URLRequest中,但是要求Parameters类型必须符合Encodable协议
      func encode<Parameters: Encodable>(_ parameters: Parameters?, into request: URLRequest) throws -> URLRequest
}      

在URLEncodedFormParameterEncoder编码url query string数据

// MARK: URLEncodedFormParameterEncoder编码url query string数据
open class URLEncodedFormParameterEncoder: ParameterEncoder {
/// 实现协议的编码参数方法,把编码参数丢入body或URL上
    open func encode<Parameters: Encodable>(_ parameters: Parameters?,
                                            into request: URLRequest) throws -> URLRequest {

在JsonEncoder来编码数据,可以控制json的格式

/// 若编码的参数为符合Encodable类型的字典时,使用两种编码方式都ok。比如parameter = ["a": 1, "b": 2]这样的参数
open class JSONParameterEncoder: ParameterEncoder {
  // 实现协议的编码方法,把参数编码成JSONData
    open func encode<Parameters: Encodable>(_ parameters: Parameters?,
                                            into request: URLRequest) throws -> URLRequest {
组合模式

将对象组合成树形结构以表示部分-整体的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性,用户可以统一的使用组合结构中的所有对象。

最简单的最常见的例子就是UIView,典型的树形结构。

在alamofire也有用到,组合模式最大的优点是他的节点可以自由增加,且调用节点方便

AF.request("https://httpbin.org/get")
        .responseString { response in
            print("Response String: \(response.value)")
        }
        .responseJSON { response in
            print("Response JSON: \(response.value)")
        }
装饰模式

其实Swift 的 extension就是装饰模式的一种,类应该接纳扩展,但避免修改。

外观模式

向现有的系统添加一个接口,来隐藏系统的复杂性。

只需要知道HTTPMethod的

public struct HTTPMethod: RawRepresentable, Equatable, Hashable {
    /// `CONNECT` method.
    public static let connect = HTTPMethod(rawValue: "CONNECT")
    /// `DELETE` method.
    public static let delete = HTTPMethod(rawValue: "DELETE")
    /// `GET` method.
    public static let get = HTTPMethod(rawValue: "GET")
    /// `HEAD` method.
    public static let head = HTTPMethod(rawValue: "HEAD")
    /// `OPTIONS` method.
    public static let options = HTTPMethod(rawValue: "OPTIONS")
    /// `PATCH` method.
    public static let patch = HTTPMethod(rawValue: "PATCH")
    /// `POST` method.
    public static let post = HTTPMethod(rawValue: "POST")
    /// `PUT` method.
    public static let put = HTTPMethod(rawValue: "PUT")
    /// `TRACE` method.
    public static let trace = HTTPMethod(rawValue: "TRACE")

    public let rawValue: String

    public init(rawValue: String) {
        self.rawValue = rawValue
    }
}
享元模式

如果存在可以复用的对象,那么对象将被共享而不是创建新的对象。享元模式的最佳实践就是UITableView的复用机制——超出屏幕外的单元格统一被回收放到一个复用队列之中,等待着需要新的单元格时进行复用。

享元模式可以再次创建对象 也可以取缓存对象

单例模式则是严格控制单个进程中只有一个实例对象

代理模式

为其他对象提供一种代理以控制对这个对象的访问。

/// 把各个状态事件派发给事件监听器对象
open class SessionDelegate: NSObject {
///持有一个强引用EventMonitor协议对象, 用来接收请求中的各个状态事件
    var eventMonitor: EventMonitor? (声明)

需要调用的话嵌入

// 收到需要验证证书的回调
    open func urlSession(_ session: URLSession,
                         task: URLSessionTask,
                         didReceive challenge: URLAuthenticationChallenge,
                         completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        //告知事件监听器
        eventMonitor?.urlSession(session, task: task, didReceive: challenge)

继承代理,实现代理的内容

class GitNetworkLogger: EventMonitor {
   ///收到响应数据
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        print(data)
    }
}
职责链模式

避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式是一种对象行为型模式。

Ps: 点击事件:如果给定的响应者对象 .isUserInteractionEnabled = false就把信息传递给下一个响应者

命令模式

请求对象将一或多个动作绑定在特定的接收者上。

func allAction() {
        action1()
        action2()
        action3()
}
解释器模式

可以将一个需要解释执行的语言中的句子表示为一个抽象语法树;一些重复出现的问题可以用一种简单的语言来进行表达;一个语言的文法较为简单。option + command + /

迭代器模式

迭代器模式可以让用户通过特定的接口巡访容器中的每一个元素而不用了解底层的实现。常见用在数组

ps:数组 .append .remove 就是迭代器的一种

中介者模式

用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

session就是alamofire的中介者

截屏2021-12-29 下午3.33.03备忘录模式

在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

alamofire的缓存就是备忘录模式

/// 先修改数据,再缓存新的数据,参数为修改数据的闭包,改闭包返回可选的新缓存数据
        let responseCacher = ResponseCacher(behavior: .modify { _, response in
          let userInfo = ["date": Date()]
          return CachedURLResponse(
            /// 与实例关联的URL响应对象。
            response: response.response,
            /// 缓存响应的数据
            data: response.data,
            /// 缓存响应的用户信息字典
            userInfo: userInfo,
            /// 硬盘和内存没有限制
            storagePolicy: .allowed)
        })
观察者模式

一个对象的状态发生变化时,其它具有依赖关系的对象可以自动地被通知和更新

KVO NSKeyValueObservation 通知 notification

 var stuName: String = "" {        willSet {            print("姓名即将修改,新值为:\(newValue)")        }        didSet {            print("姓名已经修改,旧值为:\(oldValue)")        }    }
状态模式

允许一个对象在其内部状态改变时改变它的行为。

Alamofire 的Request的State

public enum State {        /// Initial state of the `Request`.        /// Request初始状态        case initialized        /// 调用resume()的时候更新为该状态, 同时对所有自己创建的task调用resume()方法        case resumed        /// 类似上面resumed        case suspended        /// 类似上面,不同的是,一旦调用了canceled,Request就不再能转变为其他状态了        case cancelled        /// 当响应解析全部完成,并且回调被清楚后更新为该状态        case finished

开始发送请求的判断

        request.withState { state in            switch state {            // 初始化或者请求完成,什么都不干            case .initialized, .finished:                // Do nothing.                break            // 发送请求            case .resumed:                task.resume()                //告知request task开始请求                rootQueue.async { request.didResumeTask(task) }            // 请求挂起            case .suspended:                task.suspend()                //告知request task挂起请求                rootQueue.async { request.didSuspendTask(task) }            // 请求取消            case .cancelled:                // Resume to ensure metrics are gathered.                //先恢复task 再取消, 保证task被取消                task.resume()                task.cancel()                //告知request task取消请求                rootQueue.async { request.didCancelTask(task) }            }        }
策略模式

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。swift的常见用法就是定义协议protocol,让需要的类遵守该协议

模板方法模式

模板方法模式使子类可以重定义一个算法中的特定步骤,而不需要改变算法的结构。

定义一个超类,继承这个超类

典型的模板方法模式为override func

Alamofire重定义请求状态

/// 重置请求状态    func reset() {        error = nil        uploadProgress.totalUnitCount = 0        uploadProgress.completedUnitCount = 0        downloadProgress.totalUnitCount = 0        downloadProgress.completedUnitCount = 0        $mutableState.write { state in            state.isFinishing = false            state.responseSerializerCompletions = []        }    }
/// 重置请求时要把已下载的data清空    override func reset() {        super.reset()        mutableData = nil    }
访问者模式

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者不同的一般的设计模式,开发中的实际场景相对较少
定义访问类

class PlaceVisitor {    func visitor(boss:Boss) {}        func visitor(employee:Employee) {}}

元素基类为Person

class Person {        func accept(visitor:PlaceVisitor) {}}

Employee继承Person

class Employee:Person {        override func accept(visitor: PlaceVisitor) {        visitor.visitor(employee: self)    }    }

定义访问行为

class PlaceVisitor {    func visitor(employee:Employee) {}}class HouseVisitor:PlaceVisitor {	    override func visitor(employee: Employee) {        print("员工在家看电视聊天")    }}

调用

let employee:Employee = Employee()let houseVisitor:PlaceVisitor = HouseVisitor()employee.accept(visitor: houseVisitor)
工厂方法模式

提供一个接口,用于创建与某些对象相关或依赖于某些对象的类家族,而又不需要指定它们的具体类。

Alamofire 使用大量的工厂模式例如

输入的是URLConvertible,其实是String -> URL

open func request(_ convertible: URLConvertible

String来继承URLConvertible

extension String: URLConvertible {    /// Returns a `URL` if `self` can be used to initialize a `URL` instance, otherwise throws.    ///    /// - Returns: The `URL` initialized with `self`.    /// - Throws:  An `AFError.invalidURL` instance.    public func asURL() throws -> URL {        guard let url = URL(string: self) else { throw AFError.invalidURL(url: self) }        return url    }}

在URLRequest的初始化里,转换为URL

public init(url: URLConvertible, method: HTTPMethod, headers: HTTPHeaders? = nil) throws {        let url = try url.asURL()        self.init(url: url)

我们只需要输入String就能转换为URL,转换失败也会返回AFError的错误提示

AF.request("https://www.baidu.com").responseString { resp in
建造者模式

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。

Product & bulider

Alamofire的一个例子 参数编码

//参数编码,有些情况需要把参数编码到URL中,包含了转义相关的知识public protocol ParameterEncoder {  func encode<Parameters: Encodable>(_ parameters: Parameters?, into request: URLRequest) throws -> URLRequest}

leader

struct RequestEncodableConvertible<Parameters: Encodable>: URLRequestConvertible {let encoder: ParameterEncoderreturn try parameters.map { try encoder.encode($0, into: request) } ?? request
原型模式

使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式。

原型模式创建新对象的过程中是拷贝,具体实现由深拷贝和浅拷贝之分.

func clone() -> AnyObject? {    return nil}
class Book:Product {	var name:String?	var price:Float = 0.0	override func clone() -> AnyObject? {    let book:Book = Book()    book.name = self.name    book.price = self.price    return book	}}let book:Book = Book()let temp:Book = book.clone() as! Book
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值