iOS开发常用设计模式之职责链模式

何为职责链模式

职责链模式(Chain of Responsibility Pattern)是一种行为设计模式,用于将请求的发送者和接收者解耦,并允许多个对象依次处理请求,直到找到能够处理请求的对象为止。

在职责链模式中,请求被沿着一个对象链传递,每个对象都有机会处理请求或将其传递给链中的下一个对象。这样的链可以动态地组合和修改。

职责链模式由以下几个角色组成:

  1. Handler(处理者):定义一个处理请求的接口,通常包含一个处理方法。它可以是抽象类或接口。每个具体处理者都维护一个对下一个处理者的引用。

  2. ConcreteHandler(具体处理者):实现处理请求的具体逻辑。如果它能够处理请求,则进行处理;否则,将请求传递给下一个处理者。

使用职责链模式的好处包括:

  1. 解耦发送者和接收者:发送者不需要知道请求被谁处理,接收者也不需要知道请求的发送者是谁。它们只需要与链中的对象进行交互。

  2. 灵活性和可扩展性:可以通过简单地添加或移除处理者来改变请求的处理流程,而不需要修改发送者的代码。

  3. 支持动态组合:可以根据需要动态地组合处理者的顺序,以满足不同的业务需求。

需要注意的是,职责链模式可能会导致请求的传递链过长,从而增加处理请求的时间。因此,在设计职责链时需要权衡链的长度和性能。

总之,职责链模式提供了一种灵活的方式来组织和处理请求,使得请求的发送者和接收者之间解耦,同时支持动态的请求处理流程。

如何使用职责链模式

在 iOS 开发中,可以使用职责链模式来处理事件响应链或者处理视图层次结构中的事件传递。以下是在 iOS 开发中使用职责链模式的一个示例:

  1. 定义处理请求的接口:创建一个抽象类或接口,定义处理请求的方法。在 iOS 中,可以使用协议(Protocol)来定义接口。
swift 复制代码
protocol Handler {
    var successor: Handler? { get set }
    func handleRequest(request: Request)
}
  1. 实现具体的处理者:创建具体的处理者类,实现处理请求的方法。在 iOS 中,可以使用视图或视图控制器来实现处理者。
swift 复制代码
class ConcreteHandler1: UIView, Handler {
    var successor: Handler?
    
    func handleRequest(request: Request) {
        if (可以处理请求的条件) {
            // 处理请求的逻辑
        } else if let nextHandler = successor {
            nextHandler.handleRequest(request: request) // 将请求传递给下一个处理者
        }
    }
}

class ConcreteHandler2: UIViewController, Handler {
    var successor: Handler?
    
    func handleRequest(request: Request) {
        if (可以处理请求的条件) {
            // 处理请求的逻辑
        } else if let nextHandler = successor {
            nextHandler.handleRequest(request: request) // 将请求传递给下一个处理者
        }
    }
}
  1. 创建处理者链并发送请求:在使用职责链模式时,创建处理者对象并设置它们的后继关系。然后,将请求发送给链中的第一个处理者。
swift 复制代码
let handler1 = ConcreteHandler1()
let handler2 = ConcreteHandler2()

handler1.successor = handler2

handler1.handleRequest(request: request) // 发送请求

在这个示例中,处理者链由 handler1handler2 组成。请求首先发送给 handler1,如果 handler1 不能处理该请求,则将请求传递给 handler2。可以根据具体的需求调整处理者的顺序、添加新的处理者或移除现有的处理者。

在职责链模式中,"Request" 是指代被传递和处理的请求对象。它是一个自定义的数据结构,用于封装请求的相关信息,以便处理者能够识别和处理请求。

具体的 "Request" 对象的定义和结构取决于实际的应用场景和需求。它可以包含与请求相关的任何数据,例如事件类型、参数、标识符等。

在 iOS 开发中,"Request" 可以是一个自定义的类或结构体,具体的属性和方法根据具体的需求进行定义。以下是一个简单的示例,展示了一个名为 "Request" 的自定义类的可能结构:

swift 复制代码
class Request {
    let eventType: EventType
    let eventData: [String: Any]
    
    init(eventType: EventType, eventData: [String: Any]) {
        self.eventType = eventType
        self.eventData = eventData
    }
}

enum EventType {
    case buttonTap
    case gestureRecognized
    // 其他事件类型
}

在上述示例中,"Request" 类具有两个属性:eventTypeeventDataeventType 表示事件类型,使用枚举类型 EventType 来定义不同的事件类型。eventData 是一个字典,可以包含与事件相关的任何数据。

在实际使用中,可以根据需要在 "Request" 类中添加其他属性和方法,以满足具体的业务逻辑和需求。

总结:在职责链模式中,"Request" 是一个自定义的请求对象,用于封装请求的相关信息。它是处理者识别和处理请求的基础。具体的 "Request" 对象的定义和结构根据实际需求而定。

职责链模式的优缺点

职责链模式(Chain of Responsibility Pattern)具有以下优点和缺点:

优点:

  1. 解耦发送者和接收者:职责链模式将发送者和接收者解耦,发送者无需知道请求将由哪个具体的处理者处理,接收者也无需知道请求的发送者是谁。这增强了系统的灵活性和可维护性。

  2. 可扩展性:职责链模式允许在运行时动态地添加或修改处理者,可以根据需要自由地调整处理链的结构。这样可以方便地新增或改变处理请求的逻辑,而无需修改现有的代码。

  3. 动态组合:可以根据不同的业务需求动态地组合处理者的顺序。同一个处理链可以以不同的顺序处理请求,从而实现不同的业务逻辑。

  4. 单一职责原则:职责链模式有助于遵循单一职责原则,每个具体的处理者只负责处理特定类型的请求。这样有助于代码的组织和维护。

缺点:

  1. 请求未被处理的风险:由于职责链模式中的请求被传递给多个处理者,有一定的风险存在请求未被处理的情况。如果没有正确设置或配置处理者链,请求可能会在链中被忽略而得不到处理。

  2. 性能问题:职责链模式可能会导致请求的传递链过长,从而增加处理请求的时间。在处理大量请求时,可能需要考虑链的长度和性能影响。

  3. 可能导致系统变得复杂:职责链模式的灵活性和可扩展性可能导致系统的复杂性增加。处理链的设计和维护需要考虑处理者的顺序、条件判断等因素,可能增加系统的理解和调试难度。

适用场景: 职责链模式适用于以下情况:

  • 有多个对象可以处理同一请求,但具体的处理者在运行时才确定。
  • 需要在不明确接收者的情况下,将请求的发送者和接收者解耦。
  • 希望动态地组合处理者并灵活地改变请求的处理流程。

总结: 职责链模式通过解耦发送者和接收者,提供了一种灵活的方式来组织和处理请求。它具有解耦、可扩展、动态组合和符合单一职责原则的优点。然而,它也存在请求未被处理的风险、性能问题和可能导致系统复杂化的缺点。在使用职责链模式时,需要权衡其优缺点,并根据具体的需求合理地设计和应用。

系統庫使用示例

在 iOS 系统库中,一个使用职责链模式的例子是事件响应链的处理。iOS 中的视图层次结构是一个典型的职责链模式的应用。

在 iOS 中,事件处理是通过事件响应链来实现的。当用户在屏幕上进行触摸或其他交互时,事件将从应用程序的顶层视图开始传递,经过视图层次结构中的各个视图,直到找到能够处理该事件的视图为止。

在这个过程中,每个视图都有机会处理事件,如果某个视图不能处理事件,它将把事件传递给其父视图,直到事件被处理或者传递到最顶层的视图控制器。

这个事件处理的过程就是一个职责链模式的应用。每个视图或视图控制器都充当了处理者(Handler),它们负责判断是否能够处理事件,并作出相应的响应。

以下是一个简化的示例,展示了事件响应链的处理过程:

swift 复制代码
class CustomView: UIView {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 处理触摸事件的逻辑
        if (可以处理触摸事件的条件) {
            // 处理触摸事件
        } else {
            // 将触摸事件传递给下一个响应者
            next?.touchesBegan(touches, with: event)
        }
    }
}

class CustomViewController: UIViewController {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // 处理触摸事件的逻辑
        if (可以处理触摸事件的条件) {
            // 处理触摸事件
        } else {
            // 将触摸事件传递给下一个响应者
            next?.touchesBegan(touches, with: event)
        }
    }
}

在上述示例中,CustomViewCustomViewController 分别是视图层次结构中的两个处理者。它们都重写了 touchesBegan(_:with:) 方法来处理触摸事件。如果当前视图或视图控制器能够处理触摸事件,则处理事件;否则,将事件传递给下一个响应者(即 next 属性)。

这样,当用户在界面上进行触摸操作时,事件将从最顶层的视图或视图控制器开始传递,逐级向下,直到找到能够处理事件的处理者为止。这个过程就是职责链模式在事件响应链中的应用。

相关推荐
大圣数据星球4 小时前
Fluss 写入数据湖实战
大数据·设计模式·flink
思忖小下5 小时前
梳理你的思路(从OOP到架构设计)_设计模式Template Method模式
设计模式·模板方法模式·eit
LCG元7 小时前
【面试问题】JIT 是什么?和 JVM 什么关系?
面试·职场和发展
GISer_Jing11 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试
m0_7482455211 小时前
吉利前端、AI面试
前端·面试·职场和发展
TodoCoder13 小时前
【编程思想】CopyOnWrite是如何解决高并发场景中的读写瓶颈?
java·后端·面试
Wyang_XXX14 小时前
CSS 选择器和优先级权重计算这么简单,你还没掌握?一篇文章让你轻松通关面试!(下)
面试
思忖小下15 小时前
梳理你的思路(从OOP到架构设计)_简介设计模式
设计模式·架构·eit
liyinuo201717 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范
代码中の快捷键18 小时前
java开发面试有2年经验
java·开发语言·面试