Intro To Object-Oriented Design: Part 2/2

This tutorial series will teach you the basics of object-oriented design. In this final part: polymorphism, factory methods, and singletons. By Ellen Shapiro.

Leave a rating/review
Save for later
Share

Update note: Check out the latest version of this tutorial, updated for iOS 8 and Swift! Intro to Object-Oriented Design in Swift.

In Part 1 of this tutorial, you learned the basics of object-oriented design: objects, inheritance, and the model-view-controller pattern. You created the beginnings of a simple application called Vehicles to help you gain a better understanding of these concepts.

Here in the second part, you’re going to learn about Polymorphism and a couple of other key patterns in Object-Oriented programming: The Class Factory Method and the Singleton Instance.

If you completed the previous tutorial, great! You can either pick up where you left off with your previous project. However, if you want to jump right into things, you can download the completed project from Part 1 to get started.

Polymorphism

The general definition of Polymorphism comes from its Greek roots – “Poly” means many, and “Morph” means forms.

The computer-science specific definition, pulled from the Free Online Dictionary of Computing, is:

A variable that may refer to objects whose class is not known at compile time and which respond at run time according to the actual class of the object to which they refer.

The combination of these definitions boils down to “the ability of an object to be more than one thing at a time.” Sounds like your average iOS developer, doesn’t it? ;]

There are several subtypes of polymorphism that are used within Objective-C, but two key ones you’ll see often are the Decorator pattern and the Adapter pattern.

The Decorator Pattern

From Apple’s Cocoa Fundamentals guide’s section on Cocoa Design Patterns:

The Decorator design pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. As does subclassing, adaptation of the Decorator pattern allows you to incorporate new behavior without modifying existing code. Decorators wrap an object of the class whose behavior they extend.

The primary example of the Decorator pattern in Objective-C is the use of Categories.

Categories are a special kind of class in iOS that allow you to add additional methods to classes without having to subclass or alter the original class. They’re primarily used for adding methods to the stock UIKit components that come with iOS.

The difference between a category and a subclass is pretty simple: A category allows you to add new methods, but not override existing methods. You can’t add new properties or instance variables to categories – you can only use existing ones. If you want to add a new property or instance variable, you’ll need to create a subclass and use the power of inheritance to create your additional properties and methods.

But what if you don’t need to do that? What if you just want to create a simple way to encapsulate something you have to do repeatedly with a particular UIKit object? In this case, a category is the perfect solution.

In your tutorial app, you’re going to add a convenience method to UIAlertView to do away with performing the alloc-init-show dance for simple alerts over and over again in your code.

Implementing the Decorator Pattern

Go to File\New\File\Cocoa Touch, and select Objective-C Category:

Objective-C Category

Add the category name as Convenience as a category on UIAlertView:

Adding Convenience Category to UIAlertView

Once you’ve created the files, you can see by their filenames the syntax Xcode uses to indicate that a file is a category, as shown below:

UIAlertView+Convenience

The [Component]+[Category Name] format indicates both the original class being decorated and what the category itself does. It’s completely acceptable to use multiple categories on the same class in the same application; this makes it easier to reuse categories in other applications.

Creating a method on a category is very similar to creating a method on a normal class. Since you’re going to be creating a new instance of UIAlertView rather than working with an existing instance, open up UIAlertView+Convenience.h and add the following class declaration for your method after the @interface line:

// Shows a UIAlertView with the given title and message, and an OK button to dismiss it.
+ (void)showSimpleAlertWithTitle:(NSString *)title andMessage:(NSString *)message;

Then, open UIAlertView+Convenience.m and add the method implementation:

+ (void)showSimpleAlertWithTitle:(NSString *)title andMessage:(NSString *)message
{
    UIAlertView *simpleAlert = [[UIAlertView alloc] initWithTitle:title
                                                          message:message
                                                         delegate:nil
                                                cancelButtonTitle:@"OK"
                                                otherButtonTitles:nil];
    [simpleAlert show];
}

You’re not doing anything revolutionary here — you’re just combining a bunch of the boilerplate code you’d write over and over and over to show a simple alert view with a single button to dismiss it.

Next, open VehicleDetailViewController.m and add the following import:

#import "UIAlertView+Convenience.h"

Towards the bottom of the file, you’ll find several IBAction methods with just TODO comments in the method body. Update goForward, goBackward, stopMoving, and makeNoise as shown below to use your new category:

-(IBAction)goForward
{
    [UIAlertView showSimpleAlertWithTitle:@"Go Forward" andMessage:[self.detailVehicle goForward]];
}

-(IBAction)goBackward
{
    [UIAlertView showSimpleAlertWithTitle:@"Go Backward" andMessage:[self.detailVehicle goBackward]];
}

-(IBAction)stopMoving
{
    [UIAlertView showSimpleAlertWithTitle:@"Stop Moving" andMessage:[self.detailVehicle stopMoving]];
}

-(IBAction)makeNoise
{
    [UIAlertView showSimpleAlertWithTitle:@"Make Some Noise!" andMessage:[self.detailVehicle makeNoise]];
}

Build and run your application; after selecting a vehicle, press any button except the “Turn…” button, and you’ll see the appropriate message for each instance of a Vehicle. For example, if you press the “Make Some Noise!” button for various Vehicles, you’ll see the following:

Make some noise!

But what if you need to do something a bit more complicated – something that requires getting information from the UIAlertView that you’ve shown? This is where the Adapter pattern and its use of delegation comes in handy.

The Adapter Pattern

Again from the Cocoa Fundamentals Guide:

The Adapter design pattern converts the interface of a class into another interface that clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces. It decouples the client from the class of the targeted object.

Protocols are the primary example of the Adapter pattern in Objective-C. This designates a number of methods that can be implemented by any class. They’re most often used for DataSource and Delegate methods, but can also be used to help two unrelated classes communicate with each other.

The advantage of this pattern is that as long as a class declares that it conforms to the protocol, it really doesn’t matter whether it’s a model, a view, or a controller. It simply needs to know what is happening in the other class, and will implement any required methods needed to know about this.

In order to help figure out how many degrees the user wants to turn a vehicle, you’ll take advantage of the UIAlertViewDelegate protocol to get the information the user enters into a UIAlertView.

Contributors

Over 300 content creators. Join our team.