First Factory Methods (Wiki forum at Coderanch) (original) (raw)

[this page is under construction]

This page is a follow-up to the FirstClasses tutorial, and shows you how to create factory methods for your Person class.

First off, we should probably describe what a factory method is:

For the purposes of this discussion, a factory method is simply a static method that returns an instance of our type - ie, it's basically an alternative to a constructor.

There is a bit more to it than that; but for the moment the above description should suffice.

Factory methods can be a very useful because:

Indeed many programmers use them to hide constructors from clients.

This page contains some useful information about factory methods.


fromString(String)

One thing you will probably want to be able to do - at least early on - is to be able to create a number of instances of your class from a text file of Person records, where each "record" is a line in the file.

The first thing you need to do is to decide what that "record" will look like. Sometimes, you will be given a format that you have to work with, such as CSV, in which case you'll have to write it to spec; other times you will be able to create a format for yourself.

.

Since CSV can get a bit involved, I'm going to assume that we've been allowed to decide our own format - and since we already have one from our toString() method, ie:

why not use it?

Tip #13:

If you write a fromString() method (or equivalent), and you get to decide its input format, make it compatible with your toString() method.

.

OK, lets parse that string. The first method you need to know about for something like this is String.split() - an incredibly useful method that you should become familiar with ASAP.

There's quite a bit to know about it, but in it's simplest form it breaks up a String into an array of "fields" (also Strings), based on a 'delimiter'. In our case the delimiter is ";" so the call will look something like:

which will put "Joe Bloggs" into fields[0] and "47" into fields[1].

Tip #14:

String.split() takes a regular expression (regex), and they have quite a few "metacharacters". If, as in our case, the delimiter only has one character, and you're not sure if it's a metacharacter or not, you can put it in square brackets, viz:

which will remove any special meaning it has for the regex. In fact, ";" doesn't, so you don't need to do it, but I'll leave it in to remind you.

.

Right, so let's use it:

Simple, eh? Do you see what's happening? We've already done most of the work, and all we're doing is re-using it. And that's how to write properly modular code: you build it up, bit by bit.

The check is simply to make sure that the supplied string contains exactly 2 fields, separated by a single ";".


fromFile(String)

Our next factory method builds on the previous one to return a bunch of Person objects from a file whose path is supplied to the method as a String.

Here it is:

I don't propose to go through the code in minute detail, since I/O is beyond the scope of this tutorial; however, there are a few points worthy of note:

ARE necessary.


fromUser()

This final factory method does something you'll need to do a LOT early on in your programming study: create an instance of a class by prompting the user for input and taking what they type in from the keyboard. Unfortunately, this is quite a fiddly process, and most beginners create enormous piles of procedural code in their main() methods to do it.

DON'T.

It's a class's responsibility to know how it is created, and that includes via user input. Furthermore, you can re-use a lot more code if you write it in the class.

There is a LOT to know about user input, which I've covered in a tutorial called UserInput. The following is just a taster of the sort of thing you'll need to do:

It's not particularly brilliant, because it will throw an Exception if the user doesn't follow orders but, as I said above, an exhaustive look into the business of UserInput is beyond the scope of this tutorial.

However, do you now see why we wrote the constructor that takes Strings? We've now used it twice to write some very useful methods.

.

And just in case you didn't know, calls to our factory methods should use the class name because they're static; viz:


So that's our factory methods done. Don't worry if their significance isn't immediately obvious, just make sure you understand the building process - making a class that can do great things from small pieces of code, built piece by piece.


CategoryWinston