重新组织数据

来源:互联网 发布:我知女人心南宫寒txt 编辑:程序博客网 时间:2024/05/29 18:09
1. 自封装字段

为字段建立取值设值函数,以函数访问

private int _length, _width;public int area() {    return _length * _width;}更改为↓private int _length, _width;public int area() {    return getLength() * getWidth();}int getLength() {return _length};int getWidth() {return _width};
做法:
为带封装字段设置取值设值函数。
找出该字段的所有引用点,将它们全部改为调用取值设值函数
将该字段设为私有的。

2. 以对象取代数值


随着开发的进行,有时候一个数据项表示不再简单了,比如刚开始只需要知道一个人的名字就行了,可是后来的需求变成了不但要知道这个人的名字还要知道这个人的电话号码,还有住址等。这个时候就需要考虑将数据变成一个对象了。
class Order {    private String name;}更改为↓class Order {    private Person person;}class Person {    private String name;    private String tel;    private String addr;}
我们有时候需要把Person写成单例类,因为一个Person对象可以拥有很多份订单,但是这个对象只能有一个,所以Person我们应该写成单例。但有时候换成其他场景我们不能把他写成单例。这都是要视情况而定的。随意写代码要小心谨慎。
做法:
为待替换数值建立一个类,在其中声明一个final字段,类型和源类中待替换数值类型一致,然后在新类中加入这个字段的取值函数,再加上一个接收此字段为参数的构造函数。
范例:
class Order{ //private String customer; private Customer customer;public Order(String customer) {//this.customer = customer;this.customer = new Customer(customer);}public String getCustomer() {//return customer;return customer.getName();}public void setCustomer(String customer) {//this.customer = customer;this.customer = new Customer(customer);}  } class Customer{ private final String name;public Customer(String name) {this.name =name;}public String getName() {return name;}  }


3.将值对象改为引用对象
4.将引用对象改为值对象
5.以对象取代数组
String [] row = new String[3];row[0] = "love";row[1] ="11";Performance  row = new Performance();row.setName("love");row.setWins("11");


6.复制被监视数据
7.将单向关联改为双向关联
做法:
在被引用类中增加一个字段,用以保存反向指针。
决定由哪个类,引用端还是被引用端,控制关联关系。
在被控端建立一个辅助函数。
如果既有的修改函数在控制端,让它负责更新反向指针。
如果既有的修改函数在被控端,就在控制端建立一个控制函数,并让既有的修改函数调用这个新建的控制函数。
范例:
/**   * 如果俩者都是引用对象,关联关系是一对多的关系,由拥有单一引用的那一方承担控制者角色,如果一个客户   * 可以拥有多份订单,由订单来控制   * 如果某个对象是组成另一个对象的部件,由后者控制关联关系   * 如果俩者都是引用对象,且多对多的关系,可以随意   *   */  //控制关联关系  class Order{  Custommer custommer;public Custommer getCustommer() {return custommer;}public void setCustommer(Custommer custommer) {//同时更新反向指针//this.custommer = custommer;if(this.custommer!=null){this.custommer.friendOrders().remove(this);this.custommer = custommer;}if(this.custommer != null){this.custommer.friendOrders().add(this);}}    }class Custommer{private Set orders = new HashSet<>();//辅助函数Set friendOrders(){return orders;}//调用控制函数void addOrder(Order order){order.setCustommer(this);}}            //控制关联关系  class Order{  Custommer custommer;public Custommer getCustommer() {return custommer;}void addCustomer(Custommer custommer){custommer.friendOrders().add(this);this.custommer.add(custommer);}void removeCustomer(Custommer custommer){custommer.friendOrders().remove(this);this.custommer.remove(custommer);}    }class Custommer{private Set orders = new HashSet<>();//辅助函数Set friendOrders(){return orders;}public void add(Custommer custommer) {}public void remove(Custommer custommer) {}public void removeOrder(Order order) {order.removeCustomer(this);}public void addOrder(Order order) {order.addCustomer(this);}
8.将双向关联改为单向关联
9. 常量取代数字
有时候使用一个固定的数值并不是太好,最好使用建立一个常量,取一个有意思的名字来替换这个常量。
double circleArea(int redius) {    return 3.14 * redius * redius}更改为↓double circleArea(int redius) {    return pi * redius * redius;}public final double pi = 3.14;
10.封装字段
把字段设为private,并提供访问函数。

public String name;private String name;public void setName(String name){     this.name = name;}public String getName{     return name;}
11.封装集合
12.以数据类取代记录
做法:
新建一个类,表示这个记录
对于记录中的每一个数据,在新建的类中建立对应的一个private字段,提供取值设值函数
13.以类取代类型码
做法:
为类型码建立一个类
修改源类,使用新建的类
用新函数使用新建的类
范例:

class Persion{//  public static final int O = 0;//  public static final int A = 1;//  public static final int B = 2;//  public static final int AB = 3;//  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 int bloodGroup;  private BloodGroup bloodGroup;//public Persion(int bloodGroup) {////this.bloodGroup = bloodGroup;//this.bloodGroup = BloodGroup.code(bloodGroup);//}//public int getBloodGroup() {//public int getBloodGroupCode(){////return bloodGroup;//return this.bloodGroup.getCode();//}//新的取值函数public BloodGroup getBloodGroup(){return this.bloodGroup;}//建立新的构造函数和设值public Persion (BloodGroup bloodGroup){this.bloodGroup = bloodGroup;}public void setBloodGroup(BloodGroup bloodGroup){this.bloodGroup =bloodGroup;}//public void setBloodGroup(int bloodGroup) {////this.bloodGroup = bloodGroup;//this.bloodGroup = BloodGroup.code(bloodGroup);//}    }   //建立新类表示血型  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 final int code;public BloodGroup(int code) {this.code = code;}private int getCode() {return code;}  private static BloodGroup code(int arg){return values[arg];}  }
14 以子类取代类型码
范例:
public abstract class Employee {   private int type;static final int ENGINEER = 0;static final int SALESMAN = 1;static final int MANAGER = 2;public Employee(int type) {this.type = type;}//自封装字段abstract int getType();//工厂函数static Employee create(int type){//return new Employee(type);//if(type == ENGINEER) return new Engineer();//else return new Employee(type);switch (type) {case ENGINEER:return new Engineer();case SALESMAN:return new SALESMAN();case MANAGER:return new MANAGER();}}}  public class Engineer extends Employee{public Engineer(int type) {super(type);}int getType(){return Employee.ENGINEER;}}
做法:
使用自封装字段封装类型码,如果类型码被传递给构造函数,要把构造函数换成工厂函数
为类型码的每个值建立相应的子类,每个子类中覆写类型码的取值函数,返回相应的类型码值

15.以state/strategy取代类型码
做法:
使用自封装字段封装类型码
建类,根据类型码的用途命名,这是状态对象
为新类建子类,每个子类对应一种类型码
超类中建立抽象的查询函数,用以返回类型码,子类中覆写
源类中建个字段保存新建的状态对象
调整源类中为类型码设值的函数,将一个恰当的状态对象子类赋值给保存状态对象的那个字段
范例:

public abstract class Employee {   private int type;static final int ENGINEER = 0;static final int SALESMAN = 1;static final int MANAGER = 2;private EmployeeType employeeType;Employee(int type) {this.type = type;}int getType(){//return this.type;return employeeType.getTypeCode();}void setType(int arg){employeeType = EmployeeType.newType(arg);}//void setType(int arg){//switch (arg) {//case ENGINEER://employeeType = new Engineer();//default://throw new RuntimeException("Incorrect Employee");//}//}int payAmount(){switch (getType()) {case EmployeeType.ENGINEER:return monthlySalary;case EmployeeType.SALESMAN:return monthlySalary + commission;case EmployeeType.MANAGER:return monthlySalary + bonus;default:throw new RuntimeException("Incorrect Employee");}}}  public abstract class EmployeeType {static final int ENGINEER = 0;static final int SALESMAN = 1;static final int MANAGER = 2;abstract int getTypeCode();static EmployeeType newType(int code){switch (code) {case ENGINEER:return  new Engineer();default:throw new RuntimeException("Incorrect Employee");}}}public class Engineer extends EmployeeType{@Overrideint getTypeCode() {return Employee.ENGINEER;}}
16.以字段取代子类
做法:
对所有子类使用以工厂函数取代构造函数
引用子类改为引用超类
针对每个常量函数,在超类中声明一个final字段
为超类声明一个protected构造函数,用以初始化这些字段
新建或修改子类构造函数,使它调用超类的新增构造函数
将子类构造函数内联到超类的工厂函数中
范例:
public abstract class Persion {abstract boolean isMale();abstract char getCode();}public class Male extends Persion{@Overrideboolean isMale() {return true;}@Overridechar getCode() {return 'M';}} public class Female extends Persion{@Overrideboolean isMale() {return false;}@Overridechar getCode() {return 'F';}}改为public abstract class Persion {//为每个常量函数声明对应的字段private final boolean isMale;private final char code;protected Persion(boolean isMale, char code) {this.isMale = isMale;this.code = code;}//abstract boolean isMale();//abstract char getCode();//建立工厂函数static Persion createMale(){return new Male(true,'M');}static Persion createFemale(){return new Male(false,'F');}public class Male extends Persion{protected Male(boolean isMale, char code) {super(true, 'M');}//@Override//boolean isMale() {//return true;//}//@Override//char getCode() {//return 'M';//}} public class Female extends Persion{protected Female(boolean isMale, char code) {super(false, 'F');}//@Override//boolean isMale() {//return false;//}//@Override//char getCode() {//return 'F';//}}