如何使用状态设计模式创建有状态的ViewController?

有状态的ViewController是什么? 然后,我们将有状态ViewController命名为具有许多状态的ViewController,该ViewController应该能够基于当前状态更改视图或组件。

创建一个有状态的ViewController可能很棘手,首先,对于某些屏幕,我们可以有不同的加载和错误视图,例如,在LoginViewController我们的UIButton内部有加载,并且错误消息应使用自定义警报处理。 我们的HomeViewController应该显示一个默认的加载视图和一个知道如何处理Error默认错误视图。

我们希望以不必在许多视图控制器中重复代码或行为的方式构建它。

我们可以使用状态设计模式来处理它。 状态模式为:

一种行为软件设计模式,允许对象在内部状态发生变化时更改其行为。 状态模式可以解释为策略模式,它能够通过调用模式接口中定义的方法来切换当前策略。

定义我们的状态

我们定义了.success.loading.error(error) ,我们认为创建协议并将其添加到我们的ViewController会很棒。

这种方法的问题在于,每个视图控制器都会有一个巨大的switch case并且可能会有很多重复的代码。

😒:-“是的!是的,但是您可以解决这个创建函数的问题。”您说。

😅:—好! 但这不能解决我们的问题,只能掩饰它。

另一个问题是:“如果添加另一个状态会怎样?”是的! 我们需要将其添加到每个switch case或创建default switch case 。 添加另一种情况将使我们修改使用Statable协议的每个类,从而打破开放封闭原则。

创建单状态协议

我们认为如果将enumprotocol更改为新protocol会更好:

现在好多了! 这消除了switch case问题,但并不是我们想要的。

现在,即使具有默认的加载视图或错误视图,每个视图控制器都需要具有这三种方法。 换句话说,我们仍然在重复代码。

诚然,这种改变并没有使任何事情变得更好。 😓

我通常会说:

如果您使用的协议方法具有默认实现,或者不会在每个类/结构中使用,则该方法不应存在。

破坏我们的状态协议

一些视图控制器不需要实现setLoadingState()setErrorState(error: Error)这将由默认类处理。 因此,我们决定将协议分为三个部分。

这将是很棒的,因为我们可以创建默认的加载和错误视图:

默认加载视图
默认错误视图

并且还将自定义行为添加到某些UIViewControllers例如,如果您想更改在已定义的ViewController中的加载方式或自定义警报以显示错误消息,则可以在ViewController中处理所有三种协议,例如:

处理默认状态

最后,我们可以在ViewController中创建一个装饰器来处理所有状态,并在每次需要时在它们之间切换。

结论

使用这种方法,我们可以在需要时具有自定义的加载和错误视图,而在不需要自定义的时可以使用默认实现。 我们可以创建许多不同的类来处理加载,从而使我们的DefaultLoadingState关闭以进行修改,而打开以进行扩展。

我们将状态设计模式和装饰器模式混合在一起,以创建一个StatableViewController来处理视图控制器中的状态。 使用依赖注入,我们可以在单个入口点中从控制器更改加载和错误行为。

附:如果您喜欢此帖子,请在Twitter上分享,或在中等水平上推荐,或两者都=)。 这确实有助于我吸引更多人。 非常感谢。