1. Six design principles for objects

  • Single responsibility: A class does only one type of responsibility, and when that class is responsible for other types of responsibility, it needs to be broken down. In real development, however, this principle is least likely to be followed, because everyone has a different idea of what functions of a class count as the same type of responsibility. (Network request class)

  • Open Closed principle: Software entities should be extensible, not modifiable. That is, when you write a class and add functionality, you don’t modify the original class, you extend it. There are several design patterns that can meet this requirement. (Inheritance, classification, etc.)

  • Richter’s substitution principle: Instances of A subclass have an IS-A relationship only if they should be able to replace instances of any of their superclasses. That is, where an interface or superclass occurs, the class or subclass that implements the interface can be substituted, depending on polymorphism and inheritance. (Subclass objects can replace superclass objects, and the program execution remains the same.)

  • Demeter’s Law (least know principle) : an object should touch as few objects as possible, that is, only those objects that really need to be touched.

  • Interface separation principle: users should not be forced to rely on interfaces they do not use. In other words, it is better to have multiple specialized interfaces than a single master interface. Instead of providing a single large interface that includes all functionality, break up the interfaces based on functionality and reduce dependencies (such as UITableViewDelegate and UITableViewDataSource).

  • Dependency inversion principle: high-level modules should not depend on low-level modules, but both should depend on abstractions; Abstraction should not depend on details, details should depend on abstractions. (Relying on abstractions, such as signing agreements)

2. What are design patterns? In software development, a proven solution to a particular problem that is repeated in a particular environment.

  • Software development: There are patterns that can be applied to every industry, and by design patterns I mean software development
  • Proven: A design pattern is one that has been agreed upon and proven, not one that everyone summarizes
  • Context-specific: A design pattern can only be used in a specific environment, because different environments have different solutions to the same problem, so you can’t talk about using a design pattern in isolation from the environment
  • Repetition: It is necessary to summarize experience and form a fixed solution only when problems occur repeatedly. It is not necessary to start from scratch to find a solution when such problems occur again, but to apply it directly.
  • Specific problems: There are no silver bullets in software development, so don’t expect one design pattern to be a cure-all. Each pattern is just a solution to a particular problem, so don’t be superstitious about design patterns and abuse them.

3. There are 23 common design patterns, and models can be divided into three categories based on purpose: creative, structural, and behavioral

  • Creative design pattern: The creative pattern is related to the creation of objects
  • Structural design patterns: Structural patterns deal with combinations of classes and objects
  • Behavioral design patterns: Behavioral design patterns describe how classes or objects interact and how responsibilities are assigned

4. Create a type

  • Abstract Factory Abstract Factory pattern

    • Simple Factory Model (Simple Factory Pattern) : Define a class (factory class) that is responsible for creating instances of other classes. Instances of different classes can be returned based on the arguments of the creation method, and the created instances usually have a common parent class. (In summary, this is basically putting a bunch of if-else judgments from the business layer into the factory class.)
    - (PhoneFactory *)sellPhone:(NSString *)type{
         if ([type isEqualToString:@"IPhone"]) {
        IPhone *phone = [IPhone new];
         [phone sellPhone];
       return phone;
      }else if ([type isEqualToString:@"MIPhone"]){
     MIPhone *phone = [MIPhone new];
    [phone sellPhone];
     return phone;
     }else if ([type isEqualToString:@"HWPone"]){
     HWPhone *phone = [HWPhone new];
    [phone sellPhone];
    return phone;
    }
    return nil;
     }
    Copy the code
    Void sellPhone{NSLog(@" sell iPhone "); void sellPhone (@" sell iPhone "); } // sellPhone - (void)sellPhone{NSLog(@" sell "); } // Huawei mobile phone - (void)sellPhone{NSLog(@" sell Huawei mobile phone "); } // call PhoneFactory *faceory = [PhoneFactory new]; [faceory sellPhone:@"IPhone"];Copy the code
    • Factory Method Pattern (Factory Method Pattern) is also called Factory Pattern. The Factory parent class is responsible for defining the common interface for creating product objects, while the Factory subclass is responsible for generating specific product objects. That is, different Factory subclasses are used to create different product objects. (Abstract factory-concrete factory-concrete product, one more layer of inheritance than simple factory)

      The factory method pattern applies in a similar way to a simple factory, where objects are created with similar data and behavior. But unlike a simple factory: in the factory method pattern, because the responsibility for creating objects is transferred to a subclass of the abstract factory, the client needs to know the factory subclass for the product it needs, not the parameters in the simple factory

    • Abstract Factory Pattern: Provides an interface for creating a series of related or interdependent objects without specifying their concrete classes. (At the top level, the @Protocol interface creates an abstract factory, at the same level as the factory pattern.)

      Sometimes we need a factory that can provide multiple product objects instead of a single product object. For example, if there is more than one product family in the system and only one product family is used at a time, the products belonging to the same product family will be used together

    • A comparison of the three modes

      • Abstract factory pattern and Factory Pattern The factory pattern focuses on the creation of individual products, while the abstract factory focuses on the creation of a family of products. If the product series has only one product, then the abstract factory reverts to factory mode. Factory methods are used in abstract factories to provide concrete implementations, when they are used in conjunction.
      • The factory pattern and the simple factory are both very similar in that they are implemented for selection. The difference is that the simple factory makes the choice implementation itself. The factory pattern delays implementation to subclasses. If you implement the selection of factory methods directly in the parent class, then you are reduced to a simple factory pattern.
      • Simple and Abstract Factories Simple factories are used to make choice implementations, with no dependencies between the implementations of each product. The abstract factory implements a family of products that are related to each other. That’s the difference between them
  • Builder Pattern: Also known as generator Pattern, it separates the construction of a complex object from its representation so that the same construction process can create different representations. (applicable to complex object creation, simply do not use, such as SDWebImage SDWebImageDownloader and SDWebImageDownloaderOperation is the relationship between the director and the builder. The former is not responsible for the specific download operation, only responsible for the management of builder, Builder is responsible for the specific download of pictures.

The Builder pattern contains four members:

- ConcreteBuilder: A generator interface that defines the operation of the parts needed to create a Product object. Specific generator implementation, realization of the creation of various parts, and responsible for the assembly of the various parts of the Product object, but also provides a method for users to obtain the assembly of the Product object - Director: Primarily used to build the required Product objects in a unified process using the Builder interface - Product roles: represent complex objects built by generators, containing multiple partsCopy the code
Protocol DesignProtocol {// Func DesignDrawings()} protocol ConstructionProtocol {// Construction team Construction() } protocol BuilderProtocol {/ / return to construct object func build () - > Self} class Design: DesignProtocol, BuilderProtocol {func DesignDrawings() {print(" Design drawings ")} func build() -> Self {return Self}} class A_Design:Design {override func DesignDrawings() {override func DesignDrawings() {override func DesignDrawings() {override func DesignDrawings()}} Class c_drawings :Design {override func DesignDrawings() {print(" drawings are made of grass ")}} Class drawings: ConstructionProtocol, BuilderProtocol {func Construction () {print (" Construction ")} func build () - > Self {return Self}} to the class A_Construction: Construction {override func Construction () {print (" a-class Construction group ")}} class B_Construction: Construction { Override func Construction () {print (" class B Construction group ")}} class C_Construction: Construction {override func Construction () { Print ("C grade Builder ")}} Class Builder {var design: design? var construction:Construction? func buildAllParts(){ design = design? .build() construction = construction? .build() design? .DesignDrawings() construction? Construct () print(" build ")}} let build = Builder() build.design = A_Design() build.construction = B_Construction() build.buildAllParts()Copy the code
  • Prototype Pattern: Use a Prototype instance to specify the type of the object to be created, and create new objects by copying the Prototype. (Copy, after all)

    IOS already provides a protocol nscoping & Nsmutablecopying, we just need to implement nscoping & Nsmutablecopying

  • Singleton Pattern: The Singleton Pattern ensures that there is only one instance of a class and provides a full access point to it.

    When this pattern is applied, the singleton class must ensure that only one instance exists. Many times the whole system only needs to have one global object, which helps us coordinate the behavior of the whole system. For example, in APP development, we may need to use user information everywhere, so the user information can be stored in a file when logging in, and the configuration data can be read by a singleton object, and then other objects in the server process can obtain the configuration information through this singleton object. This approach simplifies configuration management in complex environments

5. Structured

  • Adapter Pattern: The transformation of one interface into another interface desired by the customer so that classes that would otherwise not work together due to interface incompatibilities can work together. The adapter pattern, alias Wrapper pattern, is a structural design pattern. (Model then uses proxy to separate out a class control data, decouple the association between View and Model, the advantage is decoupled, so that the View class is decoupled from the data class, so that the View class is more independent. There is no need to modify the view class when adding a new data class. The disadvantage is that many classes are added, which is troublesome.

    Definition interpretation: Adapter patterns are divided into object adapters and class adapters.

    • Object adapter: forwards requests to the adaptor in a composite manner.
    • Class adapter: The target method calls are transferred to the method that calls the adaptor by the adapter class multiple inheriting the target interface and the adaptor.

  • Bridge Pattern (Simple Factory Pattern) : Separate the abstract part from its implementation part so that they can all change independently.

    • Abstraction class: The Abstraction class maintains a reference to the object of an implementation part and declares the interface that calls the object of the implementation part.

    • RefinedAbstraction: Extend the abstract class that defines methods relevant to the real business.

    • Implementor: An implementation class interface defines the interface that is part of the implementation.

    • ConcreteImplementor Is an object that implements the interface of an implementation class

    Suppose you want to realize the function of sending prompt messages to customers, the message types can be divided into: ordinary message, urgent message, special urgent message and so on, and each message is generally sent in the system push, SMS, email and so on

    • An abstract class is an abstract class for a message
    • Extension abstract classes are subclasses that inherit message abstract classes: messages
    • The implementation interface is the send mode interface
    • The specific implementation class is the inheritance of the sending method class: system push, mobile phone SMS, email

Code implementation

// Message type abstract class #import <Foundation/ foundation.h > #import "messageImplement. H "NS_ASSUME_NONNULL_BEGIN @interface abstractMessage : NSObject @property(strong,nonatomic)id<messageImplement> messageIm; // initialize - (instancetype)initWithImplement:(id<messageImplement>)implement; - (void)send:(NSString*)message; @end NS_ASSUME_NONNULL_END ------------------------------------ @implementation abstractMessage - (instancetype)initWithImplement:(id<messageImplement>)implement { self = [super init]; if (self) { self.messageIm = implement; } return self; #import "abstractmessage.h" @interface commonMessage: AbstractMessage @end ----------------- #import "commonmessage. h" @implementation commonMessage (void)send:(NSString*)message{NSString* MSG = [NSString stringWithFormat:@" ordinary message: %@",message]; [self.messageIm sendMessage:msg]; } @end // message sending interface #import <Foundation/ foundation.h > @protocol messageImplement <NSObject> -(void)sendMessage:(NSString) *)message; #import "messageImplement. H "@interface messageEmail: NSObject<messageImplement> @end ------------------------ #import "messageEmail.h" @implementation messageEmail -(void)sendMessage:(NSString *)message{NSLog(@" sendMessage by Email, message content: %@", message); } @end // call messageEmail *email = [messageEmail new]; abstractMessage *msg = [[commonMessage alloc]initWithImplement:email]; [MSG send: @bridge mode test];Copy the code
  • Composition pattern combines objects into a tree structure to represent the “partition-whole” hierarchical composition pattern makes the use of single objects and composite objects consistent. In the Cocoa Touch framework, UIView is organized into a composite structure. Each INSTANCE of UIView can contain other instances of UIView, forming a unified tree structure. Let clients treat a single UIView object and a combination of UIViews identically.

Component: An abstract role that provides a unified interface for objects to be composed. Leaf: Represents a child node object in a combination. A Leaf node cannot have child nodes. Composite: Defines the dotted behavior that stores parts and implements operations in the Component interface, such as Add and Remove.Copy the code
  • Decorator pattern(DecoratorDecorator mode is more flexible than subclassing in terms of adding functionality to an object dynamically (in fact, iOS already provides us with a decorator mode method:Category)

Abstract Components: Abstract components define an object (interface) to which you can dynamically add responsibilities Concrete Components: Concrete components are instances of abstract components. Decorators: The Decorator class also inherits from the abstract component. It holds an instance of the concrete component object and implements an interface consistent with the abstract component interface. Concrete Decorator: Concrete Decorator is responsible for adding additional responsibilities to a Concrete build object instance.Copy the code
  • The appearance model(Facade Pattern) : The facade pattern defines a high-level interface that provides a unified interface for a set of interfaces in a subsystem. Appearance mode, also known as facade mode, is a structural design mode. (In short, build a unified interface to integrate and reduce dependencies, such asAFNetworkingforNSURLSessionTo provide a unified interface using the appearance pattern.

  • Flyweight Pattern: use sharing technology to reuse a large number of fine-grained objects, reduce the occupation of program memory, improve the performance of the program. This is mainly used when there are a large number of duplicate objects (the INTERNAL API of UIImage is already cached, and the internal implementation of the share mode is implemented).

  • The proxy pattern

    • Remote Proxy: Provides a local Proxy object for an object that resides in a different address space, either on the same host or on another host. Remote Proxy is also called Ambassador.

    • Virtual Proxy: If you want to create an object that consumes a lot of resources, you need to create an object that consumes a lot of resources to represent it. A real object can be created only when necessary. (Virtual proxy is mainly used to do lazy loading, a TableView list needs to download a lot of pictures from the network to display, if you wait until all downloaded and then display, the user experience will be very bad. An alternative is to display a placeholder map when it is first loaded, and then replace it with a real image when the background thread has finished downloading the image. This is lazy loading.)

    • Protect Proxy: Controls access to an object and provides different levels of access for different users.

    • Cache Proxy: Provides temporary storage for the results of a target operation so that multiple clients can share the results.

    • Smart Reference Proxy: When an object is referenced, it provides some additional operations, such as recording the number of times the object is invoked.

5. Type behavior

  • Chain of Responsibility model(Chain of Responsibility) : Avoids coupling between the sender and receiver of the request by giving multiple objects the opportunity to process the request. Link the object in a chain and pass the request along the chain until an object handles it. (The response chain in iOS follows the chain of responsibility model.)

ConcreteHandler: A class that implements responsibilities, in which it handles requests within its responsibilities and, if not, forwards the request to a successor Client: Clients of the responsibility chain submit requests to specific objects on the chain and let the responsibility chain handle themCopy the code
  • Command mode(Command Pattern) : In software systems, “behavior requester” and “behavior implementer” often present a “tight coupling.” But in some situations, such as “record, undo/redo, transaction” processing of behavior, such tight coupling that cannot resist change is not appropriate. In this case, how do you decouple the “behavior requester” from the “behavior implementor”? Abstract a set of behaviors as objects to achieve loose coupling between them. That’s the Command mode (Target-Action, NSInvocation is command mode)

  • Interpreter Pattern: Defines the grammar of a language and sets up an Interpreter to interpret the sentences in the language. The “language” here refers to the code that uses the prescribed format and syntax. The interpreter pattern is a behavioral pattern. (For example, the interpreter pattern is applied to determine whether an email address, phone number, or id number is a correct regular expression.)

  • Iterator Pattern: Provides a way to access an aggregate object without exposing the internal representation of the object, alias Cursor. The iterator pattern is an object behavior pattern. (NSEnumerator)

  • Mediator Pattern: Encapsulates a set of object interactions with a Mediator object that does not explicitly reference each other, loosens the coupling, and can change their interactions independently. The mediator pattern, also called the mediator pattern, is an object behavior pattern, and the mediator pattern is a typical application of “Demeter’s rule”. (iOS componentization)

    • Mediator: It defines an interface for communicating with peer objects.

    • ConcreteMediator: A subclass of abstract mediator that implements cooperative behavior by coordinating colleague objects, maintaining references to colleague objects.

    • Colleague: It defines methods common to Colleague classes and declares abstract methods for subclasses to implement, while maintaining a reference to an abstract mediator class through which subclasses can communicate with the mediator.

    • ConcreteColleague: This is a subclass of the Abstract colleague class; When each colleague object needs to communicate with other colleagues, it communicates with the intermediary first, and indirectly completes the communication with other colleagues through the intermediary. The abstract methods declared in the abstract colleague class are implemented in the concrete colleague class.

  • Memento Pattern: Capture the internal state of an object and save the state outside of the object without breaking encapsulation, so that the object can be restored to its original saved state at a later time. It is an object behavior pattern, alias Token. (The Cocoa Touch framework uses the memo pattern in archive unfile, property list serialization, and CoreData.)

    • Originator: A common class that can create a memo and store its current internal state, or that can be used to restore its internal state. The Originator is usually a class that needs to store its internal state.

    • Memento: Stores the internal state of the originator, which internal state is saved according to the originator. In general, the design of memo can refer to the design of the originator and determine the attributes in the memo class according to the actual needs. Note that the memo object cannot be used directly by any class other than the originator itself and the responsible human, and the implementation mechanism of the originator design varies between programming languages.

    • Caretaker: The Caretaker keeps the memo but does not act on it or check the contents. In charge of the human can store one or more memo objects, it is only responsible for storing objects, and cannot modify objects, also do not need to know the implementation details of the object.

  • 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 aliases for the observer pattern include Publish/Subscribe, Model/View, Source/Listener, or Dependents. The observer pattern is an object behavior pattern. (KVO, NSNotication in iOS are observer modes)

  • State Pattern: Allows an object to change its behavior when its internal State changes. The object appears to have modified its class. Its alias is Objects for States. State mode is an object behavior mode, which is used to solve the problem of state transformation of complex Objects in the system and encapsulation of behaviors in different States.

  • Strategy Pattern: Define a series of algorithm classes, encapsulate each algorithm, and make them interchangeable. The Strategy Pattern makes the algorithm change independently of the customers who use it, also called Policy Pattern. Policy pattern is an object behavior pattern. In the MVC pattern, the controller determines when and what the view displays the model data. The view itself knows how to draw, but it needs the controller to tell it what to display. If the same view works with different controllers and the data content varies from controller to controller, the controller is the view’s policy.

  • Template Method Pattern: A framework that defines an algorithm in an operation, deferring some steps to subclasses. The template method pattern allows subclasses to redefine specific steps of an algorithm without changing the structure of that algorithm. In the Cocoa Touch framework, the most common UIViewController must override various rotation methods if it needs to accommodate screen rotations, such as shouldAutorotate, which is a typical hook method. UIView also has a drawRect method that subclasses can override if they need to perform a custom drawing. DrawRect is also a hook method.

  • Visitor Pattern: Provides a representation of operations on elements in an object structure that allows us to define new operations on those elements without changing the classes of the elements. The visitor pattern is an object behavior pattern.