First, what is a proxy mode
- definition
Providing a proxy to control access to the object to other objects. Proxy design pattern English name is Proxy pattern, and our common delegate (delegate) does not matter.
-
Proxy pattern composed of
abstract roles: the role of real business methods implemented through an interface or abstract class declaration.
Acting roles: to achieve abstract role, the role of agents is real, abstract methods to achieve real business logic methods by role, and can attach their own operations.
Real Role: Implement the abstract roles, define business logic real role to be achieved, calls for acting role. Baidu Encyclopedia - Use scene
in iOS, we usually use a proxy to do message passing, as we often used to develop iOS UITableView it is to use a proxy to create a cell, click on a series of operations cell, etc.
Second, the pattern configuration diagram of the proxy (forwarding message broker implementation formula)
Implementation steps :
- Create an abstract proxy class ( AbstractProxy ), and a mechanism for forwarding agents are reserved to define the message Customer.
- Create a proxy class inherits from the abstract (AbstractProxy) subclass (ConcreteProxy), mainly used for message forwarding agent.
Structure diagram :
Third, code implementation
- Message forwarding class
- AbstractProxy.h
AbstractProxy @interface: NSProxy / * * * is a proxy object * / the @Property (nonatomic, weak) the above mentioned id the Customer; / * * * @breif proxy client * @param customer to achieve the customer some kind of agreement * @return proxy object * / - (instanceType) initWithCustomer: (the above mentioned id) the Customer; @end
- AbstractProxy.m
#import <objc/runtime.h> #import "AbstractProxy.h" #import "AbstractExcute.h" @implementation AbstractProxy - (instancetype)initWithCustomer:(id)customer { self.customer = customer; return self; } - (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
- AbstractProxy.h
- The broker
- ConcreteProxy.h
#import "AbstractProxy.h" #import "MessageProtocol.h" NS_ASSUME_NONNULL_BEGIN @interface ConcreteProxy : AbstractProxy<MessageProtocol> @end NS_ASSUME_NONNULL_END
- ConcreteProxy.m
#import "ConcreteProxy.h" @implementation ConcreteProxy @end
- ConcreteProxy.h
- An exception handler
- AbstractExcute.h
#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface AbstractExcute : NSObject + (instancetype)shareInstance; @end NS_ASSUME_NONNULL_END
- AbstractExcute.m
#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 ]); } the else { NSLog ( @ " % @ proxy is not set, the method not implemented% @ " , className [ 0 ], className [ . 1 ]); } } @end
- AbstractExcute.h
- An exception handler
- ViewController.h
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @end
- ViewController.m
#import "ViewController.h" #import "MessageProtocol.h" #import "ConcreteProxy.h" @interface ViewController ()<MessageProtocol> @property(nonatomic,strong) ConcreteProxy *proxy; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.proxy = [[ConcreteProxy alloc]initWithCustomer:self]; [self.proxy helloWorld]; [self.proxy goodByte]; } - (void)helloWorld { NSLog(@"helloWorld"); } - (void)goodByte { NSLog(@"goodByte"); } @end
- ViewController.h
Fourth, the advantages and disadvantages
- Advantages :
1, clear responsibilities: is the real role do not need to know the details of the agent, as long as know the result, that is to say, I do not know how the intermediary match for me listings, these processes need to match only agency to do I just know what I can for the listing.
2, a high scalability
3, between us and the real proxy object and target objects only play the role of intermediary.
4, decoupling, the proxy class and the agency made a direct need to know what each other
- Drawback : the agent is one to one, it requires an agreement between the commission and the agency.
V. Code Example
proxy mode