2011年在金蝶,部门组织了一个培训,由一个资深的老前辈(纪大松)讲了一次23种设计模式,当时懵懵懂懂,对设计模式不屑一顾。如今时隔6年,忙里偷闲,我又将23种设计模式看了一遍,依然不屑一顾。6年前不屑一顾,其实是似懂非懂,如今不屑一顾,就真的是不屑一顾了。
说不屑一顾,并不是说设计模式没有屌用,反而,我对总结出这套理论的大牛们心存感激亦存尊重。我想表达的是,“设计”,“模式”这两个词看起来似乎很高大上,好像自己沾点边那就跟架构师乃至技术总监相隔不远了,但却并不如大家想象的那样遥远和高深。
我面过一些人,也被很多人面过,在面试java时设计模式是很常见的话题,很遗憾的是,几乎所有人讨论的都是设计模式本身,诸如:你用过哪些设计模式啊?原理什么样的?画个类图看看?使用场景有哪些?门面模式和代理模式有什么区别等等。我曾经遇见过一位同事,可以说是个技术面很广的人,你随便说个技术名词能跟你讲一大堆,23种设计模式你随便挑一个,他都能准确的帮你把概念,类图,优缺点,适用于哪些场景“背”出来。但是看过他的代码后,我很悲哀。
在我认为,真正懂得设计模式的人,是不需要去记那些繁琐的名词以及概念的,因为“设计模式”对他们来说是“不屑”的(除非他刻意去记)。因为:
1.设计模式只是一些优秀经验的积累,
举个栗子:老板说要模拟一个小孩哭的场景,这小孩一哭就哇哇哇。
报告老板,写完了。
public class Baby {
public void cry() {
System.out.println("wa wa wa!");
}
}
老板又说了,家里有条狗,小孩一哭,狗也跟着叫。
好吧,改一改,先加条狗:
public class Dog {
public void bark() {
System.out.println("汪汪汪!");
}
}
然后,小孩一哭,狗就跟着叫
public class Baby {
private Dog dog;
public void cry() {
System.out.println("哇哇哇!");
if (dog != null) dog.bark();
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
老板又说了,主人还养了猫,猫也跟着叫
好,再改
public class Cat {
public void bark() {
System.out.println("喵喵喵!");
}
}
public class Baby {
private Dog dog;
private Cat cat;
public void cry() {
System.out.println("哇哇哇!");
if (dog != null) dog.bark();
if (cat != null) cat.bark();
}
// getter and setter
}
老板又说了,还有鸡,鸡还不少,好多只。
如果你还认为要这样继续加下去我觉得你是一个不合格的程序猿,我相信大部分人肯定会寻思怎么改了,怎么更容易让老板的需求变得容易实现:
先抽象一个动物,dog和cat直接实现它
public interface Animal {
void bark();
}
public class Cat implements Animal {
public void bark() {
System.out.println("喵喵喵!");
}
}
public class Dog implements Animal {
public void bark() {
System.out.println("汪汪汪!");
}
}
然后改Baby
public class Baby {
private List animals = new ArrayList();
public void cry() {
System.out.println("哇哇哇!");
for (Animal animal : animals) {
animal.bark();
}
}
public void addAnimal(Animal animal) {
animals.add(animal);
}
// getter and setter
}
现在好了,老板,你家爱有多少动物就有多少吧。
我相信任何一个不懂设计模式的程序猿,稍微有些工作经验,只要有心优化这段代码,不想再被老板无休止得加动物而烦恼,这段代码写出来并不难,而这就是23种设计模式中的监听者模式。即使你连设计模式是什么也不知道,只要有心写上若干年,某天突然来看,你会发现,几乎所有的设计模式你都用过。
2.设计模式更多的只是一种思想,而不在于代码
再举个例子,还是小孩哭,小孩一哭妈妈就喂奶。某某对于设计模式非常“精通”,于是这样写:
public interface IMother {
void nurse();
}
public class Mother implements IMother {
public void nurse() {
System.out.println("乖宝宝别哭!");
}
}
public class Baby {
private List mothers = new ArrayList();
public void cry() {
System.out.println("哇哇哇!");
for (Mother mother : mothers) {
mother.nurse();
}
}
public void addMother(Mother mother) {
mothers.add(mother);
}
// getter and setter
}
不好意思,老板,作为一个老司机,你所有的需求变化都在我的预料之中,随便你怎么变,我都能满足你,因为我用了设计模式中的监听者模式!!
老板:你他妈脑袋有包,小孩能有几个妈???
spring mvc的controller,service类并没有要求写成单例模式,也没有写工厂,但是实际上这些类spring都是生成的单例,而且所有实例统一管控。这不正是单例模式和工厂模式的思想么?当你真正明白这些思想时,并不会拘泥于这些模式。
另外也说一点,真正好的设计,并不是基于你用了多少设计模式,而是基于你对当前业务和业务扩展性的理解,非要把一些不会扩展的地方写成松耦合,滥用设计模式,只会导致工作量增加和类泛滥!
所以,请所有的面试官们,如果你仍然为自己“懂”那么多设计模式而感觉高高在上,请停止你那些愚蠢的提问,因为很可能一个真正的程序猿就被你的无知给筛掉了。
设计模式体现在每一行追求完美的代码中,而我们无须追寻!
谨以此文献给那些总在力求让自己的代码更加优美,更加易于业务扩展的程序猿们。