zoukankan      html  css  js  c++  java
  • iOS设计模式

    iOS设计模式 - 代理

    原理图

    说明

    1. 代理模式大家都用过,但用抽象基类NSProxy实现代理估计鲜有人用

    2. 本人用NSProxy实现了代理模式,对于理解消息转发机制有点帮助

    源码

    https://github.com/YouXianMing/iOS-Design-Patterns

    //
    //  AbstractProxy.h
    //  AppProxy
    //
    //  Created by YouXianMing on 15/8/4.
    //  Copyright (c) 2015年 YouXianMing. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface AbstractProxy : NSProxy
    
    /**
     *  被代理对象
     */
    @property (nonatomic, weak) id  customer;
    
    /**
     *  代理客户
     *
     *  @param customer 实现了某种协议的客户
     *
     *  @return 代理对象
     */
    - (instancetype)initWithCustomer:(id)customer;
    
    @end
    //
    //  AbstractProxy.m
    //  AppProxy
    //
    //  Created by YouXianMing on 15/8/4.
    //  Copyright (c) 2015年 YouXianMing. All rights reserved.
    //
    
    #import <objc/runtime.h>
    #import "AbstractProxy.h"
    #import "AbstractExcute.h"
    
    @implementation AbstractProxy
    
    - (instancetype)initWithCustomer:(id)customer {
    
        self.customer = customer;
        return self;
    }
    
    #pragma mark - NSProxy
    
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
        
        if ([self.customer respondsToSelector:aSelector]) {
            
            return [self.customer methodSignatureForSelector:aSelector];
            
        } else {
            
            AbstractExcute *excute = [AbstractExcute shareInstance];
            return [excute methodSignatureForSelector:NSSelectorFromString(@"nullExcute:")];
        }
    }
    
    - (void)forwardInvocation:(NSInvocation *)invocation {
        
        SEL selector = [invocation selector];
        if ([self.customer respondsToSelector:selector]) {
            
            [invocation setTarget:self.customer];
            [invocation invoke];
            
        } else {
        
            NSString *selectorString = NSStringFromSelector(invocation.selector);
            
            invocation.selector    = NSSelectorFromString(@"nullExcute:");
            AbstractExcute *excute = [AbstractExcute shareInstance];
            [invocation setTarget:excute];
            
            const char *className      = class_getName([self class]);
            NSArray    *classNameArray = nil;
            if (self.customer) {
                
                classNameArray = @[[NSString stringWithUTF8String:className], selectorString, @""];
                
            } else {
            
                classNameArray = @[[NSString stringWithUTF8String:className], selectorString];
            }
            
            [invocation setArgument:&classNameArray atIndex:2];
            [invocation invoke];
        }
    }
    
    @end
    //
    //  AbstractExcute.h
    //  AppProxy
    //
    //  Created by YouXianMing on 15/8/4.
    //  Copyright (c) 2015年 YouXianMing. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface AbstractExcute : NSObject
    
    + (instancetype)shareInstance;
    
    @end
    //
    //  AbstractExcute.m
    //  AppProxy
    //
    //  Created by YouXianMing on 15/8/4.
    //  Copyright (c) 2015年 YouXianMing. All rights reserved.
    //
    
    #import "AbstractExcute.h"
    
    @implementation AbstractExcute
    
    + (instancetype)shareInstance {
    
        static AbstractExcute *sharedAbstractExcute = nil;
        
        static dispatch_once_t predicate;
        dispatch_once(&predicate, ^{
            sharedAbstractExcute = [[self alloc] init];
        });
        
        return sharedAbstractExcute;
    }
    
    - (void)nullExcute:(NSArray *)className {
    
        if (className.count == 3) {
            
            NSLog(@"%@ 设置了代理,但该代理没有实现 %@ 方法", className[0], className[1]);
            
        } else {
        
            NSLog(@"%@ 没有设置代理,方法 %@ 没有执行", className[0], className[1]);
        }
        
    }
    
    @end

    细节

    NSProxy子类实现的关键所在

  • 相关阅读:
    Mybatis学习笔记(八) —— Mybatis整合spring
    Mybatis学习笔记(七) —— 关联查询
    Mybatis学习笔记(六) —— 动态sql
    Mybatis学习笔记(五) —— Mapper.xml(输入映射和输出映射)
    Mybatis学习笔记(四) —— SqlMapConfig.xml配置文件
    Mybatis学习笔记(三) —— DAO开发方法
    Mybatis学习笔记(二) —— mybatis入门程序
    Mybatis学习笔记(一) —— mybatis介绍
    tomcat的热部署配置
    int bool 字符串 列表 字典 集合
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/4703259.html
Copyright © 2011-2022 走看看