青雲的博客

Article

创建型设计模式总结

· 5 分钟阅读

单例、工厂、抽象工厂、建造者、原型——这五个模式都被归进”创建型”,但它们解决的问题并不一样。五个一起背下来,遇到具体问题时反而挑不出来。

这篇不重复各自的实现(每个模式都有单独一篇),只做一件事:把”创建对象”这件事拆成几种不同的麻烦,看每种该找谁。

创建对象的代码,通常是这样变难维护的

第一种:调用方不该知道具体用哪个类。 业务代码里散落着 new,换一个实现就要翻遍所有调用点。这时候要的不是”更好的 new”,而是把创建这个动作本身挪走——这是工厂

第二种:这个对象要分好几步才装得起来。 构造函数参数列表越来越长,还都是可选的,调用方开始靠位置记忆参数含义。这时候需要把”怎么装”和”装成什么”分开——这是建造者

第三种:全局只该有一个,或者复制比新建划算。 前者是单例,后者是原型。这两个容易和前面混,但它们的出发点不是”解耦创建过程”,而是”控制实例的数量和来源”。

按麻烦排的对照表

你的麻烦该用的模式它把什么挪走了代价
调用方不该知道具体类工厂new 收进一个创建入口多一层间接,类数量增加
要成套地换产品系列抽象工厂一族产品的创建集中到一个接口增加新的产品种类很别扭
构造步骤多、组合多变建造者把构建过程与最终表示分离多写一个建造者类,简单对象上显得啰嗦
全局只能有一个实例单例把构造封起来,只留取实例的入口依赖被藏进全局,测试难并行
新建比复制贵原型用克隆代替构造深拷贝的边界要自己处理

最容易混的两组

工厂 vs 抽象工厂。 工厂解决的是”用哪一个类”,一次决定一个产品;抽象工厂解决的是”用哪一套类”,一次决定一族产品。判断方法很简单:如果新增一个产品种类时你希望只加一个类,用工厂;如果新增一个产品系列时你希望只加一个类,用抽象工厂。反过来加,都会别扭。

单例 vs 原型。 两者都在控制实例的来源,但方向相反:单例把入口收到唯一一处,原型把入口放开成”从现有对象复制”。前者怕的是多,后者怕的是贵。一个模块里同时用这两个模式,通常说明实例的生命周期没想清楚。

逐个展开

选哪个模式,最终取决于你把哪一部分当成了变化点。想清楚这一点,上面这张表其实可以不看。


同属创建型模式:工厂单例建造者原型。全部篇目见设计模式标签页。

Keep Reading

相关文章

评论