Examples illustrate the role of prototype patterns in iOS application development

  • 2020-05-27 07:14:12
  • OfStack

1 introduction
In many object-oriented applications, some objects are too expensive or complex to create. It would be easier to recreate the same objects and make minor changes. We can reuse existing objects with minor changes to suit specific situations in the program. Today we're going to look at one of these patterns.

2 in detail
2.1 define
The pattern applied to the "copy" operation becomes the stereotype (Prototype) pattern. Copy (cloning) refers to the production of series 1 products from the same mould. The object on which the mold is based is called a prototype. Although the products are copied using the same mold, some properties, such as color and size, can be slightly different, but they still belong to the same category.
2.2 when the prototype mode is used
(1) the object to be created should be independent of its type and creation mode.
(2) the class to be instantiated is determined at runtime.
(3) do not want the factory level corresponding to the product level.
(4) the difference between instances of different classes is only a number of combinations of states. Therefore, it is more convenient to copy a corresponding number of prototypes than to instantiate them manually.
(5) class is not easy to create, for example, each component can use other components as composite objects of child nodes. It is easier to copy and modify the existing composite objects.
At a minimum, this pattern generates a true copy of the object to be used as a basis (prototype) for other related things in the same 1 environment.
2.3 shallow and deep replication
Deep copy is opening up new memory to achieve real memory replication, shallow copy, copy only a pointer, heap memory remains the same. When we design the system, sometimes 1 some object need according to the user operation to complete backup operations such as copy, at this time, if again according to the original method to initialize the object 1 times will bring some inconvenience and issues: 1
(1) some properties of the object are generated in the process of user operation, and cannot be assigned by only one initXXX method;
(2) regular assignment is too cumbersome and breaks encapsulation.
This is where the advantages of the prototype model come into play.

First, create an Player class with two properties, highestLevel and currentLevel, and provide two public methods to modify the two properties.

@interface Player : NSObject <NSCopying>
 *  update player's current level during game
 *  @param level
- (void)updateCurrentLevel:(NSInteger)level;
 *  update player's highest level during game
 *  @param level
- (void)updateHighestLevel:(NSInteger)level; @end

The most critical thing is that Player needs to implement the NSCopying protocol:

#pragma mark - Override
- (instancetype)copyWithZone:(NSZone *)zone
    Player *copyPlayer = [[[self class] allocWithZone:zone] init];
    copyPlayer.highestLevel = self.highestLevel;
    copyPlayer.currentLevel = self.currentLevel;     return copyPlayer;

Here you see the NSZone type, what type is this ? In fact it is a structure, is introduced in order to prevent memory fragmentation and 1 structure. NSZone will according to the size of the memory of you want to set up to allocate memory, improve memory management. However, the official Programming with ARC Release Note also points out that the current runtime system ignores the concept of regional, because itself memory management is very efficient, using Zone instead reduces memory usage, access efficiency, increase the source code complexity, etc. So as not to use NSZone 1, In this example, although the allocWithZone method is used, if we look at the source code, we will find that the original Zone initialization method is replaced by a 1-like initialization method:

#pragma mark - Override
- (instancetype)copyWithZone:(NSZone *)zone
+ (instancetype)allocWithZone:(struct _NSZone *)zone OBJC_SWIFT_UNAVAILABLE("use object        
  initializers instead");

The prototype design pattern is basically these, of course, our Player class can become an interface, let the subclass to implement, better reflect the interface oriented programming.


2015-09-18 21:30:32.072 DP_Prototype[1173:280693] <Player: 0x14d513f60>
2015-09-18 21:30:32.073 DP_Prototype[1173:280693] <Player: 0x14d5337e0>

Call the copy method in another file, and you can see that the system has allocated us a new block of memory with a reference count of 1.

4. Object replication in the Cocoa Touch framework
The CocoaTouch framework provides protocols for implementing deep replication for derived classes of NSObject. A subclass of NSObject needs to implement the NSCopying protocol and its methods -- (id) copyWithZone (NSZone *)zone. NSObject has one instance method called (id) copy. The default copy method call [selfcopyWithZone:nil]. For subclasses that adopt the NSCopying protocol, you need to implement this method or you will throw an exception. In IOS, this method holds the new replica object and returns it. The caller of this method is responsible for releasing the returned object.
The trick with deep replication is to make sure that the resources in memory are actually copied, not just Pointers.

Related articles: