如何在顺序命令之间传递数据?

时间:2016-01-16 15:05:24

标签: ios swift design-patterns command-pattern

我有一个客户端想要根据两个命令的组合工作来检索某些数据。我需要两个命令的原因是第二个命令依赖于第一个命令的数据。我的问题是将数据从第一个命令传递到第二个命令的最佳方法是什么?

我正在使用一个协调对象,它是第一个和第二个命令的委托 - 但这看起来很混乱。这可解析在所有命令所在的层中,还是需要这个协调对象?

以下是客户端类的表示:

class ViewController: UIViewController, CoordinatorDelegate {

    // ...

    @IBAction func didTouchButton(sender: UIButton) {
        self.coordinator.fetchSchoolID(firtName: "Jane", lastName: "Jones")
    }

    // MARK: - CoordinatorDelegate

    func fetchSchoolIDSucceeded(ID ID: Int) {
        self.updateUIWithSchoolID(ID)
    }

    func fetchSchoolIDFailed(error error: NSError) {
        self.displayError(error)
    }
}

协调员对象:

protocol CoordinatorDelegate {

    func fetchSchoolIDSucceeded(ID ID: Int)
    func fetchSchoolIDFailed(error error: NSError)

}

struct Coordinator: FetchSchoolInfoActionDelegate, FetchStudentInfoActionDelegate {

    let actionFactory: ActionFactory
    var delegate: CoordinatorDelegate?

    func fetchSchoolID(firstName: String, lastName: String) {

        let firstAction = self.actionFactory.fetchStudentInfoAction(firstName: firstName, lastName: lastName, delegate: self)

        firstAction.execute()
    }

    // MARK: - FetchStudentInfoActionDelegate

    func fetchStudentInfoSucceeded(studentInfo: StudentInfo) {

        let secondAction = self.actionFactory.fetchShoolInfoAction(schoolName: studentInfo.schoolName, delegate: self)

        secondAction.execute()
    }

    func fetchStudentInfoFailed(error: NSError) {
        self.delegate?.fetchSchoolIDFailed(error: error)
    }

    // MARK: - FetchSchoolInfoActionDelegate

    func fetchSchoolIDSucceeded(schoolInfo: SchoolInfo) {
        self.delegate?.fetchSchoolIDSucceeded(ID: schoolInfo.ID)
    }

    func fetchSchoolIDFailed(error: NSError) {
        self.delegate?.fetchSchoolIDFailed(error: error)
    }

}

总之,客户端(ViewController)想要获取给定schoolIDfirstName学生的lastName。为此,需要执行两个命令 - FetchStudentInfoActionFetchSchoolInfoAction。第二个Command取决于第一个Command中的数据 - 在这种情况下,FetchSchoolInfoAction需要schoolName检索到的学生FetchStudentInfoAction

这看起来很乱。如果我们想象会向ViewController添加更多请求,Coordinator对象将变得越来越复杂。当第二个命令需要来自第一个命令的数据时,是否有更好的方法来处理一组顺序命令?这可以由Command层的对象而不是Coordinator处理吗?

1 个答案:

答案 0 :(得分:0)

组合操作(fetchSchoolID)提示可能很容易变得更加复杂的实体/关系图。我建议你添加一个完成处理程序模式来返回异步请求的结果。

例如,如果execute()函数提供了一个完成处理程序,那么您就可以在fetchSchoolID的实现中获得特定的回调。

    let firstAction = self.actionFactory.fetchStudentInfoAction(firstName: firstName, lastName: lastName, delegate: self)

    firstAction.execute() 
    {
       (studentInfo) in
       let secondAction = self.actionFactory.fetchShoolInfoAction( ....
       secondAction.execute ...
    }

这需要在您的动作工厂中进行轻微的设计更改(存储和调用完成捕获,但它将极大地增加组合和链接操作的灵活性。

要在您的动作类中实现此功能,您可以执行以下操作:

class FetchStudent:YourBaseActionClass
{
   var completionHandler:((StudentInfo)->())? = nil

   // execute allow specification of a completion handler
   // but doesn't require it
   override func execute(completion:((StudentInfo)->())? = nil)
   {
      completionHandler = completion
   }

   // I assume you have something like this in here that
   // builds the StudentInfo before returning it through the delegate
   func fetchComplete() 
   {
      //... your code that prepared the student info
      completionHandler?(studentInfo)
   }

   ...