Head First 设计原则和设计模式
-
-
- 原则一:封装变化。找出应用中可能会变化之处,把它独立出来,不要和那些不需要变化的混在一起
- 原则二:针对接口编程,而不是针对实现编程
- 原则三:多用组合,少用继承
- 策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
- 观察者模式:定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
- 原则四:为了交互对象之间的松耦合设计而努力。
- 原则五:类应该对扩展开放,对修改关闭。
- 装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
- 工厂模式
- 依赖倒置原则:要依赖抽象,不要依赖具体类。
- 单件模式:确保一个类只有一个实例,并提供一个全局访问点。
- 命令模式:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤消的操作。
- 适配器模式:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
- 外观模式:提供一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
- 原则六:最少知识原则,只和你的密友谈话。(迪米特法则)
- 模版方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
- 原则七:好莱坞原则,别调用(打电话给)我们,我们会调用(打电话给)你。
- 迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
- 原则八:单一责任(基本原则):一个类应该只有一个引起变化的原因。
- 组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
- 状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
- 代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
-
原则一:封装变化。找出应用中可能会变化之处,把它独立出来,不要和那些不需要变化的混在一起
封装变化,使其更具有弹性。eg:把鸭子中容易变化的fly()和quack()分别从duck类中独立出来
哪些因素导致你必须改变你的程序?
- 我的客户或用户决定他们想要其他一些东西或新功能
- 我公司决定使用另一个数据库,并且从使用不同数据格式的另一个支持商购买数据
- 技术改变,所以我们不得不更新我们的代码取使用新的协议
- 想要重构系统使其更好
原则二:针对接口编程,而不是针对实现编程
利用接口代表每个行为,行为的每个实现都要实现其中一个接口。这样,鸭子就不需要知道行为的具体实现了。
“针对接口编程”真正的意思是针对超类型编程,可以利用多态。多态:声明的变量类型应该时一个超类,通常是一个接口的抽象类,所以分配给这些变量的对象可以是父类的任何具体实现,这意味着类声明他们不需要知道具体对象类型。
原则三:多用组合,少用继承
“有一个”可能比“是一个”更好
策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
什么时候使用策略模式?
- 很多相关类仅仅行为不同
- 你需要一个算法的不同变体
- 算法使用的数据用户不应该知道(避免暴露内部数据结构)
- 类定义了许多行为,这些行为在其操作中显示为多个条件语句
什么是设计模式:
- 记录设计面向对象软件的经验作为设计模式
- 每个设计模式系统性地命名,解释以及评估一个重要的且重复出现在面向对象系统中的设计
- 目标是去捕获设计经验,用一种人们可以高效使用的形式
- 每个模式描述了一个在我们的环境中反复出现的问题,然后描述了这个问题的解决方案的核心,这样您就可以将这个解决方案重复使用一百万次,而不必重复使用相同的方法两次
设计模式的好处:
- 设计模式为你和其他开发者提供一个共享词汇表
- 通过让你在模式层面思考,而不是基本对象层面,提升你关于架构的思考
如何使用设计模式?
- 库和框架
- DP帮助我们构建的程序更加可维护和可扩展
- DP首先进入你的大脑
设计模式4元素:
- 模式名:用一两个词描述一个设计问题,解决方案和结论
- 问题:描述什么时候取应用模式
- 解决方案:描述组成设计的元素,元素之间的关系,责任和合作
- 结论:应用模式的结果和权衡
观察者模式:定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
上图中,具体观察者持有主题的引用,为了在主题那注册成为观察者。
使用Java的Observable和Observer接口实现观察者模式
WeatherData.java
import java.util.Observable;
import java.util.Observer;
// 不再需要去持有observers,也不需要管理他们的注册和移除,父类Observable会处理他们
public class WeatherData extends Observable{
privatate float temperature;
privatate float humidity;
privatate float pressure;
public WeatherData() {
// 继承Observable之后不再需要创建保持Observers的数据结构
}
public void messurementsChanged() {
setChanged(); // 在通知观察者之前先setChanged()来表明状态已经改变
notifyObservers(); // 没有传数据对象,说明用的PULL模型
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
messurementsChanged();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
CurrentConditionsDisplay.java
import java.util.Observable;
import java.util.