如何写出好的 Java程序 —— 浅谈 API 设计
很多童鞋觉得写 Java 很简单,只要能写出功能来,效果能实现就好。还有一些培训机构,专门教人写各种“炫酷特效”,以此让许多人觉得这些培训很“牛逼”。然而事实上,能写 Java 和写好 Java 这中间还有很遥远的距离。成为专业,注定在 Java 路途上需要一步步扎实的修炼,没有捷径。
实现一个类似于“交通灯”的效果,让三个不同颜色(红、绿、黄)的圆点每隔 2 秒循环切换。
版本一
有的童鞋说,这个实现还不简单嘛?直接用几个定时器一下切换不就好了:
while (true) {
System.out.println("黄灯,等待。。。"+new Date());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("红灯,停止。。。"+new Date());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("绿灯,通行。。。"+new Date());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
没错,就这个功能本身,这样实现就 OK 了。但是这样实现有什么问题呢?
首先是过程耦合,状态切换是黄灯->红灯->绿灯 循环,在上面的设计里,实际上操作顺序是耦合在一起的,要先 ‘黄灯’,然后等待 2000 毫秒再 ‘红灯’,然后再等待 2000 毫秒在 ‘绿灯’,这中间的顺序一旦有调整,需求有变化,代码都需要修改。
如果需求不是三盏灯,而是五盏灯、十盏灯呢。
所以我们说,版本一方法虽然直接,但因为抽象程度很低(几乎没有提供任何抽象 API),它的扩展性很不好。如果只能写这样的代码,是不能说就写好了 Java 的。
版本二
将状态[‘黄灯’,’红灯’,’绿灯 ‘]抽象出来:
String[] lights = { "黄灯", "红灯", "绿灯" };
int i = 0;
while (true) {
System.out.println(lights[i]+"。。。" + new Date());
try {
Thread.sleep(2000);
i++;
if(i == 3){
i = 0;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
这一版本比前一版本要好很多,但是它也有问题,最大的问题就是封装性很差,它把 lights 和 i都暴露出来了,而且以全局变量的形式,这么做很不好,需要优化。
版本三
版本三是中规中矩的一版,也是一般我们在工作中比较常用的思路。应该将暴露出来的 API 暴露出来(本例中的 lights )。将不应该暴露出来的数据或状态隐藏(本例中的 i)。
有许多童鞋觉得说写出这一版本来已经很不错的。的确,应该也还不错,但这一版的抽象程度其实也不是很高,或者说,如果考虑适用性,这版已经很好了,但是如果考虑可复用性的话,这版依然有改进空间。
版本四
public static final int YELLOW=1;
public static final int RED=2;
public static final int GREEN=3;
static int lightControl=3;
public static void main(String[] args) {
while (true) {
changeLights();
}
}
private static void changeLights() {
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
change();
}
public static void change(){
if(lightControl == 1){
lightControl = 2;
}else if(lightControl == 2){
lightControl = 3;
}else if(lightControl == 3){
lightControl = 1;
}
print();
}
private static void print() {
if(lightControl == 1){
System.out.println("现在是黄灯!"+new Date());
}else if(lightControl == 2){
System.out.println("现在是红灯!"+new Date());
}else if(lightControl == 3){
System.out.println("现在是绿灯!"+new Date());
}
}
这一版用的是过程抽象的思路.
好了,上面我们有了四个版本,那么是否考虑了这些版本就足够了呢?
并不是。因为需求是会变更的。假设现在需求变化了:
需求变更:让 黄灯、红灯、绿灯 状态的持续时长不相等,分别改成 1秒、2秒、3秒。
那么,我们发现 ——
除了版本一之外,版本二、三、四全都跪了……
那是否意味着我们要回归到版本一呢?
当然并不是。
我们有版本五,版本五需开通vip可获取源码学习。
注意:需要本文源代码可加QQ490647751 回复关键字‘开通vip-如何写出好的 Java程序 —— 浅谈 API 设计’。
设计是把双刃剑,繁简需要权衡,尺度需要把握。
写代码简单,程序设计不易,需要走心。