Dynamic Creation

Cocoa utilizes many features of the underlying Objective-C runtime. One powerful feature is the ability to create instances of classes that did not exist at the time an application was compiled and dynamically load and link new classes at runtime.

The core of this pattern is the NSClassFromString() function that returns the class object with a specified name.

 

Motivation

Decoupling classes from each other and postpone decisions about which class to use until runtime. Provide a simple mechanism for pverriding which classes are used for particular tasks within frameworks. Simplify the creation of plug-in architectures.

 

Solution

The basis of this pattern is a single function, NSClassFromString(). It takes a single argument, an NSString containig the value of a class. An Objective-C class object is returned, Once a class object has been obtained, it can be instantiated or otherwise manipulated. One very important aspect of this power is the fact that this function allows a developer to use an object that was unknown to the compiler and linker when the application was built.

This single function effectively reduces the well-known Factory Method pattern to a single line of code in many cases. The Factory Method pattern typically requires an abstract method to be overridden to return a subclass of the desired type. By instead using NSClassFromString(), the desired subclass type can even be named by a string value in an application's property list,to be resoled into a concrete class object at runtime.

 

Example

 The Dynamic Creation pattern can be used when it comes time to parse the input and execute the commands. First, a naming convention for the classes that implement the commands must be decided. In this case, the name can be "MySomethintCommand" in which "something" is replaced by the command. For example, the command "add" is implemented by the class MyAddCommand. For each input string encountered, an attempt is made to look it up with NSClassFromString(). If an object is found, we have a command, and it is executed. If no object is found, and NSClassFromString() reurns nil, then we assume that we have a value to be pushed onto the stack. That's all there is; the details are straightforward from here. Adding new commands to the calculator is as simple as writing a new class, compiling it, and linking it into our application. There is no need to register the new class with the interpreter or list it anywhere. Its mere presence is sufficient to add it to the parsed language.

 

 

Dynamic Creation to Implement Plug-In Architectures

When creating a plug-in architecture, Dynamic Creation greatly simplifies the process.

The purpose of plug-ins isto allow new code to be loaded into an application dynamically. The NSBudle class provides a solid foundation for creating plug-ins. A bundle can tie together code, images, Interface Builder interfaces, text and XML files, and so on and localize them, making it a perfect package for housing all the elements a plug-in might require. As such NSBundle is usually used to implement plug-ins.

The NSBundle class defines a method, -classNamed:, which functions much as NSClassFromString(). Because bundles can contain executable code, the method differs from the function in two key ways. 1. it searches only the bundle itself to find the requested class. 2. it will load executable code and link it into the running application if necessary.

 

NSBundle instances representing plug-ins can be obtained usingth +bundleWithPath: method. Keep in mind that the running application is a special type of bundle, so sending the message [NSBundle mainBundle] will return an NSBundl instance that represents the application. Because frameworks are also bundles, don't expect to be able to look up cass objects for framworks in the main bundle.?

Once the correct bundle is obtained, there are two methods that can be used to obtain Objective-C class objects. Most plug-in architectures will use -principalClass to locate an entry point to the plug-in, given that the names of the classes in th plug-in are probably not known to the application loading them. Each bundle has a property list (Info.plis) that can be configured to identify an Objective-C class as that bundle's principal class by putting the class name in the "Principal clas" key. The -classNamed: method also can be used to obtain a class object from a bundle, if you know the name of the class you want. Both methods will cause the bundle's executable code to be loaded and linked into the application if necessary.

Underlying all of this NSBundle functionality is the Dynamic Creation pattern. Because this pattern decouples class names from the code using the classes, it helps to avoid link time issues when an application that uses plug-ins is compiled. ??

 

 Core Dta relies upon dynamic creation when associating Objective-C classes with entities. When creating data models in Xcode, it is possible to choose a custom subclas of NSManagedObject to be used for each entity that is defined. When Core Data instantiates entities. it uses Dynamic Creatin to instantiate an object of the requested class.

When objects are archived, the class name is stored in the archive, and then the class' data is written. To unarchive an object, the class name is read, and then the dynamic cration is used to instantiate the object. The object is then sent a message to read its data.

These are just a few exampls of places in which this pattern is used. Coca uses Dynamic Creation pervasively throughout the frameworks to increase their flexibilty.

 

 

 

 

 

 

posted on 2013-02-20 00:36  Chansonyan  阅读(244)  评论(0)    收藏  举报

导航