设计模式,是对前人遇到问题并顺利解决问题方案的一种总结,是一种经验复用。
1)泛化,可以简单地理解为继承关系;
2)实现,一般是接口和实现类之间的关系;
3)关联,一种拥有关系,比如老师类中有学生列表,那么老师类和学生类就是拥有关系;
4)聚合,整体与部分的关系,但是整体和部分是可以分离而独立存在的,如汽车类和轮胎类;
5)组合,整体与部分的关系,但是二者不可分离,分离了就没有意义了,例如,公司类和部门类,没有公司就没有部门;
6)依赖,一种使用关系,例如创建 A 类必须要有 B 类。
下面我们从一个游戏说起
需求:做一个模拟鸭子的游戏,游戏中有各种鸭子,一边游泳,一边呱呱叫。
实现:设计一个鸭子超类,让各种鸭子继承这个超类。
需求变更1:需要会飞的鸭子
具体实现1:在超类Duck中加入fly()方法,然后让所有的鸭子都会继承fly()方法
遇到问题1:并非所有的Duck子类都会飞,会使得某些不适合该行为的子类也具有该行为
分析:
1)对代码的局部修改影响层面并不只是局部,在超类中加入fly()会导致所有的子类都具有fly()
2)如果在某些不需要fly()方法的子类中覆盖掉此方法,会怎么样
V
如果我再加入一个木头鸭子,不会飞也不会叫,需要检查是否覆盖fly()和quark(),
每当加如一个鸭子时都要这样做,这简直是无穷无尽的噩梦
V
我们发现利用继承提供Duck的行为,会导致代码在多个子类中重复,
运行时的行为不容易改变,很难直到鸭子的全部行为,
改变会牵一发而动全身,造成其他鸭子不想要的改变
需求变更2:每六个月更新一次产品
具体实现2:把fly()从超类中提取出来放进一个Flyable接口中,只有实现此接口的鸭子类型才会飞,quack()亦如此
分析:Flyable和Quackable能够解决一部分问题,但是却无法造成代码复用,比如,50个子类实现Flyable接口后都需要稍微修改一下飞行的行为,
甚至在会飞的鸭子中,飞行的动作可能还有多种变化
V
我们希望有一种方法,让我们用一种对既有代码影响最小的方式来修改软件
小结
继承并不能很好的解决问题,因为鸭子的行为在子类中不断的改变,并且让所有的子类都具有这些行为并不恰当,
Flyable和Quackable接口一开始似乎不错,解决了只有会飞的鸭子才继承Flyable接口,但是JAVA接口不具有实现代码,
所有继承接口无法实现代码的复用,这意味着无论何时你需要修改某个行为,必须得在每一个定义此行为的类中去修改它。
软件是需要成长和改变的,否则就会dead。
有一个设计原则可以帮助我们解决现在遇到的问题 ,把软件中变化的部分抽离并封装起来,
以便以后可以轻易的改动或扩充这部分,并不影响其他不需要改变的部分,系统因此变得具有弹性。
参考资料:经典设计模式实战
参考资料:《Head First设计模式》
原文:https://www.cnblogs.com/marton/p/11334111.html