合理使用设计模式

文章目录

半吊子水平的设计模式理解 + 糟糕的抽象 + 多重继承 = 灾难。

最近接触很多项目,深感设计模式给项目带来的痛苦,比如:

  1. 不必要的接口。
  2. 不必要的池化。

首先是接口。设计合理的接口对程序员的能力要求很高,这需要很完备的顶层设计,建模能力、前瞻能力都需有。可我在现实中看到更多的是:接口更多被用来当做表征 feature 了(虽然这也是接口表达的初衷),不管什么业务类,都会先去做如下定义:

1
2
3
4
5
6
7
8
9
public interface Aaa {
void m();
}

public class AaaImpl implements Aaa {
public void m() {
...
}
}

接口 Aaa 可能还会有两到三层继承,还有可能有嵌套。天,有时候这种接口 + 搭配动态代理/注入,看代码的时候必须要层层深入,找到这个接口实现类最终的注入点,劳神费心。让我们来回顾一下接口的定义:

在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

抽象,抽象,抽象!

然后是池化。可能很多人受 Spring的依赖注入影响太深,总觉得只要是实例化,必须要来个容器装一装,亲,可以理解你对实例化的恐惧,可是在程序整个的运行生命周期内,总共才实例化一两次对象,为啥不当成一个全局属性用呢?各种 XXXContainer、XXXHolder 满天飞,真是画虎不成反类犬。对了,我不反对延迟加载(Lazy Loading),可我反对对延迟加载理念的过度吹捧,譬如单例分为懒汉和饿汉模式:

方法1:

1
2
3
4
5
6
7
8
9
10
11
// 利用类加载
public class Singleton {

private final static Singleton INSTANCE = new Singleton();

private Singleton(){}

public static Singleton getInstance(){
return INSTANCE;
}
}

方法2:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 也是利用类加载(会加锁),同时有 Lazy-Loading 的作用
public class Singleton {

private Singleton() {}

private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}

我就喜欢第一种,原因很简单:就是因为 简单 + 高效 + 好理解。顺便提一句,我面试过好多人,让写单例模式,写的都是第二种,可当我问及为何利用类加载就可以保证单例的时候,绝大多数都没答上来。

我如此反感接口滥用、五六层继承、池化滥用、工厂模式滥用等现象的原因很简单: 为了炫技却给丧失了代码的简洁性和可读性。

当然,很多开源框架的代码设计,读起来还是挺舒服的,比如 Spring,Redis,ZK,Kubernetes 除外,后者也存在一定程度上的过度设计之嫌。