Inheritance


The code for RegularGradingStrategy and HonorsGradingStrategy contains duplicate logic. The code that you used to derive a basic grade is the same in both classesboth classes contain switch statements with the exact same logic:

 switch (grade) {    case A:  return 4;    case B:  return 3;    case C:  return 2;    case D:  return 1;    default: return 0; } 

One solution for eliminating this duplication is to use inheritance. I discussed inheritance briefly in the Agile Java Overview chapter. You can factor the commonality between RegularGradingStrategy and HonorsGradingStrategy into a common class called BasicGradingStrategy. You can then declare the classes RegularGradingStrategy and HonorsGradingStrategy as subclasses of BasicGradingStrategy. As a subclass, each of RegularGradingStrategy and BasicGradingStrategy obtain all of the behaviors of Basic-GradingStrategy.

You will refactor to an inheritance-based solution in very small increments. The first step is to create a BasicGradingStrategy class:

 package sis.studentinfo; public class BasicGradingStrategy { } 

Then declare both RegularGradingStrategy and HonorsGradingStrategy as subclasses of BasicGradingStrategy by using the extends keyword. The extends clause must appear before any implements clause.

 // RegularGradingStrategy.java package sis.studentinfo; public class RegularGradingStrategy       extends BasicGradingStrategy       implements GradingStrategy {    public int getGradePointsFor(Student.Grade grade) {       switch (grade) {          case A: return 4;          case B: return 3;          case C: return 2;          case D: return 1;          default: return 0;       }    } } // HonorsGradingStrategy.java package sis.studentinfo; public class HonorsGradingStrategy        extends BasicGradingStrategy       implements GradingStrategy {    public int getGradePointsFor(Student.Grade grade) {       int points = basicGradePointsFor(grade);       if (points > 0)          points += 1;       return points;    }    int basicGradePointsFor(Student.Grade grade) {       switch (grade) {          case A: return 4;          case B: return 3;          case C: return 2;          case D: return 1;          default: return 0;       }    } } 

You can now move the common code to a method on the BasicGradingStrategy superclass (also known as the base class). First, move the method basicGradePointsFor from HonorsGradingStrategy to BasicGradingStrategy:

 // HonorsGradingStrategy.java package sis.studentinfo; public class HonorsGradingStrategy       extends BasicGradingStrategy       implements GradingStrategy {    public int getGradePointsFor(Student.Grade grade) {       int points = basicGradePointsFor(grade);       if (points > 0)          points += 1;       return points;    } } // BasicGradingStrategy.java package sis.studentinfo; public class BasicGradingStrategy {    int basicGradePointsFor(Student.Grade grade) {       switch (grade) {          case A: return 4;          case B: return 3;          case C: return 2;          case D: return 1;          default: return 0;       }    } } 

Recompile and test.

Even though HonorsGradingStrategy no longer contains the definition for basicGradePointsFor, it can call it just as if it were defined in the same class. This is akin to your ability to call assertion methods in your test classes, because they extend from junit.framework.TestCase. Conceptually, HonorsGradingStrategy is a BasicGradingStrategy, much as a class that implements an interface is of that interface type. Thus HonorsGradingStrategy can use any (nonprivate) method defined in BasicGradingStrategy. (We'll discuss the nonprivate distinction shortly.)

The UML representation of this relationship appears in Figure 6.1.

Figure 6.1. Inheriting from BasicGradingStrategy


Next, modify RegularGradingStrategy to reuse the method basicGradePointsFor.

 package sis.studentinfo; public class RegularGradingStrategy       extends BasicGradingStrategy       implements GradingStrategy {    public int getGradePointsFor(Student.Grade grade) {       return basicGradePointsFor(grade);    } } 



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

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