🚀 优质资源分享 🚀
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
💛Python量化交易实战💛 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
真正开发中使用最频繁的模式基本就是【策略】和【工厂】这个两个模式。
按照"国际惯例"先引入些模式的概念和示例。(示例参考Head First,但是力求比它讲的简洁且清晰)
之后在详细讲解优惠券的设计和模式应用。
所有面向对象入门的时候都是以人、动物为示例。讲解什么是【继承】等相关概念。这个是符合直觉的。
但是在实际应用中,继承用到的地方有限,它有它的问题,它是一种【强耦合】方式,一般使用【策略模式】【装饰模式】代替继承。
以鸭子动物设计为例,讲解继承方式存在哪些问题:
所有鸭子都有quack和swim能力,所以超类实现这两个功能。
display是抽象方法,每个子类鸭子自己负责实现自己的display功能。
这样很好的使用了父类继承能【复用】的特性。
(符合直觉的第一想法,而且还是面向对象学习的不错的情况)
有些功能很好界定,有些功能很“尴尬”,例如fly功能。
fly不能加在超类上,因为不是所有鸭子都有fly功能。
如果加在超类上就导致所有的子类都要实现或者继承这个可能不适用的方法。
而且也不是所有鸭子都会quack(例如木头玩具鸭子),那些没有quack的鸭子,同样要实现或继承quack。
想利用继承来达到代码复用的目的有以下问题:
- 同样的display功能代码在子类中重复,代码没有【复用】。
- 这些子类鸭子的display、fly代码是写死的,想运行时候修改很难。
- 由于每个display功能分散在不同的子类鸭子中,很难知道全部的行为。
- 我们修改了父类会导致牵一发而动全身。所有鸭子都受到了影响。同时我们修改某个相同类型display行为的时候,需要每个鸭子去找该相同代码进行修改。
设计升级:
通过接口的形式,让“某些”(而非全部)鸭子类型可飞可叫。
谁有需要谁就去实现相应的接口。
例如:你可以飞你就实现flyable接口,你不能飞,你就什么都不做。
通过接口的形式解决了部分问题,因为不是所有子类鸭子都具有fly,和quack行为。没必要继承或实现自己不适用的功能。
但是代码无法【复用】的问题还是存在。
我们每个子类中都维护了display,quack功能,可能很多子类的功能都是一致的,没有复用起来,修改一类相同行为,要每个类去找,逐个修改。
同时这些代码都散在每个实现类中,不知道全部的行为。
设计思路与原则:
软件项目唯一的共性:【需求不断变化】
我们要做的就是【识别变化】【隔离变化】,每次迭代或者需求变化的时候,修改范围可控,模块之间【松耦合】。
主要最好不要动到那些成熟的已经经过测试和生产验证的代码,尽量遵循【开闭原则】。
是否进行隔离有个【单一职责】原则判断,如果两个模块修改的原因是不同的,彼此的修改不一定牵涉到对方的修改。那他们应该隔离。
所谓隔离即代表,他们代码在不同方法中、或在不同类中、或者不同服务模块中、甚至是不同系统中。
示例中,每个鸭子的fly和quack会随着鸭子的不同而不同。我们建立两组类,一组和fly相关,一组和quack相关。
fly类里面有各种fly的实现方式。例如:用翅膀飞是一个实现类。用火箭飞是另外一个实现类。
这样对于使用翅膀飞的一类鸭子,我想办法把相应的fly类给到它,就实现了fly方法的【复用】和【集中管理】
下面我们要解决的就是如何将这个用翅膀飞的实现类“给到”这个具体的鸭子类。
插播一条概念:
【针对接口编程】
什么是接口?
接口就是约定好的规范、口令、图纸。
就好比,各个地方的人,都听得懂“滚”这个语言接口命令,也有相应的实现。 大家虽然各不相同、想法各异、体能差异。
但是听到你跟他说“滚”,大家都会执行迈腿这个动作,根据人种不同,有的地方人可能迈腿上步揍你,有的地方的人是迈腿跑路。
这种不同人种的不同反应方式,我们称为【多态】。
虽然语言接口相同,都是一个“滚”的语音输入。但是具体实现类不同,反应也是不同的。
例如:电脑主板上有很多接口,这些接口是有明文规定,例如电压、时序、通讯协议、功能等的。
这些就是规范。你按照这个规范走,就能拿到规范定义的结果和返回。
不同的内存厂商都有自己的内存条。他们的内存芯片、板子方案都是不同的,但是他们的插槽是相同的,他们都是实现了内存接口规范。
电脑只要按照内存接口规范,发出同样的指令。任何厂商的内存条都能进行存储操作。
以前经常听说一句话,一流公司定规范,二流公司做产品。
其实规范就是接口,大公司定义实现方案和方案要实现的接口,其他公司根据自己的原材料实现这些接口,这个产品就落地了。
所谓【要针对接口编程,不要针对实现编程】
你学习如何让一个人滚,一定要学习普通话,因为大多数地方的人都能听懂,只不过反应不同。
如果你针对某个特定的人群学习,那你这个技能就限定在少数人上,例如闽南语只有福建那块的人能听懂。
再比如,你这个电脑主板内存接口是针对三星独家的开发的,指令也只有三星认识,其他品牌的内存条甚至都插不上去。
这样的主板谁会买,绑死在三星上,他说涨价你就要掏钱。不然整个电脑都不能运行。
针对接口实现的板子。我可以换同样接口的国产便宜的内存。还是那句“又不是不能用,李姐万岁”。
解释完概念,我们看编程上如何应用。
我们以一个人的一天活动为例子。
class PersonDayAct{
DayAct act = new 码农();
act.dayAct();
act.nightAct();
}
act.dayAct();act.nightAct(); 我们都用的接口方法,都是使用接口在编程。好处是如果我们想打印富二代的一天。DayAct act = new 富二代(); 只需要修改这一行代码即可。
通过多态,我们就能打印富二代的一天活动。而且这个new操作,我们能通过稍后的工厂模式代替。如果以后要打印其他人的一天活动。我们只要新建新的实现类即可。不需要改动以前写好的经过测试的代码。符合【开闭原则】
讲完【面向接口编程】,我们继续讲如何完善鸭子示例。替代继承的方式就是【组合】,多用组合,少用继承。“有一个”比“是一个”更好,每一个鸭子都有一个FlyBehavior和一个QuackBehavior,好将飞行和咕咕叫委托给他们处理。鸭子的行为不是继承来的,而是和“适当”的对象“组合”而来。组合的好处:
1.将一类行为封装成类2.运行时动态改变行为。