前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Head First 设计模式》笔记

《Head First 设计模式》笔记

原创
作者头像
谛听
修改2020-09-07 14:27:55
1.1K1
修改2020-09-07 14:27:55
举报
文章被收录于专栏:巫山跬步巫山跬步

软件开发的一个不变真理:不管当初软件设计得多好,一段时间后,总是需要成长与改变,否则软件就会“死亡”。

1 OO 原则

虽然原则提供了方针,但在采用原则之前,必须全盘考虑所有的因素。

  1. 封装变化。
    • 把会变化的部分取出并封装起来,以便以后可以轻易地改动或扩充此部分,而不影响不需要变化的其它部分。
  2. 多用组合,少用继承。
    • 使用组合建立系统具有很大弹性,不仅可将算法族封装成类,更可以“在运行时动态地改变行为”,只要组合的行为对象符合正确的接口标准即可。
  3. 针对接口编程,不针对实现编程。
    • 指“针对超类编程”,意味着声明类时不用理会以后执行时的真正对象类型。
  4. 为交互对象之间的松耦合设计而努力。
    • 松耦合的设计之所以能让我们建立有弹性的 OO 系统,能够应对变化,是因为对象之间的互相依赖降到了最低。
  5. 类应该对扩展开放,对修改关闭。
    • 我们的目标是允许类容易扩展,在不修改代码的情况下,就可搭配新的行为。这样的设计具有弹性,可以应对改变,可以接受新的功能来应对改变的需求。
    • 每个地方都采用开放-关闭原则,是一种浪费,也没有必要,还会导致代码变得复杂且难以理解。
  6. 依赖抽象,不要依赖具体类。
    • 不能让高层组件依赖底层组件,而且不管高层或底层组件,“两者”都应该依赖于抽象。
  7. 最少知识原则:只和朋友交谈。
    • 在设计中,不要让太多的类耦合在一起,免得修改系统中的一部分,会影响到其它部分。
    • 会导致更多的“包装”类被制造出来,以处理和其它组件的沟通。
  8. 别找我,我会找你。
    • 将决策权放在高层模块中,以便决定如何以及合适调用低层模块。
    • 当高层组件依赖底层组件,而底层组件又依赖高层组件是,依赖腐败就会发生。换句话说,高层组件对待底层组件的方式是“别调用我们,我们会调用你”。
  9. 类应该只有一个改变的理由。
    • 类的每个责任都有改变的潜在区域。超过一个责任,意味着超过一个改变的区域。应尽量让每个类保持单一责任。
    • 区分设计中的责任是最困难的事情之一。我们的大脑习惯看着一大群的行为,然后将它们集中在一起,尽管它们可能属于多个不同的责任。想要成功的唯一方法,就是努力不懈地检查你的设计,随着系统的增长,随时观察没有迹象显示某个类改变的原因超出一个。

2 OO 模式

  1. 策略:封装可以互换的行为,并使用委托来决定要使用哪一个。
    • 定义:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
  2. 观察者:让对象能够在状态改变时被通知。
    • 定义:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
    • 让主题和观察者之间松耦合。
    • 推:推的方式被认为更“正确”。但观察者可能会被强迫收到一堆数据。
    • 拉:如果主题需要增加更多的状态,不用修改和更新对每个观察者的调用,只需要改变自己允许更多的 getter 方法来取得新增的状态。但观察者可能需要调用多次才能收集全所需要的状态。
  3. 装饰者:包装一个对象,以提供新对行为。
    • 定义:动态地将责任附加到对象上,若要扩展功能,装饰者提供比继承更有弹性的替代方案。
    • 维持了开放-封闭原则,但会造成设计中有大量的小类,如果过度使用,会让程序变得复杂。
  4. 工厂方法:由子类决定要创建的具体类是哪一个。
    • 定义:定义了一个创建对象的接口,但由子类决定要实例化的是哪一个。工厂方法让类把实例化推迟到子类。
    • 简单工厂:不是真正的设计模式,但可以将客户程序从具体类解耦。
  5. 抽象工厂:允许客户创建对象的家族,而无需指定他们的具体类。
    • 定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
    • 客户不需要知道实际产出的具体产品是什么,从而将客户从具体的产品中被解耦。
    • 工厂方法 vs 抽象工厂:
      • 将应用程序从特定实现中解耦的方式不同,工厂方法用的是继承。
      • 抽象工厂用的是组合。另外,抽象工厂可以把一群相关的产品集合起来。
  6. 单例:确保有且只有一个对象被创建。
    • 定义:确保一个类只有一个实例,并提供一个全局访问点。
    • 全局变量的缺点:如果创建对象非常耗费资源,而后续没有用到,会形成浪费。而单例模式可以延迟类的实例化。
    • 为了解决多线程问题,方式 1:使用“急切”创建实例,而不用延迟实例化的做法。方式 2:使用“双重检查加锁”方式,检查实例,如果不存在则进入同步区块。只有第一次需要进入同步区块,代价较低。
    • 如果有多个类加载器,可能会导致多个单件并存。最好不要继承单件,因为构造方法是一般是私有的。
  7. 命令:封装请求成为对象。
    • 定义:将“请求”封装成对象,以便使用不同的请求、队列或日志来参数化其它对象。命令模式也支持可撤销的操作。
    • 命令模式将发出请求的对象和只需请求的对象解耦。被解耦的两者之间通过命令对象进行沟通。命令对象封装了接收者和一个或一组动作。
    • 实际操作时,常用“聪明”命令对象,也就是直接实现了请求,而不是将工作委托给接收者。
  8. 适配器:封装此对象,并提供不同的接口。
    • 定义:将一个类的接口转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以合作无间。
    • 对象适配器使用组合来适配被适配者,而类适配器是继承被适配者和目标类。
    • 适配器 VS 装饰者:
      • 装饰者的意图是扩展包装对象的行为或责任。
      • 适配器的意图是进行接口的转换。
  9. 外观:简化一群类的接口。
    • 定义:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
    • 外观不只是简化了接口,也将客户从组件的子系统中结偶。
    • 外观 VS 适配器:
      • 外观的意图是简化接口。
      • 适配器的意图是将接口转换成不同的接口。
  10. 模版方法:由子类决定如何实现一个算法中的步骤。
    • 定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
    • 模版方法 VS 策略:
      • 模版方法使用继承进行算法的实现。模版方法对算法有更多的控制权,算法的每一部分基本相同。重复使用的代码都被放到超类中,让所有的子类共享。
      • 策略通过对象组合的方式让客户选择算法实现。策略使用对象的组合,更具有弹性,可以在运行时改变算法。
    • 模版方法 VS 工厂方法:
      • 工厂方法是模版方法的一种特殊版本。
  11. 迭代器:在对象集合之中游走,而不暴露集合的实现。
    • 定义:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
    • 迭代器将遍历聚合的工作封装进一个对象中。
  12. 组合:客户用一致的方式处理对象集合和单个对象。
    • 定义:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
    • 使用组合结构,我们能把相同的操作应用在组合和个别对象上。换句话说,在大多数情况下,我们可以忽略对象组合和个别对象之间的差别。
    • 组合以单一责任原则换取透明性。
  13. 状态:封装了基于状态对行为,并使用委托在行为之间切换。
    • 定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
    • 将状态封装成独立的类,并将动作委托到代表当前状态的对象。
    • 状态 VS 策略:
      • 状态中,利用许多不同的状态对象。“改变行为”是建立在方案中的。
      • 策略中,不鼓励对象用于一组定义良好的状态转换。事实上,通常会控制对象使用什么策略。
  14. 代理:包装对象,以控制对此对象的访问。
    • 定义:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
    • 使用代理模式创建代表对象,让代表对象控制某对象的访问,被代理的对象可以是远程的对象,创建开销大的对象或需要安全控制的对象。
    • 代理 VS 装饰者:两者的目的不同。
      • 代理代表对象,控制对象的访问。
      • 装饰者装饰对象,增加新的行为。

参考

  1. Eric Freeman, Elisabeth Freeman, Kathy Sierra and Bert Bates. Head First 设计模式 M. 北京:中国电力出版社. 2010.

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 OO 原则
  • 2 OO 模式
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档