前言
本文内容选自Java核心技术卷1 第10版,感兴趣的小伙伴可以自行阅读原书,以下内容为本人学习后摘取的片段与大家分享。
正文
4.10 类设计技巧
我们不会面面俱到,也不希望过于沉闷,所以这一章结束之前,简单地介绍几点技巧。应用这些技巧可以使得设计出来的类更具有 OOP 的专业水准。
- 一定要保证数据私有
这是最重要的;绝对不要破坏封装性。有时候,需要编写一个访问器方法或更改器方法,但是最好还是保持实例域的私有性。很多惨痛的经验告诉我们, 数据的表示形式很可能会改变, 但它们的使用方式却不会经常发生变化。当数据保持私有时,它们的表示形式的变化不会对类的使用者产生影响,即使出现 bug 也易于检测。
为什么一定要保证数据私有呢?
举个栗子,一个涉及到加密算法的类,其中具有公钥私钥属性。我们可以通过公钥私钥再经过加密算法生成结果,这个结果是不会被破解的,所以我们可以允许其他类拿到这个结果,但是公钥和私钥不允许暴露,所以也就不能设置为public。如果被拿到了,那我们提供的这个结果就没有任何意义,因为其他人同样可以根据算法生成一致的结果。
- 一定要对数据初始化
Java 不对局部变量进行初始化, 但是会对对象的实例域进行初始化。最好不要依赖于系统的默认值,而是应该显式地初始化所有的数据,具体的初始化方式可以是提供默认值,也可以是在所有构造器中设置默认值。
- 不要在类中使用过多的基本类型
就是说,用其他的类代替多个相关的基本类型的使用。这样会使类更加易于理解且易于修改。例如,用一个称为 Address 的新的类替换一个 Customer 类中以下的实例域:
private String street;
private String city;
private String state;
private int zip;
这样,可以很容易处理地址的变化,例如, 需要增加对国际地址的处理。
- 不是所有的域都需要独立的域访问器和域更改器
或许, 需要获得或设置雇员的薪金。而一旦构造了雇员对象,就应该禁止更改雇用日期,并且在对象中,常常包含一些不希望别人获得或设置的实例域,例如,在 Address 类中,存放州缩写的数组。
- 将职责过多的类进行分解
这样说似乎有点含糊不清, 究竟多少算是“ 过多” ? 每个人的看法不同。但是,如果明显地可以将一个复杂的类分解成两个更为简单的类,就应该将其分解(但另一方面,也不要走极端。设计 10 个类,每个类只有一个方法,显然有些矫枉过正了)。
下面是一个反面的设计示例。
public class CardDeck // bad design
{
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 类实际上是一个用于描述时间的类)。
命名类名的良好习惯是采用一个名词(Order )、前面有形容词修饰的名词( RushOrder )或动名词(有“ -ing” 后缀)修饰名词(例如, BillingAddress)。对于方法来说,习惯是访问器方法用小写 get 开头 ( getSalary ), 更改器方法用小写的 set 开头(setSalary )
指路https://www.cnblogs.com/liqiangchn/p/12000361.html
你或许可以从这篇文章学习到绝大部分的命名规则。
- 优先使用不可变的类
LocalDate 类以及 java.time 包中的其他类是不可变的—没有方法能修改对象的状态。类似 plusDays 的方法并不是更改对象,而是返回状态已修改的新对象。
更改对象的问题在于, 如果多个线程试图同时更新一个对象,就会发生并发更改。其结果是不可预料的。如果类是不可变的,就可以安全地在多个线程间共享其对象。
因此,要尽可能让类是不可变的,这是一个很好的想法。对于表示值的类,如一个字符串或一个时间点,这尤其容易。计算会生成新值, 而不是更新原来的值。
当然,并不是所有类都应当是不可变的。如果员工加薪时让 raiseSalary 方法返回一个新的 Employee 对象,这会很奇怪。
指路https://cloud.tencent.com/developer/article/1477314
这篇博文会帮助你如何使用不可变类
标签:选读,Java,int,private,对象,方法,public,第四章 From: https://www.cnblogs.com/jwcat313/p/18615655本章介绍了 Java 这种面向对象语言的有关对象和类的基础知识。 为了真正做到面向对象,程序设计语言还必须支持继承和多态。Java 提供了对这些特性的支持,具体内容将在下一章中介绍。