问题来源
我们在进行软件系统设计的时候,有一些业务(如下图,一些通用的非功能性需求)是多个模块都需要的,是跨越模块的。把它们放到什么地方呢?
最简单的办法就是把这些通用模块的接口写好,让程序员在实现业务模块的时候去调用。
这样做的缺点是,日志、安全、事务、统计性能等相关代码几乎把真正的业务代码淹没了。重复的代码会变得非常多。
设计模式:模板方法
调用方式很简单:
BaseCommand cmd = new PlaceOrderCommand(xxx);
cmd.execute();
子类变得很清爽,只需要关注业务逻辑就可以了。
这种方式的巨大缺陷是:父类会定义一切。要定义哪些非功能性代码、执行顺序,子类都只能无条件接受。如果有一个子类,根本不需要某个功能,也无法去掉。
设计模式:装饰器模式
现在让这个 PlaceHolderCommand
能够打印日志,进行性能统计:
Command cmd = new LoggerDecorator(new PerformanceDecorator(new PlaceOrderCommand()));
cmd.execute();
如果 PaymantCommand
只需要打印日志,那么装饰一次就可以了。
Command cmd = new LoggerDecorator(new PaymentCommand());
cmd.execute();
可以使用任意数量的装饰器,还可以以任意次序执行,是不是很灵活?