1 Preface
In many object-oriented applications, some objects are too expensive or too complicated to create. Things would be much easier if the same object could be reconstructed and slightly changed. We can reuse existing objects with slight changes to suit specific situations in the program. Today we will learn about this model.
2 Details
2.1 Definition
The mode applied to the "copy" operation becomes the prototype mode. Copying refers to the production of a series of products using the same mold. The item on which the mold is based is called a prototype. Although products are copied with the same mold, some properties, such as colors and sizes, can be slightly different, they still belong to the same category.
2.2 When to use prototype mode
(1) The objects that need to be created should be independent of their type and creation method.
(2) The class to be instantiated is determined at runtime.
(3) Do not want the factory level corresponding to the product level.
(4) The differences between instances of different classes are only several combinations of states. Therefore, it is more convenient to copy the corresponding number of prototypes than to instantiate them manually.
(5) Classes are not easy to create, for example, each component can use other components as a combination object of child nodes. It is easier to copy existing combination objects and modify the copy.
The minimum of this pattern is to generate a real copy of the object to be used as the basis (prototype) for other related things in the same environment.
2.3 Shallow copy and deep copy
Deep replication is to open up new memory to realize real memory replication. shallow copying, only copying pointers, and heap memory remains unchanged. When we design the system, sometimes some objects need to complete copy and backup operations based on user operations. At this time, if you initialize the object according to the original method, it will cause some inconvenience and problems:
(1) Some properties of the object are generated during user operations, and values cannot be assigned based on just one initXXX method;
(2) Regular assignment is too troublesome and destroys the encapsulation.
At this time, the advantages of the prototype model are reflected.
First create a Player class, which has 2 attributes, highstLevel and currentLevel, and provides 2 public methods to modify these 2 attributes. The code is as follows:
@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 important thing is that Player needs to implement the NSCopying protocol:
#pragma mark - Override
- (instancetype)copyWithZone:(NSZone *)zone
{
Player *copyPlayer = [[[self class] allocWithZone:zone] init];
= ;
= ;
return copyPlayer;
}
Here you see the NSZone type. What type is this? In fact, it is a structure, which is introduced to prevent memory fragmentation. NSZone will allocate memory according to the memory size you want to open up and improve memory management. However, the official Programming with ARC Release Note also points out that the current runtime system ignores the concept of zones because its own memory management is already very efficient. Using Zone will reduce memory usage, access efficiency, increase source code complexity, etc. Therefore, NSZone is generally not used. In this example, although the allocWithZone method is used, we will find that Apple actually uses the general initialization method instead of the original Zone development:
#pragma mark - Override
- (instancetype)copyWithZone:(NSZone *)zone
+ (instancetype)allocWithZone:(struct _NSZone *)zone OBJC_SWIFT_UNAVAILABLE("use object
initializers instead");
This is basically the prototype design pattern. Of course, our Player class can be turned into an interface, allowing subclasses to implement, and better reflect interface-oriented programming.
result:
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 other files and you will see a newly opened piece of memory for us by the system, with a reference count of 1.
Object copying in the Touch framework
The CocoaTouch framework provides a protocol for deep replication for derived classes of NSObject. The subclass of NSObject needs to implement the NSCopying protocol and its method -- (id) copyWithZone:(NSZone *)zone. NSObject has an instance method called (id)copy. The default copy method calls [selfcopyWithZone:nil]. For subclasses that have adopted NSCopying protocol, this method needs to be implemented, otherwise an exception will be raised. In IOS, this method keeps the new copy object and returns it. The caller of this method is responsible for releasing the returned object.
The trick of deep copy is to ensure that resources in memory are indeed copied, not just pointers.