Effective Java讀書筆記(四)
阿新 • • 發佈:2019-02-05
介面優於抽象類
骨架實現:通過對匯出的每個重要介面都提供一個抽象的骨架實現類,把介面和抽象類的優點結合起來。
- 研究介面,並確定哪些方法是最為基本的,其他的方法可以根據它們來實現。這些方法將成為骨架實現類中的抽象方法。
- 為介面中的所有其他方法提供具體實現。
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域被匯出,其型別為該策略介面。
優先考慮靜態成員類
如果宣告成員類不要求訪問外圍例項,就要把它宣告為靜態成員類。