更能获得 OOP 圈子承认的类的设计技巧:java
这是最重要的;绝对不要破坏封装性。有时候,可能须要编写一个访问器方法或更改器方法,可是最好仍是保持实例字段的私有性。不少惨痛的教训告诉咱们,数据的表示形式极可能会改变,但它们的使用方式却不会常常变化。当数据保持私有时,表示形式的变化不会对类的使用者产生影响,并且也更容易检测 bug。数组
Java 不会为你初始化局部变量,可是会对对象的实例字段进行初始化。最好不要依赖于系统的默认值,而是应该显式地初始化全部的数据,能够提供默认值,也能够在全部构造器中设置默认值。安全
这个想法是要用其余的类替换使用多个相关的基本类型。这样会使类更易于理解,也更于修改。例如,用一个名为 Address 的新类替换一个 Customer 类中一下的实例字段:
private String street;
private String city;
private String state;
private int zip;
这样一来,能够很容易地处理地址的变化,例如,可能须要处理国际地址。并发
你可能须要得到或设置员工的工资。而一旦构造了对象,确定不须要更改雇佣日期。另外,在对象中,经常包含一些不但愿别人得到或设置的实例字段,例如,Address 类中的州缩写数组。ide
这样说彷佛有点含糊,究竟多少算是“过多”?每一个人的见解都不一样。可是,若是明显地能够将一个复杂的类分解成两个更为简单的类,就应该将其分解(但另外一方面,也不要走极端,若是设计 10 个类,每一个类只有一个方法,显然就有些矫枉过正了)。ui
下面是一个反面的设计示例。线程
// 坏的设计 public class CardDeck { private int[] value; private int[] suit; public CardDeck() { ... } public void shuffle() { ... } public int getTopValue() { . . . } public int getTopSuit() { . . . } public void draw() { .. } }
实际上,这个类实现了两个独立的概念:一副牌(含有 shuffle 方法和 draw 方法)和一张牌(含有查看面值和花色的方法)。最好引入一个表示一张牌的 Card 类。如今有两个类,每一个类完成本身的职责:设计
public class CardDeck { private Card[] cards; public CardDeck() { ... } public void shuffle() { ... } public Card getTop() { ... } public void draw() { ... } } public class Card { private int value; private int suit; public Card (int aValue, int aSuit) { ... } public int getValue() { ... } public int getSuit() { ... } }
与变量应该有一个可以反映其含义的名字同样,类也应该如此(在标准类库中,也存在着一些含义不明确的例子,如 Date 类其实是一个用于描述时间的类 )。code
对此有一个很好的惯例:类名应当是一个名词(Order),或者是前面有形容词修饰的名词(RushOrder),或者是有动名词(有“ -ing” 后缀)修饰的名词(例如,BillingAddress)。对于方法来讲,要遵循的标准惯例:访问器方法用小写 get 开头,更改器方法用小写的 set 开头。对象
LocalDate 类以及 java.time 包中的其余类是不可变的——没有方法能修改对象的状态。相似 plusDays 的方法并非更改对象,而是返回状态已修改的新对象。
更改对象的问题在于,若是多个线程试图同时更新一个对象,就会发生并发更改。其结果是不可预料的。若是类是不可变的,就能够安全地在多个线程间共享其对象。
所以,要尽量让类是不可变的,这是一个很好的想法。对于表示值的类,如一个字符串或一个时间点,这尤为容易。计算会生成新值,而不是更新原来的值。
固然,并非全部类都应当是不可变的。若是员工加薪的方法返回一个新的员工对象,这会很奇怪。