00:00
今天我们讲的内容呢,也是非常重要的啊,同学们,同学们一定要去认真的体会。那我先把这个保存一把,然后打开我们今天新的任务,我们今天要讲的内容是什么呢?先给大家看一下我们的幻灯片,第一个呢,要把设计模式给大家讲完,第二个呢,要给家讲幻型。上下界视图界定,上下文界定,还有一个没写出来,还有一个就是我们的斜面。邪变,逆变。然后不变啊,听这个名字一看就非常的高大上,是不是感觉好像很牛逼的样子是吧,其实很简单啊,很简单,但是有些也不是很简单啊,就是说你要你不把第18章给你们讲了,你们有很多代码你是看不懂的,就是那个它的语法你看不懂,讲完了过后大家就真的比较明白了。所以说我们这个给你们给你们讲的这个看呢,应该说从从目前来说啊,咱不是吹牛,在国内应该是至少是最全面最系统的一个版本。
01:09
啊,这个视频发出去肯定是要火的,肯定是要火的,好,我们接着往下看,我们就接着说这个事了。呃,那么我们直接跳过讲解的内容,我们直接到哪里呢?到我们的装饰者模式,诶,啊同学们,你理解一下,真是很牛逼,这个装饰这种模式你听完了过后,你应该产产生一种什么呢?很愉悦的感觉啊,这真的很牛啊,你看这个设计思想对不对?那么我们老规矩还是用一个案例来推动大家对它的理解,没有案例你很难理解。那么我们现在这个案例呢,我们整一个咖啡馆的订单系统项目,那就是喝咖啡了,说现在呢,有一个咖啡店啊,说有一个咖啡馆。啊,咖啡。咖啡馆,呃,咖啡馆你们你们没去过,你们咖啡肯定是喝过的,对不对,那外国人很喜欢喝咖啡,将来你们到了好一点的公司,一般下午茶呢,都会给你来一杯咖啡啊,你就可以喝饭,主要的目的呢,老板主要目的是让你们睡不着觉,知道吧,啊,不是让你口渴了,喝咖啡睡不着觉,你就可以干活了嘛,那么咖啡呢,我们假设有单品咖啡有这么四种,Espresso,这个是意大利浓咖啡,就意大利很浓,这个喝了过后呢,就是想睡也睡不着了,还有一个short black,就是黑短短黑咖啡,这个我不知道怎么翻译,所以说我就只只写了个英文叫short black,还有一个long black,就是美式咖啡啊,就是美式咖啡呢,它就可能没有那么浓,没有那么浓烈,还有一个,呃,第一无音咖啡就没有糖的那种,有些人他喜欢喝这种,呃,这种这种咖啡对coffee coffee啡,那么除了这个咖啡之外呢,诶,我们咖啡有些人喜欢加点牛奶,对。
03:00
么miracle,有些人喜欢加点豆浆,哎,好像没有是吧,这变了一个加了个豆浆,还有些人喜欢加点巧克力,诶有小朋友他喜欢喝巧克力的咖啡,大家看目前呢,我这儿有四个单品的咖啡,同时呢,我还有调料啊调料调料就是说我在买一个咖啡的时候呢,我可以让别人加点豆浆诶或者说加点加点牛奶。等等,或者加点巧克力啊,那么这是一个,他们一个是单品,一个是调料。那现在呢?要求在扩展新的咖啡种类时具有良好的扩展性,改动方便,维护方便。什么意思呢?是这样子的啊,看我的要求,请用oooo,就是我们面向对象用oo来设计不同种类咖啡的费用,就是用O的方式来计算不同种类的咖啡的费用,比如说我意大利咖啡的,我点一份意大利咖啡,同时呢,我要我要求加一份牛奶。
04:04
把这个你就把这个价格给我算出来,或者说我点了一份美式咖啡nonb,同时呢,我还要加两份巧克力。啊,你把这个总的价格估算出来,就这么简单,那客户既可以点单品咖啡,就是他可以单点,也可以点单品加调料组合。需求已经出来了。那同学们想,此时此刻,你作为一个程序员,你怎么去设计这个类呢?我们是面向对向O的方式,其实最主要就是设计类,好同学们看我还是个老规矩,说你男朋友长得帅对吧?那是有比较的,那是有比较的,你得看跟谁比对不对啊,不,不是跟我比啊,我也不行,好,呃,你要跟这个帅哥比,那就不是了,那么我们看一个比较差的方案。我们来看一个比较差的方案,这个方案呢,可行,但比较差。比如说我先抽象出来一个类叫drink,同学们注意认真听啊,绝对提高你的档次啊,绝对提高你档次,那么这是一个drink呢?我抽象成一个抽象类,就是饮品嘛,我不管你是什么样的单品呢,还是组合,你反正是饮料嘛,说白了,那么这边我有个描述叫description,就是描述,还有一个得到的描述,这个cost是干什么呢?Cost的就是计算费用。
05:24
这个cost的就是用来计算我们的费用的,就是你一共给应该给多少钱,好,现在看啊,一个比较差劲的方案是。单品,我单独的设计一个类,这很合理吗?就是无音咖啡non park,还有意大利农咖啡,我就给你设计一个类,那么我计算的成就计算就行,如果你单点一份,这个就出来了,如果你两份就乘以二。那么问题栏问题是在这个地方,同学们看问题是在这里,因为一个人在,比如说有一个人点了一个espresso,就是我们的意大利浓咖啡,他在点的时候呢,他说我要加份牛奶。
06:02
诶,这就形成一个新的一个组合了,这就是按理说用新的类啊,那么我也可以点这个press的加份牛奶,同时还加份豆浆,我喜欢这么喝,又出现一个类,那么presso呢,我单点一个豆浆,又出现一个类,这是合合理的一种直观的想法,同学们想。这样会出现一个什么可怕的现象呢?这样会出现我们经常所说的内爆炸。就是你这个例会很多,你搞不定为什么呢?你想啊,我们这个意大利浓咖啡跟我们,我们现在现在单品咖啡有四个,单品咖啡有四个,我们的调料有三种,那你想一想,一个单品跟我们这个调料组合一共有多少种呢?算得出来吗?一不是,你看啊,我们一个意大利浓咖啡,我们可以单独给他组合就三种了,我们再挑两个组合又是三种,是不是再加一种,就七种,就是一个单品就会对应七个类,还没有算它单品本身,那也就是说相当于一个单品总共要对应八个。
07:11
再乘以一个四等于32个类,你这样设计,你觉得O吗?显然不在A个地方,你彻底完蛋,为什么呢?如果将来人家又来了一份中国的土咖啡,对不对?我们中国人呢,喜欢喝的咖啡我们又不一样,而且中国人喜欢加点什么呢?诶,咱们喜欢加点这个豆腐脑是不是?那这个玩意儿你进去过真的不得了,一加又又爆炸对吧?又爆炸不行了,好,这个不行,所以这个方案很差,这个很差变成什么呢?变成内爆炸,它会出现一个可怕性,就是内爆炸,看我的分析。对一方案的分析尽可是个抽象类表示饮品对表示描述,而cos的就是计算费用无因咖啡单品。那么这种设计方案会有很多类,并且当增加一个新的单品咖啡或者调料时,类的数量就会被呃倍增,出现一个类爆炸的这么一个情况。而且你几乎可经常说,啊,你这个设计会显得非常的低端。
08:11
你自己也能想象,那问题来了,怎么升级呢?好,同学们,这就是设计模式的。要解决的问题就是我要告诉你应该怎么去干,你才是合理的一种设计方案,这就设计模式的价值。对吧,好,那么我们来提出第一个稍微好一点的方案,但是不是最好的,但是还是可以怎么看,前面我们分析的方案一,因为咖啡就是这个组合,就是咖啡单品。它的问题是在什么地方?是因为你的单品咖啡和调料组合会造成内的倍增,那我怎么解决呢?因此我们可以做如下改进,将调料内置在drink里面。没错,可以调料内置这个零,这样就不会造成内数量过多,为什么你看我这样设计的。
09:02
我这儿呢,还是一个drink,那么这个drink呢,我认为将来会有milk,会有这个豆浆,会有巧克力。好,然后呢,大家看我这里costs呢,仍然是计算我们费用的,然后我问你有没有牛奶啊。你可以设你你有没有设置牛奶,就这是一组吗?就比如说人家点了一个饮品,说我要我要一份牛奶,然后我在计算成本的时候,我看你有没有加牛奶不就可以了吗?同样我判断你有没有加豆浆,我又计算成本吗?然后呢,我看你有没有巧克力,我要加成本,好,这个是。这个确实还是可以的,为什么呢?因为这样设计过后,我的类只需要有四个就可以了。多好。因为我将来在继承的时候,我只需要在点的时候,我设置一下说我要分豆浆,在这个cost里面,我去判断你有没有完事了。多艰难,所以这个方案呢,还是可以的,还是可以的,诶,然后这个可以是可以,但是有个问题大家看这种方案有什么缺点呢?来同学们看啊,这种方案可以控制类的数量,不至于造成过多的类。
10:14
没有问题,但是在增删调料种类时,代码维护量仍然很大,什么意思?就说如果将来我这个drink,我增加了一个调料,比如说加了一份豆腐,我们有个调料是豆腐脑,那你就要去动这个drink,你要你要去修改这个drink是不是很麻烦,我们这就违反了我们一个什么原则呢?OCP原则。因为你在加一个单品的时候,你的代码变化是很大的,你的变化是很大的,因为我们在这个设计的方案是这样一个原则,注意听讲,注意听讲啊同学们给你们说说一下我们的原则,尽量应该做到什么一个原则呢?就说你这里有很多的类,你这里有很多的这个类,包括他们之间有很多继承关系,这个没问题,比如说我这个呢,我这个地方继承了他注意听。
11:12
啊,同学们注意听讲啊,这个地方呢,咱们注意听,你听完了过后你会发现,的确啊,上了档次了就说什么,就说我们希望这是一个类的一个体系图,将来我们要干什么呢?如果我们要增加一个功能,在我们开发里面有个原则就是。比如说右图是左图,左图。作图。是一个类的体系图,就是我们项目的是一个项目的类的体系图。体体体系图。啊体系体系图,那么在我们开发中有个原则,说当我们在这个开发中尽量遵守要求啊,要求尽量的尽量,呃,你你可能有时候做不到一点办法尽量的遵守,遵守什么呢?诶遵守这个OCP原则。
12:12
就是我们经常所说的开开闭原则啊,开闭原则,那么什么叫开闭原则呢?它的原则就是说我所以开篇就是说将来我要增加一个功能,我要增加一个功能,这些代码尽量都不要去改。你可以干什么,你也可以加一个类进去,你可以加一个类,就你尽量是通过加了一个新的类,比如说这是我的新的一个类。新的类。那么我只要把这个新的一加进去,我的功能就增加了。就这么简单。就这么简单,就是他希望达到这个效果,就你整个这个体系没有变化,我加了一个新的进去。这个功能就增加了。诶,这确实是很有意思的一个现象,对吧,这就是他想达到的一个效果,就是我没有去你动你的这个这个这个我都没动,但是我加了新的,加完这个新类以后,但是这个新类可能是去继承一个,这个关系还是可以保留的,比如说我加了个新类,我去继承了一个类,这个它是允许的,因为我继承我并没动你嘛。
13:14
然后呢,我们在调用的时候,我们这比方说这是我们的这个调用程序,调用程序,调用程序这地方,只要你就就这是我们的调用程序,直接就可以增加使用新功能了。诶,这是调用程序,那么这里就可以直接使用到,使用到新的功能,诶它就是这么一个原则,就是我们所谓的开辟原则什么呢?就说就是通过什么呢,通过增加。增加新的类。来扩展来来扩展功能。即开闭的,开是什么呢?开闭,开闭原则,这个开闭原则的这个开指的是这个意思,开指的是。
14:03
啊指的指的是功能增加开放。就是功能,功能扩展开放,它是开放。就是功能扩展,我是开放的B呢,它的B的原则指的什么呢?B就是代码修改给你关闭,它指的意思是这样子,BB合指的是什么呢?就是修改代码就不要去修改,不要去修改。不要去修改我们的已有的啊,已有的这个代码。就这么简单,好,那么要实现这么一个功能,咱们能不能搞定呢?当然是可以搞定的,当然是可以搞定的,那么看看我们的第三一个设计方案,这时。我们就来设计一个装饰者模式。好,同学们,装饰的模式呢?呃,这个终于咱们引出来了,我先截取一段视频,就是前面讲的内容,就是为了引出我们这个装饰者模式,讲了那么多东西,好,我先截取一段视。
我来说两句