设计模式解决什么样的问题
我们通过继承来实现代码复用,通过扩展接口来实现功能扩展。不过当需求不断地变更,代码量越来越庞大地时候,仅仅靠这两种方式并不能很好地解决问题,例如通过复写改变子类行为会导致代码在多个子类重复。单纯地使用接口,则带来改变的困难,如果接口改变了,可能要在多处修改。
封装变化是每一个设计模式背后共有的思想
设计原则:
把变化的部分取出来并封装起来,以便以后可以轻易地改动或者扩展此部分,而不影响不需要变化的其它部分 ·
例如一个Duck有很多飞行行为,如果我们在每个子类去实现接口,我们就被实现绑的死死的,所以,从另一个角度来说,我们可以将飞行行为与子类分离(不是通过子类实现接口的方式)。我们可以提供一个 setFlyBehavior 方法,然后传入接口实现类,以达到动态扩展的功能。在这里,将鸭子和飞行行为(Unsteady factor)分离开来。
设计原则:
针对接口编程,而不是针对实现编程
针对接口编程真正的意思是针对超类型(supertype)编程,针对超类型编程这句话,可以更明确地说成 “变量的声明类型应该是超类型,通常是一个抽象类或者接口,声明类时不用理会以后执行时地真正对象类型”。下面是一个很好的例子。
1 | Animal animal = new Dog(); |
2 | animal.makeSound(); |
更棒的是,子类实例化的动作不再需要在代码中硬编码,而是在 “运行时才指定具体实现的对象”
1 | a = getAnimal(); |
2 | a.makeSound(); |
匿名实现类 OR Else
是否声明一个具体的类,取决于这个行为是否通用,可复用的就声明一个具体的类,在Duck的构造函数(如果可用度比较高,就可以放在默认构造函数中,也可提供一些带 IFlayBehavior 的构造函数)中实例化这个行为并赋值给Duck的 IFlyBehivor 即可。
设计原则:
多用组合,少用继承
组合用在很多的设计模式中。”有一个” 可能比 “是一个更好”
上面所讲的也涉及到我们介绍的第一个设计模式 “策略模式”,策略模式也是一种很基本的模式,大概率地出现在其它设计模式内
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法(方法)的变化独立于使用算法的客户
使用设计模式带来的好处
共享词汇的魅力:当讲到某个设计模式时,别人(同样和你一样优秀的学习了设计模式的Guy)能很容易理解你要表达的东西,你的代码如何组织的。
如何使用设计模式
1.设计模式不会直接进入你的代码中,而是先进入你的 “大脑” 中,在敲键盘之前,先想想怎么装逼
2.当你的旧代码如同shit一样,试着用设计模式去重构它们
3.当你找不到具体的设计模式时,自己创造设计模式吧