关于设计模式:HeadFirst设计模式读书笔记一策略模式

作者:折纸
集体博客:https://www.zhezhi.press
记录菜鸡的成长之旅!

1 从一堆鸭子说起

家喻户晓《机器学习》(周志华版)被称为西瓜书,我感觉《Head First 设计模式》也能够被称为鸭子书~ 假如有这么一个模仿鸭子游戏SimUDuck,游戏中会呈现各种鸭子,它们一边游泳一边呱呱叫。于是有这么一个鸭子超类,并且让各种鸭子继承这个超类;


这看起来仿佛还不错,所有的鸭子都会继承Duck超类,并且只须要重写display办法以打印本人的特色就能够。但需要是在变动的

2 让鸭子飞起来!

好吧,看起来不难,咱们只须要给Duck类加一个fly()办法并实现就能够了;的确这样一来所有继承Duck类的鸭子都会飞了,然而咱们疏忽了一个事实——不同子类之间的差异性,橡皮鸭子本来不会飞当初飞起来了!

对代码的部分批改 影响的不肯定只停留在部分;当波及“保护”时,为了“复用”目标而应用继承,终局并不完满
我的了解:对超类的批改要审慎,防止造成不必要的麻烦!如无必要,勿增实体

2.1 解决办法:子类重写

咱们能够重写不会飞的橡皮鸭子的fly办法,将其改为什么也不做就能够了。
这的确解决了橡皮鸭能够飞的问题,然而当前每次设计新的子类的时候,咱们都须要查看fly、quack、swim等办法,这就失去了复用的意义。

通过继承提供Duck的行为,可能会带来的毛病

代码在多个子类中反复(须要改写行为以适应不同子类)
运行时的行为不容易扭转(无奈灵便切换)
很难晓得所有鸭子的全副行为
扭转会牵一发而动全身,导致其余鸭子不想要的扭转

2.2 解决办法:通过接口

接口是对行为的形象,能够把fly()、quack()从超类中提取进去,放进Flyable、Quackable接口,而后只有会飞、会叫的鸭子才回去实现这个接口。
但这一来反复的代码将变得更多,对于每一种会飞、会叫的鸭子都须要去实现对应的接口,此外还有不同航行办法、不同叫声的叫法,这使得代码的可复用性降得很低。

2.3 从新扫视问题

首先咱们晓得在这个案例中,fly是新退出的需要~
并且应用继承并不能很好地解决问题,因为鸭子的行为在子类里一直地扭转,并且让所有的子类都有这些行为是不失当的。Flyable与Quackable接口一开始仿佛还挺不错,解决了问题(只有会飞的鸭子才继承Flyable),然而Java接口不具备实现代码,所以继承接口无奈达到代码的复用。
这意味着: 无论何时你须要批改某个行为,你必须得往下追踪并在每一个定义此行为的类中批改它,一不小心,可能会造成新的谬误!
侥幸的是,有一个设计准则,恰好实用于此情况。

设计准则: 找出利用中可能须要变动之处,把它们独立进去,不要和那些不须要变动的代码混在一起。

上面是这个准则的另一种思考形式:“把会变动的局部取出并封装起来,以便当前能够轻易地改变或裁减此局部,而不影响不须要变动的其余局部”。–>零碎变得更有弹性

这样的概念很简略,简直是每个设计模式背地的精力所在。所有的模式都提供了一套办法让“零碎中的某局部扭转不会影响其余局部”。
好,该是把鸭子的行为从Duck类中取出的时候了!

3 抽离易于变动的局部

一种办法是建设2组齐全远离Duck类的Class,每一组类将实现fly、或者是quack,而类中有对于fly的不同实现;而且能够使得鸭子的行为能够动静地扭转(setter)

设计准则:针对接口编程,而不是针对实现编程。

咱们利用接口代表每个行为,行为的每个实现都将实现其中的一个接口。这样的做法迥异于以往,以前的做法是:行为来自Duck超类的具体实现,或是继承某个接口并由子类自行实现而来。

这两种做法都是依赖于“实现”,咱们被实现绑得死死的,没方法更改行为(除非写更多代码)。在咱们的新设计中,鸭子的子类将应用接口(FlyBehavior与QuackBehavior)所示意的行为,所以理论的“实现”不会被绑死在鸭子的子类中(鸭子不会负责实现Flyable、Quackable接口)。(换句话说,特定的具体行为编写在实现了FlyBehavior与QuakcBehavior的类中,从而实现理解耦)。

这样的设计,能够让航行和呱呱叫的动作被其余的对象复用,因为这些行为曾经与鸭子类无关了;并且咱们也能够新增一些行为(不同的实现),不会影响到已有的行为类和“应用”其余已有行为的鸭子类。

这么一来,有了继承的“复用”益处,却没有继承所带来的包袱。

4 复盘

你兴许可能听过Has-A is Better than is-A的说法,兴许你可能像我一样此前并没有很间接地感触到或者思考过Why Has-A is Better than is-A?
但通过鸭子的例子我想你应该有一些感触了,is-A也就是继承的关系(不同的鸭子继承超类Duck),而has-A更偏差于组合的关系(鸭子类有FlyBehavior类和QuackBehavior类,鸭子是容器/对象,而后两者是容器/对象的组件类)

 设计准则:多用组合,少用继承

如你所见,应用组合建设零碎具备很大的弹性,不仅可将算法族(对于同一个行为的不同实现办法)封装成类,更能够“在运行时动静地扭转行为”(setter办法),只有组合的行为对象合乎正确的接口标准即可。
组合用在许多设计模式中,它也有许多长处和毛病,在之后的学习中咱们还会持续探讨;

5 策略模式

策略模式是一种行为型设计模式, 它能够在运行时抉择算法;与间接实现某个算法不同,代码在运行时能够抉择在算法族中选取一个执行。
(In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.wikipedia)

或者说

策略模式将某一个行为(接口)通过不同的办法/算法实现[上文所提的算法族],不便须要实现该接口对应行为[Has-A]的程序/客户能够在”运行时”灵便切换该行为实现的办法/策略,使得策略的变动独立于应用它的客户/程序;

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据