1. 程式人生 > >Effective Java讀書筆記(四)

Effective Java讀書筆記(四)

介面優於抽象類

骨架實現:通過對匯出的每個重要介面都提供一個抽象的骨架實現類,把介面和抽象類的優點結合起來。

  1. 研究介面,並確定哪些方法是最為基本的,其他的方法可以根據它們來實現。這些方法將成為骨架實現類中的抽象方法。
  2. 為介面中的所有其他方法提供具體實現。
public abstract class AbstractMapEntry<K, V> implements Map.Entry<K, V> {
    // Primitive operations
    public abstract K getKey();
    public abstract V getValue
(); // Entries in modifiable maps must override this method public V setValue(V value) { throw new UnsupportedOperationException(); } // Implements the general contract of Map.Entry.equals @Override public boolean equals(Object o){ if(o == this) return true
; if(! (o instanceof Map.Entry)) return false; Map.Entry<?,?> arg = (Map.Entry) 0; return equals(getKey(), arg.getKey()) && equals(getValue(), arg.getValue()); } private static boolean equals(Object o1, Object o2){ return
o1 == null ? o2 == null : o1.equals(o2); } // Implements the general contract of Map.Entry.hashCode @Override public int hashCode() { return hashCode(getkey()) ^ hashCode(getValue()); } private static int hashCode(Object obj){ return obj == null? 0 : obj.hashCode(); } }

介面只用於定義型別

如果要匯出常量,可以有幾種合理的選擇方案。如果這些常量與某個現有的類或者介面緊密相關,就應該把這些常量新增到這個類或者介面中。如果這些常量最好被看做美劇型別的成員,就應該用列舉型別來匯出這些常量。否則應該使用不可例項化的工具類來匯出這些常量。

public class PhysicalConstants {
    private PhysicalConstants(){}

    public static final double AVOGADROS_NUMBER = 6.02214199Ee23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS = 9.10938188E-31;
}

如果大量利用工具類匯出的常量,可以通過利用靜態匯入的機制,避免用類名來修飾常量名。

public class Test {
    double atoms(double mols) {
        return AVOGADROS_NUMBER * mols;
    }
    ...
    // Many more uses of PhysicalConstants justify static import
}

類層次優於標籤類

標籤類:

// Tagged class - vastly interior to a class hierarchy!
class Figure {
    enum Shape{ RECTANGLE, CIRCLE };

    // Tag field - the shape of this figure
    final Shape shape;

    // These fields are used only if shape is RECTANGLE
    double length;
    double width;

    // This field is used only if shape is CIRCLE
    double radius;

    // Constructor for circle
    Figure(double radius){
        shape = Shape.CIRCLE;
        this.radius = radius;
    }

    Figure(double length, double width) {
        shape = Shape.RECTANGLE;
        this.length = length;
        this.width = width;
    }

    double area() {
        switch(shape) {
            case RECTANGLE:
                return length * width;
            case CIRCLE:
                return Math.PI * (radius * radius);
            default:
                throw new AssertionError();
        }
    }
}
// Clas hierarchy replacement for a tagged class
abstract class Figure {
    abstract double area();
}

class Circle extends Figure {
    final double radius;

    Circle(double radius) { this.radius = radius; }

    double area() { return Math.PI * (radius * radius) }
}

class Rectangle extends Figure {
    final double length;
    final double width;

    Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }

    double area() { return length * width }
}

用函式物件表示策略

要實現策略模式,要宣告一個介面來表示該策略,並且為每一個具體策略宣告一個實現了該介面的類。當一個具體策略只被使用一次時,通常使用匿名類來宣告和例項化這個具體策略類。當一個具體策略類是設計用來重複使用的時候,它的類通常就要被時限為私有的靜態成員類,並銅鼓歐公有的靜態final域被匯出,其型別為該策略介面。

優先考慮靜態成員類

如果宣告成員類不要求訪問外圍例項,就要把它宣告為靜態成員類。