[译言网]在“Hello World!”中滥用的设计模式

关于设计模式,我觉得一个软件工程领域的准则特别适用:No Silver Bullet——没有银弹。

设计模式越来越多的走向神坛,和MVC概念一样,简单的东西变得越来越复杂,在开发变得越来越庞大的同时,

需要记住,简洁也是一种美。

下文是译言网的一篇文章,指出了设计模式的滥用,

当设计模式变得流行后,我在一个新闻组看到一条评论,指出人们想在一个程序中用尽 23 个 GoF 设计模式。

他们说那些人失败了,因为他们只能使用 20 个。他们希望客户能让他们再编编所以他们也许能再挤进去另外 3 个。
尝试把所有模式都用上是不好的,因为你会以一个需要猜测设计方式而且拥有任何人都不需要的灵活性结束。近来的软件都太复杂,我们不能承受猜测模块功能的代价。我们需要专注到它们要干的事情。- Erich Gamma [1]
当人们开始学习设计模式,他们尝试把模式套用在任何地方,他们不管是否需要这个设计模式,因为他们认为模式越多,设计越好。而结果是一团不必要地复杂的代码。[2]
其实称呼他们为“滥用模式”比“使用模式”更合适。这里就有一个当人们想把模式塞到“你好世界!”(Hello World)程序的例子。
让我们专注于这个例子。这个问题很经典:写一个在标准输出打印“你好世界!”的程序(在 Java 中):

System.out.println("hello world");

代码看起来太简单了。让我们能不能用用几个设计模式?
看看……
首先我们定义两个接口对象和监听器来增加监听器。

public interface Subject {

public void attach(Observer observer);

public void detach(Observer observer);

public void notifyObservers();

}

public interface Observer {

public void update(Subject subject);

}

再定义 HelloWorldSubject 和 HelloWorldObserver 然后实现它们。

private ArrayList<Observer> observers;

private String str;

public HelloWorldSubject() {

super();

observers = new ArrayList<Observer>();

}

public void attach(Observer observer) {

observers.add(observer);

}

public void detach(Observer observer) {

observers.remove(observer);

}

public void notifyObservers() {

Iterator<Observer> iter = observers.iterator();

while (iter.hasNext()) {

Observer observer = iter.next();

observer.update(this);

}

}

public String getStr() {

return str;

}

public void setStr(String str) {

this.str = str;

notifyObservers();

}

}

  

public class HelloWorldObserver implements Observer {

public void update(Subject subject) {

HelloWorldSubject sub = (HelloWorldSubject)subject;

System.out.println(sub.getStr());

}

}

然后我们增加一个命令。

public interface Command {

void execute();

}

public class HelloWorldCommand implements Command {

private HelloWorldSubject subject;

public HelloWorldCommand(Subject subject) {

super();

this.subject = (HelloWorldSubject)subject;

}

public void execute() {

subject.setStr("hello world");

}

}

然后我们增加一个抽象工厂。

public interface AbstractFactory {

public Subject createSubject();

public Observer createObserver();

public Command createCommand(Subject subject);

}

public class HelloWorldFactory implements AbstractFactory {

public Subject createSubject() {

return new HelloWorldSubject();

}

public Observer createObserver() {

return new HelloWorldObserver(); 

}

public Command createCommand(Subject subject) {

return new HelloWorldCommand(subject);

}

}

然后最后地,一个单件。

public class FactoryMakerSingleton {

private static FactoryMakerSingleton instance = null;

private AbstractFactory factory;

private FactoryMakerSingleton() {

factory = new HelloWorldFactory();

}

public static synchronized FactoryMakerSingleton getInstance() {

if (instance == null) {

instance = new FactoryMakerSingleton();

}

return instance;

}

public AbstractFactory getFactory() {

return factory;

}

}

最后是主类。

public class AbuseDesignPatterns {

public static void main(String[] args) {

AbstractFactory factory = FactoryMakerSingleton.getInstance().getFactory();

Subject subject = factory.createSubject();

subject.attach(factory.createObserver());

Command command = factory.createCommand(subject);

command.execute();

}

}

然后输出:
Hello World             
哇,我们在 Hello World 中用了四个设计模式耶!(好吧,其实还有一个迭代器,但我们使用了 Java 的内建迭代器)这一定是一个优秀的设计! 但存在什么问题?
对 Hello World 程序,它太复杂。
它包含了我们不可能需要的灵活性。
设计和实现它是彻底的对时间的浪费。
它违反了 KISS 原则。[3]
它没有围绕问题的目标制作。原来的初衷是学习在标准输出上打印而这些代码已经离他们太远。
总结:自然地使用设计模式,不要滥用用他们。设计模式对设计卓越软件很有用。明智而不滥用地使用他们。

参考来自:

[1] How to Use Design Patterns.

[2] Chapter 13: Patterns in the Real World from Head First Design Patterns

[3] KISS Principle.

你可能感兴趣的:(Hello world)