iOS 开发中的 Self-Manager 模式

2016-03-26  本文已影响0人  L4H

给某个视图更大的权力,让它自己负责处理自己的事件

有一个例子:负责展示头像的视图

它的职责包括:

代码是这样的:

@interface FDAvatarView : UIView
// 假设 VIPInfo 是某个 Entity
- (void)configureWithAvatarURL:(NSURL *)URL VIPInfo:(id)info tapped:(void (^)(void))block;
@end

使用这个控件的人只要调用该方法传入参数就ok。但此时会有个问题:

为解决这个问题,就需要给这个 View 放权,让其自己 Handle 自己的事件,也就是 Self-Managed,为了不破坏 View 的纯洁性,比较好的实践是在 Category 中实现:

@interface FDAvatarView (FDAvatarViewSelfManager)
- (void)selfManagedConfigureWithAvatarURL:(NSURL *)URL VIPInfo:(id)info uid:(NSString *)uid;
@end

实现:

@implementation FDAvatarView (FDAvatarViewSelfManager)
// 为后一个页面的创建增加了个 UID 参数
- (void)selfManagedConfigureWithAvatarURL:(NSURL *)URL VIPInfo:(id)info UID:(NSString *)UID {
    [self configureWithAvatarURL:URL VIPInfo:info tapped:^{
        // 假设 App 结构是 Root -> TabBar -> Navigation -> ViewController
        UITabBarController *tabBarControler = (id)[UIApplication.sharedApplication.delegate.window.rootViewController;
        UINavigationController *navigationController = tabBarControler.selectedViewController;
        // 创建用户信息 View Controller
        FDUserProfileViewController *profileViewController = [FDUserProfileViewController viewControllerWithUID:UID];
        [navigationController pushViewController:profileViewController animated:YES];
    }];
}
@end

这里用到了类似 AOP(面向对象) 的思路,添加了对 App 层级的耦合(调用者只要调用了该方法就会直接跳转到用户界面),如果觉得这样的耦合方式不妥的话,也可以封装个全局方法去取到当前顶层的 Navigation Controller
这样,FDAvatarView 的调用者只需要配置入参,其余的它自己全能搞定了,即使 App 内很多处出现头像,逻辑代码也只有一份。

接下来再看一个例子:


这个点赞的按钮功能上有几个职责:

显示已有的点赞数
点击按钮后执行一个小动画,点赞数 +1,同时发送网络请求。
若已经点赞,点击执行反向操作
若网络请求发送失败,则回退成点击前的状态

这个控件的 代码 可以设计成这样:

@interface FDLikeButton : UIButton
- (void)configureLikeStatus:(BOOL)likeOrNot count:(NSInteger)count animated:(BOOL)animated;
@end

因为继承自 UIButton,所以外部可以直接设置其 action,就不增加 tappedHandler 的参数了。外部直接在点击事件中需要调用这个配置方法,播放点赞动画,紧接着发送一个网络请求,若网络请求失败,可以再次调用这个 API 的无动画版本回滚状态。

有个问题,像上面的例子一样,网络请求事件处理逻辑相同,但代码却分部在各个页面中,于是给这个 View 增加 Self-Managed 模式的 Category

@interface FDLikeButton (FDLikeButtonSelfManager)
- (void)selfManagedConfigureWithLikeStatus:(BOOL)likeOrNot count:(NSInteger)count;
@end
@implementation FDLikeButton (FDLikeButtonSelfManager)
- (void)selfManagedConfigureWithLikeStatus:(BOOL)likeOrNot count:(NSInteger)count {
    [self configureLikeStatus:likeOrNot count:count animated:NO];
    [self addTarget:self action:@selector(likeButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)likeButtonTapped:(id)sender {
    // +1 or -1 with animation
    // Network request ^(NSError *error) {
    //     if (error) {
    //         rollback
    //     }
    // }
}
@end

设计上,Self-Manager 模式并没有破坏原有的 MVC 结构,上面两个例子中的 View 依然可以不耦合具体业务逻辑的单拿出来用。使用 Category 的方式把应该写在 ViewController 中的代码移动到 View 的文件中,让功能更加的内聚

程序的复杂度并不会因哪种酷炫的设计模式所减少,能做到的只是对复杂度的切分控制,即:

来源于 http://blog.sunnyxx.com/ 博客。

上一篇下一篇

猜你喜欢

热点阅读