• 重构改善既有代码的设计-处理概括关系


    有一批重构手法专门用来处理类的概括关系,即继承关系。其中主要是将函数上下移动于继承体系之中。

    1、Pull Up Field(字段上移)

    两个子类拥有相同的字段。将该字段移至超类。

    2、Pull Up Method(函数上移)

    有些函数,在各个类中产生完全相同的结果。将该函数移至超类。

    3、Pull Up Constructor Body(构造函数本体上移)

    你在各个子类中拥有一些构造函数,它们本体几乎完全一致。在超类中新建一个构造函数,并在子类构造函数中调用它。

    代码1

    class Manager extends Employee...

    public Manager(String name, String id, int grade){

    _name = name;

    _id = id;

    _grade = grade;

    }

    代码2

    public Manager(String name, String id, int grade){

    super(name, id);

    _grade = grade;

    }

    4、Push Down Method(函数下移)

    超类中的某个函数只与部分(而非全部)子类有关。将这个函数移到相关的那些子类去。

    5、Push Down Field(字段下移)

    超类中的某个字段只被部分(而非全部)子类用到。将这个字段移到需要它的那些子类去。

    6、Extract Subclass(提炼子类)

    类中的某些特性只被某些(而非全部)实例用到。新建一个子类,将上面所说的那一部分特性移到子类中。

    7、Extract Superclass(提炼超类)

    两个类有相似特性。为这两个类建立一个超类,将相同特性移至超类。

    8、Extract Interface(提炼接口)

    若干客户使用类接口中的同一子集,或者两个类的接口有部分相同。将相同的子集提炼到一个独立接口中。

    9、Collapse Hierarchy(折叠继承体系)

    10、Form Template Method(塑造模板函数)

    动机:你有一些子类,其中相应的某些函数以相同顺序执行类似的操作,但各个操作的细节上有所不同。

    做法:将这些操作分别放进独立函数中,并保持它们都有相同的签名,于是原函数也就变得相同。然后将原函数上移至超类。

    代码1

    class Customer {
     
    public String statement(){
    return new TextStatement().value(this);
    }
    public String htmlStatement(){
    return new HtmlStatement().value(this);
    }
    }
     
    class TextStatement{
    public String value(Customer aCustomer){
    Enumeration<e> rentals = aCustomer.getRentals();
    String result = "Rental Record for " + aCustomer.getName() + "
    ";
    while(rentals.hasMoreElements()){
    Rental each = (Rental) rentals.nextElement();
    //show figures for this rental
    result += "	" + each.getMovie().getTitle() + "	"
    + String.valueOf(each.getCharge()) + "
    ";
    }
    //add footer lines
    result += "Amount owed is "
    + String.valueOf(aCustomer.getTotalCharge()) + "
    ";
    result += "You earned "
    + String.valueOf(aCustomer.getTotalFrequentRenterPoints())
    + " frequent renter points";
    return result;
    }
    }
     
    class HtmlStatement {
    public String value(Customer aCustomer){
    Enumeration<e> rentals = aCustomer.getRentals();
    String result = "<H1>Rental Record for <EM>" + aCustomer.getName()
    + "</EM></H1><P>
    ";
    while(rentals.hasMoreElements()){
    Rental each = (Rental) rentals.nextElement();
    //show figures for this rental
    result += each.getMovie().getTitle() + ":"
    + String.valueOf(each.getCharge()) + "<BR>
    ";
    }
    //add footer lines
    result += "<P>You owed <EM>"
    + String.valueOf(aCustomer.getTotalCharge()) + "</EM><P>
    ";
    result += "On this rental you earned <EM> "
    + String.valueOf(aCustomer.getTotalFrequentRenterPoints())
    + "</EM> frequent renter points<P>";
    return result;
    }
    }

    代码2:将上面两个类中不同的地方抽出来,分别放进独立函数中。

    class TextStatement{
    String headerString(Customer aCustomer){
    return "Rental Record for " + aCustomer.getName() + "
    ";
    }
    String eachRentalString(Rental aRental){
    return "	" + aRental.getMovie().getTitle() + "	"
    + String.valueOf(aRental.getCharge()) + "
    ";
    }
    String footerString(Customer aCustomer){
    return "Amount owed is "
    + String.valueOf(aCustomer.getTotalCharge()) + "
    "
    +"You earned "
    + String.valueOf(aCustomer.getTotalFrequentRenterPoints())
    + " frequent renter points";
    }
    public String value(Customer aCustomer){
    Enumeration<e> rentals = aCustomer.getRentals();
    String result = headerString(aCustomer);
    while(rentals.hasMoreElements()){
    Rental each = (Rental) rentals.nextElement();
    //show figures for this rental
    result += eachRentalString(each);
    }
    //add footer lines
    result += footerString(aCustomer);
    return result;
    }
    }
     
    class HtmlStatement {
    String headerString(Customer aCustomer){
    return "<H1>Rental Record for <EM>" + aCustomer.getName()
    + "</EM></H1><P>
    ";
    }
    String eachRentalString(Rental aRental){
    return aRental.getMovie().getTitle() + ":"
    + String.valueOf(aRental.getCharge()) + "<BR>
    ";
    }
    String footerString(Customer aCustomer){
    return "<P>You owed <EM>"
    + String.valueOf(aCustomer.getTotalCharge()) + "</EM><P>
    "
    + "On this rental you earned <EM> "
    + String.valueOf(aCustomer.getTotalFrequentRenterPoints())
    + "</EM> frequent renter points<P>";
    }
    public String value(Customer aCustomer){
    Enumeration<e> rentals = aCustomer.getRentals();
    String result = headerString(aCustomer);
    while(rentals.hasMoreElements()){
    Rental each = (Rental) rentals.nextElement();
    //show figures for this rental
    result += eachRentalString(each);
    }
    //add footer lines
    result += footerString(aCustomer);
    return result;
    }
    }

    代码3:经过第二步处理,我们将相同的函数提炼到超类中。函数内容不同提炼为抽象类。

    abstract class Statement{
    abstract String headerString(Customer aCustomer);
    abstract String eachRentalString(Rental aRental);
    abstract String footerString(Customer aCustomer);
    public String value(Customer aCustomer){
    Enumeration<e> rentals = aCustomer.getRentals();
    String result = headerString(aCustomer);
    while(rentals.hasMoreElements()){
    Rental each = (Rental) rentals.nextElement();
    //show figures for this rental
    result += eachRentalString(each);
    }
    //add footer lines
    result += footerString(aCustomer);
    return result;
    }
    }


    第四步:TextStatement、HtmlStatement 继承Statement,并实现抽象函数。

    11、Replace Inheritance with Delegation(以委托取代继承)

    动机:某个子类只使用接口中的一部分,或是根本不需要继承而来的数据。

    代码1:只要看看MyStack的用户,我就会发现,用户只要它做4件事:push()pop()size()isEmpty()。后两个函数就是从Vector继承来的。

    class MyStack extends Vector{

    public void push(Object element){

    insertElementAt(element, 0);

    }

    public Object pop(){

    Object result = firstElement();

    removeElementAt(0);

    return result;

    }

    }

    代码2:跟封装模式有点类似,只不过只封装了需要用到的函数。

    class MyStack{

    private Vector _vector = new Vector();

    public void push(Object element){

    _vector.insertElementAt(element, 0);

    }

    public Object pop(){

    Object result = _vector.firstElement();

    _vector.removeElementAt(0);

    return result;

    }

    public int size(){

    return _vector.size();

    }

    public boolean isEmpty(){

    return _vector.isEmpty();

    }

    }

    12、Replace Delegation with Inheritance(以继承取代委托)

    动机:需要用到受委托类的所有函数。

  • 相关阅读:
    作用域随笔
    关于取数组地址的识记(&s+1,s+1,&s[0]+1)
    c中关于#与##的简易使用
    Qt Creator的配置
    sizeof对int long double char的使用
    i++与++i的区别
    for循环执行顺序
    gcc 编译的4个过程简单识记
    各进制之间转化识记
    删除临时文件
  • 原文地址:https://www.cnblogs.com/kuyuyingzi/p/4266259.html
Copyright © 2020-2023  润新知