First take a look at the wiki explanation of the mediator pattern:

In software engineering, the mediator pattern defines an object that encapsulates how a set of objects interact. This pattern is considered to be a behavioral pattern due to the way it can alter the program’s running behavior.

In software engineering, a mediation pattern defines an object that encapsulates how a set of objects interact. This pattern is considered a behavior pattern because it can change the running behavior of a program.

In a project, the program we develop is made up of a large number of classes. As the functionality of the program increases, the dependencies between classes become more complex. The mediator pattern solves this problem.

This complex dependency is typically represented by ViewController(VC) defined in the MVC pattern commonly used in iOS development. In general, a page corresponds to one VC in the code, and a medium-sized software will have at least dozens of pages, corresponding to dozens of VC. (Of course you can also say VC reuse, but under normal circumstances, VC reuse scenarios would be this much? Here we do not consider the case of reusing VC. And to manage the relationship between these VC is a very tedious thing, we have to deal with the relationship between various VC, every time a VC to jump to another VC, we need to include the header file of the new VC, so some pages that play a bridging role contain a large number of other VC header files. At the same time, whenever the product manager requires to modify the logical relationship of some pages, we need to modify these header files and the corresponding code, I think I have a big head. Similar to the picture below:

The use of the mediator pattern can be very good to solve this problem. The function of this class is to bind a URL to each VC. When a new VC needs to be opened, the URL of the new VC can be passed through the openURL interface of the function class. The party initiating openURL does not need to rely on the new VC, but only needs to establish a relationship with the function class, as shown below:

The Mediator class acts as a Router to redirect URL requests initiated by customers to the corresponding class. We can also add some features to the Router using the features of the iOS app and objective-C: In some special cases, after opening different pages (VC), also need to transfer some commands to the VC, let it do some special operations, so you can configure the URL parameters, and then pass the parameter name and parameter value to the new VC:

[MRRouter openURL:@"scheme://test? aa=11&bb=22"];
Copy the code

More conveniently, we can pass parameters directly with dictionaries:

[MRRouter openURL:@"scheme://test3" parameters:@{@"ccc":@ "333".@"ddd":@ "444"}];
Copy the code

So you also need to create a mapping table, to establish the mapping between URL and VC, each VC increase, add a corresponding relationship in the table header. We can use the Objective-C Runtime to dynamically map class names to simplify our daily coding operations. The implementation is not described in detail here, but can be seen here.

You can also define a default openURL action:

[MRRouter sharedInstance].defaultExecutingBlock = ^(id object, NSDictionary *parameters) { 
    [self.navigationController pushViewController:object animated:YES];
};
Copy the code

In this way, when opening a new page, there is no need to import any header files or establish a mapping relationship, just call the openURL interface of the Router.

The additional benefit of managing pages through the Router based on the intermediary mode is that it can simplify the operation of opening a new page for the server push. When there is a new activity, to open a corresponding page, you only need to send the URL of the page to the client through push, and the client directly passes the URL to the Router. A lot of if/else logic is omitted.

Conclusion:

The use of the mediator pattern is not only used for VC management, it can be used to manage complex groups of objects such as “many-to-many” in functionality. Of course, before again, you should not start using the mediator pattern, but consider whether the functionality is properly designed. Although the use of Mediator mode reduces the coupling between objects and the complexity of logic between objects, this complexity is transferred to the Mediator class to a certain extent, so the function maintenance of Mediator class needs to be handled carefully. All of the code in the examples above can be downloaded here. All star/ Request/issues are welcome.