5.1. Categories and Classes

 <  Day Day Up  >  

Sam came by and said, "Oh, by the way, the rental period is different based on the category of a CDRelease."

"What is a category?" I asked.

"Oh," he said nonchalantly, "it could be a Golden Oldie, New Release, or Regular. Didn't I mention that before?"

"You must have ”I just didn't remember it," I noted dryly.

You can approach this issue in a couple of ways ”using different classes and using different objects. Using different classes is often the solution for when a programmer learns about inheritance. Once you have a shiny new hammer , every problem is a nail needing to be pounded. But not every problem is, or should be, solved with inheritance. Often an extra attribute in a class will do the trick.

5.1.1. Different Classes

We have three different categories: NewRelease , GoldenOldie , and Regular . Because there are three names , a designer might make these three separate classes. Since they are CDRelease s, a natural thing to do is to form an inheritance hierarchy with a base class from which to derive each class. Figure 5-1 shows what an inheritance-oriented class hierarchy might look like.

Figure 5-1. A CDRelease inheritance hierarchy

The CDRelease abstract base class defines the base_rental_period() abstract method. This method is implemented differently for each type of CD. The base class and the three derived classes would look like those shown in Example 5-1.

Example 5-1. CDRelease with inheritance
 abstract class CDRelease         {         abstract Days base_rental_period();         };     class NewReleaseCD extends CDRelease         {         Days base_rental_period()             {             return 2;             }         };     class GoldenOldieCD extends CDRelease         {         Days base_rental_period()             {             return  4;             }         };     class RegularCD extends CDRelease         {         Days base_rental_period()             {             return  3;             }         }; 

Some solutions might use a concrete method for base_rental_period() and eliminate the RegularCD class.

The users of the classes illustrated in Figure 5-1 would use objects as outlined in Example 5-2.

Example 5-2. Using derived classes
 CDRelease my_cd = new GoldenOldieCD();         Days rental_period = my_cd.base_rental_period(); 

5.1.2. Different Objects

Having three classes whose behavior differs only in terms of the value of a property is an example of overclassification. The alternative is to have a single class with an attribute that denotes the type of CD. The class diagram in Figure 5-2 depicts this alternative.

Figure 5-2. CDRelease using an enumerated category

The term CDCategory in Figure 5-2 might not specify exactly what we mean. The word category can be overloaded. However, if the client says that is what he wants, by all means, go with the client. It will make life a lot easier if you and your client are on the same page.

Using the CDCategory enumeration, the CDRelease class appears as shown in Example 5-3.

Example 5-3. CDRelease using different objects
 enumeration CDCategory {NEW_RELEASE_CD, REGULAR_CD, GOLDIE_OLDIE_CD};          class CDRelease         {         CDCategory category;         CDRelease(CDCategory cd_category)             {             this.category = cd_category;             }         Days base_rental_period()             {             /* Coming up soon */             }         }; 

Using different objects, the code corresponding to Example 5-2 is shown in Example 5-4.

Example 5-4. Using different objects
 CDRelease my_cd = new CDRelease(GOLDIE_OLDIE_CD);         Days rental_period = my_cd.base_rental_period(); 

The code for the base_rental_period() method in CDRelease that corresponds to the code for the derived classes in Example 5-1 looks like that shown in Example 5-5. [*]

[*] Example 5-5 was written to parallel the derived class example. We should apply the "Never Let a Constant Slip into Code" guideline so that the numbers are coded as BASE_RENTAL_PERIOD_FOR_NEW_RELEASE , etc.

Example 5-5. Base_rental_period method
 static Days [] base_rental_period_per_category = {2, 3, 4};          Days base_rental_period()         {         return base_rental_period_per_category [category];         } 

The real question is whether the three types really represent objects of the same class or of different classes. One rule of thumb you can use in making that decision is whether the objects differ in just values or in the logic of their methods . [*] If the former is true, one class might be sufficient. If the latter is true, different classes might be appropriate. We will examine inheritance again in a later section.

[*] Scott Ambler suggests that this concept came from Responsibility-Driven Design. This topic was introduced in Object-Oriented Design: A Responsibility-Driven Approach by Rebecca Wirfs-Brock and Brian Wilkerson (Proceedings of OOPSLA, 1989).

DON'T OVERCLASSIFY

Separate concepts into different classes based on behavior, not on data.


 <  Day Day Up  >  


Prefactoring
Prefactoring: Extreme Abstraction, Extreme Separation, Extreme Readability
ISBN: 0596008740
EAN: 2147483647
Year: 2005
Pages: 175
Authors: Ken Pugh

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net