Today I am going to show you how to implement a factory pattern in your iPhone app.
This the second installment of my series of articles about how to implement the abstract factory design pattern in an iPhone app. Before we move on to the abstract factory we should start with a regular factory implementation.
The idea of a factory is that you have one object that supplies all of the objects that an app will need. We will be defining a factory class and then we will simply use class functions to return objects to the program. Each component in the system will simply need to use an import directive to use our factory.
The first thing I did was create a new window based application. I choose window based because I want the first view to be determined by the factory. I also created two view controllers that I am simply calling View_A and View_B.
The two views look different; each view has a label but the colors and fonts all look different. Interface builder was used to create the UI elements. I also made sure to create two new groups in my XCode Groups and Files pane: Factory and View. This is my way of keeping these components organized.
The Factory Code
Now that you have the basic setup, let’s get to the factory code. For now, my factory is going to return a view controller and a string. Here is the interface file:
As you can see here this is very simple, our factory only produces two objects right now. Here is how I implemented the factory:
This is pretty straight forward. The factory creates a pretty boring string that just says “Default Title” while the UIViewController that is returned has a pretty sparse view that just displays a white background with a label in at the bottom.
That is the factory class definition, now we need to use our factory back in the app delegate to retrieve the view from the factory object. We will declare a view controller in our app delegate and release the view controller in our app delegate’s dealloc method. We need to do this because our factory is not using autorelease (thoughts on this?).
Here is the key bit of code from the app delegate:
This is pretty simple, now when we build the app we will get whatever components we defined in the factory displayed in the app window.
We also used the factory object from within our view controller itself. Take a look at the viewDidLoad method in our View_A class:
Here is the screen that we get when we run this app:
Now that everything is setup I can make changes easily by just changing what gets returned in the factory class definition. Let’s change the title here to something cooler:
Now, when I run the app you can see that the app label has changed:
Previously, I used Interface Builder to create an different view for my app. As you can guess this is also very easy to change by altering the appropriate function in the factory:
Now when we build and run the run we get a completely different looking app:
So, that is how you do it. The factory pattern is pretty cool – it will let you centralize key variables and you can make changes to objects used by many components in your system in one place.
But, to be truly useful we need more from our factory. We would like to be able to switch back and forth between factories on the fly. This is what would give us a truly flexible and customizable solution.
Stay tuned – tomorrow I will show you what I mean when we code up our first abstract factory!
[...] That post on howtomakeiphoneapps.com from yesterday introduced me to design patterns. Started reading Design Patterns Explained: A New Perspective on Object-Oriented Design, Second Edition by Alan Shallowy, James R. Trott. Only got through the first paragraph about Object Orientation which I already know a bit. Nonetheless it’ been great so far. Can’t wait to read on. [...]
Would it be more appropriate to set the autorelease on the view controller? It assume the worst. ie. the caller does not release the view controller. If they want to keep it beyond the event they must call retain.
+(UIViewController *) mainView{
UIViewController *uivc
uivc = [[View_B alloc] initWithNibName:@”View_B” bundle:nil];
[uivc autorelease]
return uivc;
}
I struggled with this one. As you point out normally you would always use autorelease when returning objects like this from convenience functions.
But, in this case the purpose of the factory is to create all the app’s objects; so I am more worried that most people would forget to retain the object causing hard to find memory errors that would make the app crash. Also, since the purpose of the factory is to make life easier I would rather not seen extra retain messages peppered across the code.
But, this does give me pause when considering using this pattern in an app.
Learn How To Make An iPhone App right now using my proven system.
PS: Tons of us are having a blast living off our own code, join us now. Click here to get all the details.