In iOS, the Delegate uses singleton pattern to ensure that there is only one object. Then, in the case of multiple singleton, the share pattern can be used to reduce the number of reads and writes of the object and improve the performance. NSString, NSArray and NSMutableArray are used to create abstract factory pattern. An AppDelegate uses state mode to change the state of the APP. UIView uses appearance mode to encapsulate a series of interfaces to display the view. Tableview uses proxy mode to separate view from data. There are a lot of design patterns that we use that are not very clear, so let’s take a look at common design patterns.

Design patterns

Design Pattern is a set of repeatedly used, most people know, classified, code Design experience summary. The purpose of using design patterns is to make code reusable, make it easier for others to understand, and ensure code reliability. Design patterns make code writing truly engineering; Design patterns are the cornerstone of software engineering, just like the structure of a mansion.

Design patterns can be divided into creative, structural, and behavioral patterns, represented by borrowing a diagram

Creation pattern

These design patterns provide a way to hide the creation logic while creating objects, rather than instantiating objects directly using the new operator. This gives the program more flexibility in deciding which objects to create for a given instance.

1. Simple factory mode

Simple Factory Pattern: Also known as Static Factory Method Pattern, it belongs to the class creation Pattern. In the simple factory pattern, you can return instances of different classes depending on the parameters. The simple factory pattern specifically defines a class that is responsible for creating instances of other classes, which usually have a common parent class.

In factory mode, we create objects without exposing the creation logic to the client, and by using a common interface to point to the newly created objects.

Sample Sample =new Sample(parameter);Copy the code

We usually use it like this in OC

@protocol Product <NSObject> -(void)productMethod; @interface SimpleFactory: NSObject +(id<Product>)createProduct:(NSString *)productName; @interface ProductA: NSObject<Product> @end: @interface ProductB: NSObject<Product> @end @class ProductA,ProductB; @implementation SimpleFactory + (id<Product>)createProduct:(NSString *)productName{if ([productName isEqualToString:NSStringFromClass(ProductA.class)]) {
        return [[ProductA alloc]init];
    }else if ([productName isEqualToString:NSStringFromClass(ProductB.class)]){
        return [[ProductB alloc]init];
    }else{
        return nil;
    }
}
@end
@implementation ProductA
- (void)productMethod {
    
}
@end
@implementation ProductB
- (void)productMethod {
}
@end
Copy the code

This is what it looks like when it’s used

/ / create product ProductA A * A = [SimpleFactory createProduct: NSStringFromClass (ProductA. Class)]; [a productMethod]; / / create product ProductB B * B = [SimpleFactory createProduct: NSStringFromClass (ProductB. Class)]; [b productMethod];Copy the code

The advantage is that the desired instance of a class is determined by a single parameter, regardless of how it is implemented internally. The disadvantage is that adding a new product requires changing the implementation of createProduct (NSString *)productName.

2. Factory mode

The Factory Method Pattern is also called the Factory Pattern, also called the Virtual Constructor Pattern or the Polymorphic Factory Pattern, which belongs to the class creation Pattern. Parent in factory method pattern, the factory is responsible for defining public interfaces, objects created products and factories subclass object is responsible for generating the specific products, the purpose is to delay product class instantiation operations to complete, factory subclasses by factory subclasses to determine exactly which a specific product class to instantiate.

The factory method pattern contains the following roles:

  • Product: Abstract Product
  • ProductA: Specific product
  • Factory: Abstract Factory
  • FactoryA: Concrete factory

// @protocol Factory <NSObject> + (void)createProduct:(NSString *)productName; @interface FactoryA: NSObject<Factory> +(id<Product>)createProduct:(NSString *)productName; @interface FactoryB: NSObject<Factory> +(id<Product>)createProduct:(NSString *)productName; @implementation FactoryA + (id<Product>)createProduct:(NSString *)productName{if ([productName isEqualToString:NSStringFromClass(ProductA.class)]) {
        return [[ProductA alloc]init];
    }else{
        returnnil; b@implementation FactoryB + (id<Product>)createProduct:(NSString *)productName{if ([productName isEqualToString:NSStringFromClass(ProductB.class)]){
        return [[ProductB alloc]init];
    }else{
        return nil;
    }
}
@end
Copy the code

It’s easy to use

/ / create product ProductA A * A = [FactoryA createProduct: NSStringFromClass (ProductA. Class)]; [a productMethod]; / / create product ProductB B * B = [FactoryB createProduct: NSStringFromClass (ProductB. Class)]; [b productMethod];Copy the code

The advantage is that when creating a new product, there is no need to change the old production line, but only need to add a new method. The disadvantage is that the product is a single production line, the factory inherits the protocol, which is slightly complicated, and the function degrades into a simple factory mode.

3. Abstract factory pattern

Abstract Factory Pattern: Provides an interface for creating a series of related or interdependent objects without specifying their concrete classes. The Abstract factory pattern, also known as the Kit pattern, belongs to the object creation pattern.

The abstract factory pattern contains the following roles:

  • Factory: Abstract Factory
  • FactoryA/B: Concrete factory
  • ProductA/B: abstract product
  • ProductA1/A2: Specific product
  • ProductB1/B2: specific product

@protocol ProductA <NSObject> -(void)productMethod; @end @protocol ProductB <NSObject> -(void)productMethod; @protocol Factory <NSObject> // create an instance of ProductA + (id<ProductA>)createProductA:(NSString *)ProductAName; + (id<ProductB>)createProductB:(NSString *)ProductBName; @end // Factory class A implements @Interface Factory1: NSObject<Factory> @end // Factory class B implements @Interface Factory2: @interface ProductA1: NSObject<ProductA> @end@interface ProductA2: NSObject<ProductA> @end // Implement @interface ProductB1 in.m instead of abstract method protocol: NSObject<ProductB> @end @interface ProductB2 : NSObject<ProductB> @endCopy the code

It’s easy to use, to create a factory and then produce the desired product based on that factory.

/ / A factory product ProductA1 * a1 = [Factory1 createProductA: NSStringFromClass (ProductA1. Class)]; ProductA1 *a2 =[Factory1 createProductA:NSStringFromClass(ProductA2.class)]; [a1 productMethod]; [a2 productMethod]; // Factory B produces product B //Copy the code

The advantage is that you only need to change the factory to change the production line. The disadvantage is that when you need to add a new product, you need to change all the subclasses of the factory.

The three factory patterns are linked

When only one product object is created for each concrete factory class in the abstract factory pattern, that is, only one product hierarchy exists, the abstract factory pattern degenerates into the factory method pattern. The factory method pattern degenerates into a simple factory pattern when abstract factories are merged with concrete factories in the factory method pattern, providing a unified factory to create product objects, and designing the factory method for creating objects as a static method.

A simple factory has a static method to produce a product, a factory mode in which the factory method is abstracted to produce a product, and an abstract factory in which the factory abstract method produces multiple products.

4. Builder mode

Builder Pattern: Separates the construction of a complex object from its representation so that the same construction process can create different representations.

The Builder pattern, which creates a complex object step by step, allows users to build complex objects simply by specifying their type and content, without needing to know the specific build details inside. The Builder pattern belongs to the object creation pattern. Depending on the Chinese translation, builder mode can also be called generator mode.

The Builder mode contains the following characters:

  • -Blair: You’re an abstract Builder
  • -Serena: ConcreteBuilder
  • The Director
  • Product: Product role

code

@protocol Builder <NSObject> @optional - (void)buildPartA; - (void)buildPartB; - (void)buildPartC; - (instancetype)getResult; @end @interface BuilderA : NSObject<Builder> - (void)buildPartA; @end @interface BuilderB : NSObject<Builder> - (void)buildPartB; @end @interface Builder : NSObject - (id)constuct; // process - (void)setBuilder:(id<Builder>)bd; @implementation BuilderA - (void)buildPartA{printf("build A");
}
-(instancetype)getResult
{
	return self;
}
@end
@implementation BuilderB

- (void)buildPartB{
	printf("build B");
}
-(instancetype)getResult
{
	return self;
}
@end


@interface Builder() { id<Builder> _bd; } @implementation Builder - (id)constuct{_bd buildPartA]; [_bd buildPartB]; [_bd buildPartC]; // Assemble the productreturn [_bd getResult];
}
- (void)setBuilder:(id<Builder>)bd{
	_bd = bd;
}
@end
Copy the code

The advantage is that customers do not know the specific production steps, and the production steps and process are decoupled. The same steps (with subclasses to achieve different processes) can produce different products, which is easy to expand and only need (subclasses) to achieve each step. The disadvantage is that steps can be abstracted only when there are many similarities between multiple products.

5. Singleton mode

Singleton Pattern: The Singleton Pattern ensures that a class has only one instance and that it instantiates and provides that instance to the entire system. This class is called a Singleton class, which provides globally accessible methods.

The singleton pattern has three main points: first, there can be only one instance of a class; Second, it must create the instance itself; Third, it must provide this instance to the entire system itself. The singleton pattern is an object creation pattern. Singleton is also called singleton or singleton.

The singleton pattern contains the following roles:

  • Singleton: Singleton

code

@interface Singleton : NSObject
+ (instancetype)getInstace;
@end

@implementation Singleton
+ (instancetype)getInstace{
	static dispatch_once_t onceToken;
	static Singleton *_t;
	dispatch_once(&onceToken, ^{
		_t = [Singleton new];
	});
	return _t;
}
@end

Copy the code

It’s also easy to use

Singleton  *ton=[Singleton getInstace];
//next code
Copy the code

Advantages The class is instantiated only once in memory, eliminating frequent create and destroy steps and improving performance. The disadvantage is that the singleton pattern has no abstraction layer and is difficult to extend.

Structural mode

Structural patterns describe how to combine classes or pairs together to form larger structures. Just like building blocks, complex and more powerful structures can be formed by combining simple blocks.

Structural patterns contain patterns

  • Adapter mode (Adapter)
  • Bridge mode (Bridge)
  • Decorator pattern
  • Facade Pattern
  • Flyweight Mode
  • Proxy mode

6. Adapter mode

Adapter Pattern: Transforms one interface into another interface that the customer wants. The Adapter Pattern enables classes with incompatible interfaces to work together. Its alias is wrappers. The adapter pattern can be used as either a class schema or an object schema.

The adapter pattern contains the following roles:

  • Target: Target abstract class
  • Adapter: Adapter class
  • Adaptee: the Adaptee class
  • Client: indicates the Client class

code

@interface Adaptee : NSObject
- (void)specificRequest;
@end

@interface Adapter : NSObject
@property (nonatomic,strong) Adaptee *adaptee;

+ (instancetype)initWithAdaptee:(Adaptee *)obj;
- (void)request;
@end


@implementation Adaptee

- (void)specificRequest{
    NSLog(@"Adapter third party worker is working.");
}

@end
@implementation Adapter

+ (instancetype)initWithAdaptee:(Adaptee *)obj{
    Adapter *adapter=[Adapter new];
    adapter.adaptee = obj;
    returnadapter; } request{[self.adaptee specificRequest]; } @endCopy the code

The advantage is that the third party can serve the customer after processing, while the disadvantage is that it does not support multiple inheritance. Only one can be adapted at a time.

7. Bridge mode

Bridge Pattern: Separate the abstract part from its implementation part so that they can all change independently. It is an object structure pattern, also known as Handle and Body pattern or Interface pattern.

The bridge mode contains the following roles:

  • Abstraction: Abstract class
  • RefinedAbstraction: Expanded abstract class
  • Implementor: Implements the class interface
  • ConcreteImplementor: Concrete implementation class

The advantage is to abstract Implementor, implement it in a subclass of Implementor, and reduce the coupling. The disadvantage is that the introduction of bridge mode will increase the difficulty of understanding and designing the system. Since the aggregation association relationship is established at the abstraction layer, developers are required to design and program for abstraction.

8. Decoration mode

Decorator Pattern: Dynamically assigning additional responsibilities to an object is more flexible in terms of adding functionality to the object than generating subclass implementations. It can also be called a Wrapper, the same alias as the adapter pattern, but they are suitable for different situations. Depending on the translation, decoration pattern is also called “painter pattern”, which is an object structure pattern. Decoration mode contains the following roles:

  • Component: Abstract Component
  • ConcreteComponent: ConcreteComponent
  • Decorator: Abstract Decorator class
  • ConcreteDecorator: ConcreteDecorator class

code

@protocol ComponentProtocol <NSObject> - (void)opertion; @interface ComponentA: NSObject<ComponentProtocol> @interface ComponentB: NSObject<ComponentProtocol> @end //ComponentA: ComponentA(add) - (void)addMethod; @implementation ComponentA - (void)opertion{NSLog(@)"ComponentA opertion ");
}
@end

@implementation ComponentB
- (void)opertion{
    NSLog(@"ComponentB opertion "); } @implementation Component(add) - (void)addMethod{NSLog(@)"addMethod");
}
@end
Copy the code

Advantages Dynamic adding functions (categories in iOS), disadvantages are that when classes change (multiple categories), it is difficult to check errors.

9. Appearance mode

Facade Pattern: External communication with a subsystem must be through a unified Facade object that provides a consistent interface for a set of interfaces in the subsystem. The Facade Pattern defines a high-level interface that makes the subsystem easier to use. Appearance pattern, also known as facade pattern, is an object structure pattern.

The appearance mode contains the following roles:

  • Facade: Facade role
  • SubSystem: SubSystem role

@interface SystemA: NSObject - (void)run; @interface SystemB: NSObject - (void)eat; @interface SystemC: NSObject - (void)play; @end // @interface Facade: NSObject @property (nonatomic,strong) SystemA *a; @property (nonatomic,strong) SystemB *b; @property (nonatomic,strong) SystemC *c; @endCopy the code

Advantages reduce the user and subsystem coupling, and can access the subsystem through the appearance, the subsystem portability is strong, the disadvantage is that the appearance is not abstracted, change the subsystem must change the appearance class.

10. Enjoy yuan mode

Flyweight Pattern: the use of sharing technology effectively supports the reuse of a large number of fine-grained objects. The system only uses a small number of objects, and these objects are very similar, the state change is very small, can realize the object multiple reuse. Because the share mode requires that the objects that can be shared must be fine grained objects, it is also called lightweight mode, which is an object structure mode.

The share mode contains the following roles:

  • Flyweight: Abstract enjoy metaclass
  • ConcreteFlyweight: Concrete enjoy metaclass
  • UnsharedConcreteFlyweight: unshared specific metaclass
  • FlyweightFactory: Enjoy the meta factory class

@interface FYFly : NSObject
@property (nonatomic,strong) NSMutableDictionary  * dic;

@end

@protocol FlyweightProtocol <NSObject>

- (void)play;
@end

@interface FlyweightA : NSObject<FlyweightProtocol>
- (void)eat;
@end
@interface FlyweightB : NSObject<FlyweightProtocol>
- (void)run;
@end

@implementation FlyweightA

- (void)play{
	NSLog(@"I'm playing.");
}
- (void)eat{
	NSLog(@"I'm eating.");
}
@end

@implementation FlyweightB

- (void)play{
	NSLog(@"I'm playing.");
}
- (void)run{
	NSLog(@"I'm running.");
}
@end
Copy the code

Advantages Using this mode for multiple objects with high reuse rate can improve efficiency, while disadvantages make the system more complex.

11. Proxy mode

Proxy mode is relatively simple, the system’s tableView is the use of proxy implementation.

Behavioral pattern

Behavioral patterns are abstractions that divide responsibilities and algorithms among different objects. Behavioral patterns focus not only on the structure of classes and objects, but also on their interactions. Behavioral patterns allow for a clearer division of the responsibilities of classes and objects, and for studying the interaction between instance objects at run time. When the system is running, objects are not isolated, they can communicate with each other and cooperate to complete some complex functions. One object will also affect the operation of other objects when it is running.

Behavioral pattern can be divided into class behavior pattern and object behavior pattern:

  • Class behavior pattern: The behavior pattern of a class uses inheritance relationships to distribute behavior among several classes. Class behavior pattern mainly distributes responsibilities of parent and subclass by means of polymorphism.

  • Object behavior pattern: The object behavior pattern uses the aggregate association of objects to assign behaviors. The object behavior pattern mainly assigns responsibilities of two or more classes through object association. According to the principle of composite reuse, association relation should be used to replace inheritance relation, so most behavior design pattern belongs to object behavior design pattern.

Contains the schema

  • Chain of Responsibility model
  • Command mode
  • Interpreter mode
  • Iterator pattern (Iterator)
  • Mediator Mode
  • Memento Mode
  • Observer Model
  • State mode
  • Strategy Pattern
  • Template Method
  • Visitor Pattern

Let’s pick a few important exercises

12 Command Mode

Command Pattern: Encapsulating a request as an object, which allows us to parameterize customers with different requests; Queue or log requests, and support undoable operations. Command mode is an object behavior mode, alias for Action mode or Transaction mode.

The command mode contains the following roles:

  • Command: Abstract Command class
  • ConcreteCommand: ConcreteCommand class
  • Invoker: the caller
  • Receiver: the Receiver
  • Client: the customer class

code

@interface Order : NSObject
- (void)exe;
@end

@protocol CommandProtocol <NSObject>

- (void)play;

@end

@interface Order1 : NSObject<CommandProtocol>

@end
@interface Order2 : NSObject<CommandProtocol>

@end
@interface Order3 : NSObject<CommandProtocol>

@end


@implementation Order
- (void)exe{
	[[Order1 new] play];
}
@end
@implementation Order1

- (void)play {
	NSLog(@"Enter the park.");
	[[Order2 new] play];
}

@end
@implementation Order2

- (void)play {
	NSLog(@"Start playing ball");
	[[Order3 new] play];
}

@end
@implementation Order3
- (void)play{
	NSLog(@"Start playing badminton");
}
@end

Copy the code

Advantages of low coupling between classes, disadvantages of a single command will cause too many entity classes.

13. The Mediator model

Definition of Mediator Pattern: encapsulating a series of object interactions with a Mediator object, the Mediator makes the objects loose coupling without explicitly referring to each other, and can independently change their interactions. The mediator pattern, also known as the mediator pattern, is an object behavior pattern.

The mediator pattern contains the following roles:

  • Most mediators are abstract
  • -Serena: ConcreteMediator
  • Colleague: An abstract Colleague
  • ConcreteColleague: ConcreteColleague class

@interface Meditor : NSObject

- (void)registerObj:(NSString *)key;

- (void)sendMsg:(NSString *)key msg:(NSString *)msg;
@end

@protocol ColleagueProtocol <NSObject>

- (void)sendmsg:(NSString *)msg;

@end

@interface ColleagueA : NSObject<ColleagueProtocol>

@end
@interface ColleagueB : NSObject<ColleagueProtocol>

@end


@interface Meditor(){
	NSMutableDictionary *_dic;
}
@end

@implementation Meditor
- (void)registerObj:(NSString *)key id:(id<ColleagueProtocol>)obj{
	if (_dic ==nil) {
		_dic=[NSMutableDictionary dictionary];
	}
	[_dic setObject:key forKey:obj];
}
- (void)sendMsg:(NSString *)key msg:(NSString *)msg{
	id <ColleagueProtocol> obj = _dic[key];
	[obj sendmsg:msg];
}
@end

@implementation ColleagueA

- (void)sendmsg:(NSString *)msg{
	NSLog(@"ColleagueA send %@",msg);
}

@end
@implementation ColleagueB

- (void)sendmsg:(NSString *)msg{
	NSLog(@"ColleagueB send %@",msg);
}

@end
Copy the code

Advantages simplify interactions between pairs and reduce coupling, while disadvantages can lead to terminator complexity.

14 Observer Mode

Observer Pattern: Defines a one-to-many dependency between objects so that whenever an object’s state changes, its dependent objects are notified and automatically updated. The observer pattern is also called Publish/Subscribe, Model/View, Source/Listener or Dependents.

The observer pattern is an object behavior pattern.

The Observer mode contains the following roles:

  • Subject: the target
  • ConcreteSubject: Concrete target
  • The Observer: the Observer
  • ConcreteObserver: ConcreteObserver

@interface ViewController ()
@property (nonnull,nonatomic,assign) int age;
@end

@implementation ViewController

- (void)viewDidLoad {
	[super viewDidLoad];
	// Do any additional setup after loading the view.
	[self addObserver:self forKeyPath:@"age"
			  options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld
			  context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
	NSLog(@"% @",change);
}

@end
Copy the code

The advantage is that the changes of objects can be monitored in real time, while the disadvantage is that too many subscribers will cause poor performance. Observers only know the results of changes, not how they change.

15 Status Mode

State Pattern: Allows an object to change its behavior when its internal State changes. The object appears to have modified its class. The alias is Objects for States, and state mode is an object behavior mode.

The state mode contains the following roles:

  • Context: environmental class
  • State: Abstract State class
  • ConcreteState: ConcreteState class

typedef enum : NSUInteger {
	StateClose = 0,
	StateOpen = 1,
} State;
@interface StateClass : NSObject

@property (nonatomic,assign) State s;
@end
@implementation StateClass
- (void)setS:(State)s{
	switch (s) {
		case StateOpen:
		{
			NSLog(@"Aircraft has been activated.");
		}
			break;
		case StateClose:
		{
			NSLog(@"The plane has landed.");
		}
			break;
			
		default:
			break;
	}
}
@end
Copy the code

The advantage is the use of state control class behavior, the disadvantage is that the new state needs to modify the source code corresponding to the state class.

16 Policy Mode

Strategy Pattern: Define a series of algorithms, encapsulate each algorithm, and make them interchangeable. A Policy pattern, also known as a Policy pattern, allows an algorithm to change independently of the customers that use it.

The policy mode contains the following roles:

  • Context: environmental class
  • Strategy: Abstract policy class
  • ConcreteStrategy: ConcreteStrategy class

@interface Strategy : NSObject
- (void)handle;
@end
@interface StrategyA : NSObject
- (void)handle;
@end
@interface StrategyB : NSObject
- (void)handle;
@end

@interface Context : NSObject
@property (nonatomic,strong) Strategy *obj;
- (void)opertion;
@end

@implementation Context
- (void)opertion{
	[self.obj handle];
}
@end
@implementation Strategy
- (void)handle{}
@end
@implementation StrategyA

- (void)handle{
	NSLog(@"Old three counts.");
}

@end
@implementation StrategyB

- (void)handle{
	NSLog(@"Old four counts.");
}

@end
Copy the code

The advantage is that the algorithm can be flexibly added, but the disadvantage is that the customer must know the algorithm of the policy so as to know which algorithm to use. The policy will generate multiple objects, and you can use the share mode for object management.

The code includes the class diagram and the source file download

The resources

  • Design patterns
  • Design patterns
  • Java Design Pattern [Tsinghua Press]

AD time