1. Design principles
  • Single responsibility principle A class is only responsible for one thing (UIView/CALayer)
  • The open closed principle is closed for modification and open for extension
  • Interface segregation principle Using multiple special agreement (UITableViewDataSource/UITableViewDelegate)
  • Dependency Inversion principle Abstraction should not depend on concrete implementation, concrete implementation can depend on abstraction (data access)
  • Richter’s substitution Principle The parent class can be seamlessly replaced by the child class without affecting the original function (KVO)
  • Demeter’s Law An object should know as little as possible about other objects, be highly cohesive and coupling less

2. Design patterns

  • Chain of Responsibility model
@class Object;
typedef void(^CompletionBlock)(Bool handled);
typedef void(^ResultBlock)(Object *handler, BOOL handled);

@interface Object: NSObject

@property (nonatomic.strong) Object *nextObject;

- (void)handle:(ResultBlock)result;
- (void)handleBusiness:(CompletionBlock)completion;

@end

@implementation Object

- (void)handle:(ResultBlock)result {
    CompletionBlcok completion = ^(BOOL handled) {
        if (handled) {
            return (self, handled);
        } else {
            if (self.nextObject) {
                [self.nextObject handle:result];
            } else {
                result(nil.NO); }}} [self handBusiness:completion];
}

- (void)handleBusiness:(CompletionBlock)completion 
{
    // Business processing
}

@end

Copy the code
  • The bridge model

A1 –> B1, B2, B3

A2 –> B1, B2, B3

A3 –> B1, B2, B3

@interface BaseObjectB: NSObject

- (void)fetchData;

@end


@implementation BaseObjectB

- (void)fetchData
{
    
}

@end
Copy the code
#importt "BaseObjectB.h"

@interface BaseObjectA: NSObject

@property(nonatomic.strong) BaseObjectB *objB;

- (void)handle;

@end

@implementation BaseObjectB

- (void)handle 
{
    [self.objB fetchData];
}

@end

Copy the code
  • Adapter mode

How does a class adapt to change

#import "AdaptedObject.h"

@interface FitObject: NSObject
@property (nonatomic.strong) AdaptedObject *adapted;
@end

@implementation FitObject

- (void)request 
{
    // adapt logic
    [self.adapted request];
    // adapt logic
}

@end
Copy the code
  • The singleton pattern
@implementation SingObject

+ (id)shareInstace 
{
    static SingleObject *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[super allocWithZone:NULL] init];
    })
    
    return instance;
}

+ (id)allocWithZone:(struct _NSZone *)zone
{
    return [self shareInstance];
}

- (id)copyWithZone:(nullable NSZone *)zone 
{
    return self;
}

@end
Copy the code
  • Command mode

Behavior parameterization reduces code coincidence

@class Command;
typedef void(^CommandCompletionCallBack)(Command *cmd)

@interface Command: NSObject
@property (nonatomic.copy) CommandCompletionCallBack completion;

- (void)execute;
- (void)cancel;
- (void)done;
@end

@implementation Command

- (void)execute 
{
    // Logical processing
    [self done];
}

- (void)cancel 
{
    self.completion = nil;
}

- (void)done
{
    dispatch_async(dispatch_get_main_queue(), ^{
        if (_completion) {
            _completion(self)}self.completion = nil;
        
        [[CommandManager shareInstance].arrayCommands removeObject: self]; })}@end

// Command manager
#import "Command.h"
@interface CommandManager: NSObject

@property (nonatomic.strong) NSMutableArray<Command *> *commandArr;

+ (instanceType)sharedInstance;

+ (void)executeCommand:(Command *)cmd completion:(CommandCompletionCallBack)completion;

+ (void)cancelCommand:(Command *)cmd;
@end

@implementation CommandManager

+ (id)shareInstace 
{
    static CommandManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[super allocWithZone:NULL] init];
    })
    
    return manager;
}

+ (id)allocWithZone:(struct _NSZone *)zone
{
    return [self shareInstance];
}

- (id)copyWithZone:(nullable NSZone *)zone 
{
    return self;
}

+ (void)executeCommand:(Command *)cmd completion:(CommandCompletionCallBack)completion
{
    if (cmd) {
        if(! [self _isExecutingCommand:cmd]) {
            [[selfsharedInstance] arrayCommands addObject:cmd]; cmd.completion = completion; [cmd execute]; }}} + (void)cancelCommand:(Command *)cmd 
{
    if (cmd) {
        [[[selfshareInstance] arrayCommands] removeObject:cmd]; [cmd cancel]; }} + (BOOL)_isExecutingCommand:(Command *)cmd
{
    if (cmd) {
        NSArray *cmds = [[self shareInstance] arrayCommands];
        for (Command *aCmd in cmds) {
            if (aCmd = cmd) {
                return yes;
            } 
        }
    }
    
    rturn NO;
}
@end
Copy the code