Top Banner

Click here to load reader

of 37

重構—改善既有程式的設計(chapter 8)part 2

Dec 08, 2014

Download

Education

Chris Huang

 
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  • 1. Hubert Chan
    Refactoring chap 8-2

2. 8.9 Replace Magic Number with Symbolic Constant
Magic Number

/ /

Constant Magic Number
double potentialEngery(double mass, double height) {
return mass * 9.81 * height
}
double potentialEngery(double mass, double height) {
return mass * GRAVITATIONAL_CONSTANT * height
}
static final double GRAVITATIONAL_CONTSTANT = 9.81;
3. 8.9 Replace Magic Number with Symbolic Constant
Refactoring
Magic Number Type Code
Replace Type Code With Class

Array.length()

const
static
final
4. 8.10 Encapsulate Field
class A {
public String _name;
}
class A {
private String _name;
public String getName() {return _name;}
public void setName(String arg) {_name = arg;}
}
5. 8.10 Encapsulate Field

Encapsulation
Data Hiding
public
Objective-C 2.0 property
readonly
readwrite
assign
copy
6. 8.11 Encapsulate Collection

Collection readonly view
add/remove function
7. 8.11 Encapsulate Collection

Getter collection

getter collection
add/remove
CollectionList, Array, Vector
8. 8.11 Encapsulate Collection
class Course {
public Course (String name, booleanisAdvanced) {}
public booleanisAdvanced() {}
}
Class Person {public Set getCourses() {
return _courses;}
public void setCourses(Set arg) {
_courses = arg;}
private Set _courses;
}
// data
// assign
9. 8.11 Encapsulate Collection
Person kent = new Person();
Set s = new HashSet();
s.add(new Course("Smalltalk Programming", false));
s.add(new Course("Appreciating Single Malts", true));
kent.setCourses(s);
Course refact = new Course("Refactoring", true);
kent.getCourses().add(refact);
kent.getCourses().remove(refact);
// assign
// data
// data
10. 8.11 Encapsulate Collection
Refactoring for JAVA 1.2
add/remove
Class Person {
public void addCourse(Course arg) {
_courses.add(arg);}
public void removeCourse(Course arg)
_courses.remove(arg);}
public void initializeCourses(Set arg) {
Assert.isTrue(_courses.isEmpty());
_courses.addAll(arg);}
}
// _courses != arg
11. 8.11 Encapsulate Collection
Refactoring for JAVA 1.2
add/remove
Person kent = new Person();
Set s = new HashSet();
s.add(new Course("Smalltalk Programming", false));
s.add(new Course("Appreciating Single Malts", true));
kent.setCourses(s);
Person kent = new Person();
kent.addCourse(new Course("Smalltalk Programming", false));
kent.addCourse(new Course("Appreciating Single Malts", true));
12. 8.11 Encapsulate Collection
Refactoring for JAVA 1.2
getter collection
Getter unmodified set
kent.getCourses().add(new Course("C Programming", false));
Class Person {
public Set getCourse() {
return Collections.unmodifiableSet(_courses);}
}
// unmodifiable Set
13. 8.11 Encapsulate Collection
class
Move Method

class Person {
intnumberOfAdvancedCourses(Person person) {Iterator iter = person.getCourses().iterator();
int count = 0;
while (iter.hasNext()) {
Course each = (Course) iter.next();
if (each.isAdvanced()) count++;}
return count;
}
}
14. 8.12 Replace Record with Data Class

record structure data class
getter/setter
class Person {
String getName() {
return _name;}
String setName(String arg) {
_name = arg;}
private String _name;
}
class PersonRecord {
public char[] name;
}
15. 8.13 Replace Type Code with Class

Type Code
Type Code => Classfactory class
16. 8.13 Replace Type Code with Class
Person Type Code
class Person {
public static final int O = 0;
public static final int A = 1;
public static final int B = 2;
public static final int AB = 3;
private int _bloodGroup;
public Person (intbloodGroup) {
_bloodGroup = bloodGroup;
}
public void setBloodGroup(intarg) {
_bloodGroup = arg;
}
public intgetBloodGroup() {
return _bloodGroup;
}
}
// int
17. 8.13 Replace Type Code with Class
Person Type Code BloodGroup Class
class BloodGroup {
public static final BloodGroup O = new BloodGroup(0);
public static final BloodGroup A = new BloodGroup(1);
public static final BloodGroup B = new BloodGroup(2);
public static final BloodGroup AB = new BloodGroup(3);
private static final BloodGroup[] _values = {O, A, B, AB};
private finalint _code;
privateBloodGroup (int code ) {
_code = code;
}
public intgetCode() {
return _code;
}
public static BloodGroup code(intarg) {
return _values[arg];
}
}
//class instance Type Code
//constructor private
18. 8.13 Replace Type Code with Class
Class
class Person {
public static final int O = BloodGroup.O.getCode();
public static final int A = BloodGroup.A.getCode();
public static final int B = BloodGroup.B.getCode();
public static final int AB = BloodGroup.AB.getCode();
private BloodGroup _bloodGroup;
public Person (intbloodGroup) {
_bloodGroup = BloodGroup.code(bloodGroup);
}
public intgetBloodGroup() {
return _bloodGroup.getCode();
}
public void setBloodGroup(intarg) {
_bloodGroup = BloodGroup.code (arg);
}
}
19. 8.13 Replace Type Code with Class
Constructor Class
setter/getter
class Person {
public Person (BloodGroupbloodGroup) {
_bloodGroup = bloodGroup;
}
public void setBloodGroup(BloodGrouparg) {
_bloodGroup = arg;
}
public BloodGroupgetBloodGroup() {
return _bloodGroup;
}
}
// BloodGroup
// Setter
// Getter
20. 8.13 Replace Type Code with Class

Person thePerson = new Person(PersonA);
thePerson.getBloodGroupCode();
thePerson.setBloodGroup(Person.AB);
Person thePerson = new Person(BloodGroup.A);
thePerson.getBloodGroup();
thePerson.setBloodGroup(BloodGroup.AB);
21. 8.14 Replace Type Code with Subclasses

type code class
Replace Conditional with Polymorphism

22. 8.14 Replace Type Code with Subclasses
class
type code
class Employee{
private int _type;
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;
Employee (int type) {
_type = type;
}
}
//Type Code
23. 8.14 Replace Type Code with Subclasses
Base Class function
getType()
class Employee{
abstractintgetType();
}
class Engineer extends Employee {
intgetType() {
return Employee.ENGINEER; }
}
//abstract subclass implement
// implement
24. 8.14 Replace Type Code with Subclasses
factory class
class Employee {
static Employee create(int type) {
switch (type) {
case ENGINEER:
return new Engineer();
case SALESMAN:
return new Salesman();
case MANAGER:
return new Manager();
default:
...
}
}
//getType
25. 8.14 Replace Type Code with Subclasses
Refactoring

Push Down Method
Push Down Field
26. 8.15 Replace Type Code with State/Strategy

type code class
subclassing type

state object type code
Replace Type Code with Class
27. 8.15 Replace Type Code with State/Strategy
type code state object
class Employee{
private int _type;
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;
Employee (int type) {
_type = type;
}
}
//Type Code
28. 8.15 Replace Type Code with State/Strategy
type code
class Employee{
intpayAmount() {
switch (_type) {
case ENGINEER:
return _monthlySalary;
case SALESMAN:
return _monthlySalary + _commission;
case MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException("Incorrect Employee");
}
}
}
// Type Code
29. 8.15 Replace Type Code with State/Strategy
state object / state
abstract class / abstract function
abstract class EmployeeType {
abstract intgetTypeCode();
}
class Engineer extends EmployeeType {
intgetTypeCode () {
return Employee.ENGINEER;
}
}
//abstract function
//subclass implementation
30. 8.15 Replace Type Code with State/Strategy
state state object class
class Employee...
private EmployeeType _type;
void setType(intarg) {
switch (arg) {
case ENGINEER:
_type = new Engineer();
break;
case SALESMAN:
_type = new Salesman();
break;
case MANAGER:
_type = new Manager();
break;
default:
...
}
}
// factory pattern
//
31. 8.15 Replace Type Code with State/Strategy
factory method state object
class Employee...
void setType(intarg) {
_type = EmployeeType.newType(arg);
}
class EmployeeType...
static EmployeeTypenewType(int code) {
switch (code) {
case ENGINEER:
return new Engineer();
case SALESMAN:
return new Salesman();
case MANAGER:
return new Manager();
default:
...
}
}
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;
//setter state class factory method
// state class factory method
32. 8.15 Replace Type Code with State/Strategy
state object state
Replace Conditional with Polymorphism
class Employee...
intpayAmount() {
switch (getType()) {
case EmployeeType.ENGINEER:
return _monthlySalary;
case EmployeeType.SALESMAN:
return _monthlySalary + _commission;
case EmployeeType.MANAGER:
return _monthlySalary + _bonus;
default:
...
}
}
33. 8.16 Replace Subclass with Fields

Subclass function constant method
field constant method
34. 8.16 Replace Subclass with Fields

abstract method hard-code
abstract class Person {
abstract booleanisMale();
abstract char getCode();
...
class Male extends Person {
booleanisMale() {
return true;
}
char getCode() {
return 'M';
}
}
//return hard-code
//return hard-code
35. 8.16 Replace Subclass with Fields
Factory Method subclass
subclass constructor private
subclass
class Person...
static Person createMale(){
return new Male();
}
static Person createFemale() {
return new Female();
}
36. 8.16 Replace Subclass with Fields
superclass field
class Person...
protected Person (booleanisMale, char code) {
_isMale = isMale;
_code = code;
}
booleanisMale() {
return _isMale;
}
class Male...
Male() {
super (true, 'M');
}
// Field subclass function
37. 8.16 Replace Subclass with Fields
subclass
class Person
static Person createMale(){
return new Person(true, 'M');
}
// factory pattern