00:00
之前我们把这个代码呢,给大家呢,用三层架构的方式呢,做了一个分解啊,但是我们说了,你这个分解完成以后,功能到能实现呢,但是有些地方呢,其实应该还有改善和优化的地方啊呃,比方说咱们的第一个叫application,这个application程序大家会发现,如果你再写一个新的应用程序的话,这段代码是不是还得再来一遍。对不对,那你需要变化的代码其实只有它,但这些代码其实是不是完全相同的,为什么呢?环境嘛,对吧,你要提交应用程序,要么是雅,要么是STEM,可能还是个local,那么这样的话,你的环境其实啊,基本是固定的,但是呢,你的逻辑,你的这个调度应该是变化的,所以呢,这些代码是固定,那么这个代码是变化的,你这个怎么能够做到。你不能每一次写程序都把它全写一遍,这不就是冗余了吗?对不对,也浪费咱们的时间啊,所以啊,我们现在要想个办法把那些重复性的代码给它抽取出来,诶说到抽取出来了,咱们这里是不是有个common呢?我现在就要想办法干嘛呢?封装成一个我们的抽取的类,那这个类我们是用那个抽象类还是用咱们之前学过一个叫特质啊,咱们在史GALA当中特质是不是也可以抽取方法没问题吧,而且咱们死GALA当中的特质其实在某些场合下也能看成是抽象类,所以呀,咱们就别单独用的抽象类了,咱们这里是不是就可以直接来new,我创建什么?诶它然后写上一个叫T,咱们叫treat嘛,我就用一个T来表示了,咱们叫application,然后呢,我们下面的选择treat,点击OK,那么就意味这样,只要你是我们的什么我们的应用程序的话。
01:53
你就应该有启动执行应用的这个操作,所以我在这里写上一个叫DF,然后写上咱们叫start,叫启动咱们的应用程序,对吧,或者叫初始化,这个无所谓,你看你怎么起名,然后写个括号,然后放过来,放过来以后那就意味着这样的代码,大家想想我是不是应该放到这里面来。
02:16
没问题吧,同学们,那如果放到这里的话,那我该怎么办,那么我们是不是应该在这个位置给他来,咱们叫with,咱们叫T,咱们叫application呢?哎,我得这么写,那么你这么写的话,这些咱们就不要了,不要了以后咱们干嘛呀,调用一下叫做start对不对,哎,咱们这么写,所以啊,咱们叫做启动啊,咱们的应用程序。你这么写就够了,但你这么写有个问题啊,什么问题啊,你在我们的T啊,不对当中,这个controller你给它固定写死了,大家想一想好吗?好像不太合适吧,什么意思啊,咱们的这个地方大家想一想,你的这个controller难道只有word吗?你这是可是一个抽取出来的特质呀。
03:06
那你现在固定写成word count,那肯定不合适,所以这段代码呢,是应该是什么变化的,而这些代码应该是什么我们的固定的,所以在这种情况下,我们如何能够把一段变化的代码传到这个里面呢?诶,这个时候我就想到了在咱们盖LA当中有一个叫控制抽象的这么一个哎,语法,这个语法呢,它可以将一段我们代码传递到咱们的函数当中,大家还有印象吗?所以我们在这写上咱们叫做什么呢?叫做op啊,操作嘛,然后给它来我们写上一个箭头,我们叫做unit,嗯。你这么写完以后,那么就意味着我们可以在star的方法当中把一段逻辑传进来,那好,这个逻辑呢,我们就直接拿过来,拿过来以后大家看一下,我就在这儿写个花括号。
04:01
哎,放到这里,你放到这里以后,大家想想这个就是我变化的逻辑对不对?哎,把它传进去,你传进去以后,这个逻辑被你拿到了,拿到了该怎么办?我是不是应该执行啊,但是我执行的时候,我加上一个什么呢?咱们叫try catch,诶,拿过来啊,咱们写上它,然后写上一个case,我们叫ex啊,然后放过来,我们这里呢,就直接咱们的print吧,咱们叫EXDR,我们叫做什么呢?嗯,就可以了,所以大家会发现在咱们这里呢,加上一个异常的处理,万一你的执行过程当中出现了问题,我们能够看到它的错误信息,这不挺好吗?所以把这段逻辑我就放在这儿,它就可以执行了啊,所以啊,咱们现在就把两块代码呢,给它分解了一下,有一个抽取出来的OB,但是呀,其中还有个问题,大家看这。这个地方是不是叫local星啊,这是我们的环境master,这个是我们的应用程序的名称,这个你固定死了是不是也不太合适啊,对不对,你这样的话是一个抽取出来的共同类,你把这个环境固定了,把这个名称固定了也不合适吧?哎,所以呢,同学们看我在咱们的这个地方,或者说在前面,这都无所谓啊,你在前面我们写上一个叫master,好,再来一个咱们叫做什么呢?咱们叫APP,给他一个stream,那这样的话master就可以放到这个地方了,对不对?好,然后呢,这个APP呢,我们就可以放到这里了,但是我担心啊,你每回传是不是也不太方便啊,所以给他一个默认值,咱们就叫local,咱们写上一个星,你不给我传,那我就写上一个logo的一个星了啊。
05:51
好了,那同样道理,这个APP呢也是一样的,你如果不给我传,那我就叫应用程序不就完事了吗?那所以啊,给他一定的默认值,那么这个时候回过头来我就加一个括号,诶加括号你加完了以后,大家会发现在这个时候。
06:08
我们根本就不用管它,只要写逻辑是不是就可以了,哎,就是这样,好,那这个如果大家能够明白的话,那我们现在啊,就先放到这儿,我们再说另外一个问题,说什么呢?咱们的controller,咱们这个controller大家想一想,其实每一个控制器是不是都应该有一个调度啊,它都应该有调度,所以啊,既然咱们那个application可以抽取出来,那咱们难道我们的controller不能抽取一下吗?所以我们写个T,咱们叫controller啊,咱们叫controller,好,把这个写个treat,嗯。然后呢,我在这个地方大家看一下,只要记住啊,咱们说一下,只要你是一个控制器叫controller,那你是不是就应该怎么了,你就应该有这样的一个调度的功能,对不对,所以把它就放到了这里啊,然后那我这个地方干嘛呢?叫做混入咱们的t controller啊,咱们的controller好了,那你放到这里之后就可以了呀,那么你放到这里之后,大家想想这是一个抽象方法吧,那么你抽象方法的话,我这里给他重写不就可以了吗?哎,就是这样啊,所以把这个呢,我们去掉,把这个都去掉,嗯。
07:23
好了,那我现在写完以后,那同样道理,我们再回到咱们的service当中,那么service当中这个数据分析也基本上都是什么通用的嘛,所以来new,我们写上咱们叫T,咱们叫service,那这个service呢,也是treat,然后在这个里面我们拿过来把那个service实验,我们原封不动拷贝,拷贝以后我放到这里啊,给他一个咱们叫做冒号,咱们叫做any啊,这个咱们就不要了,好了,那我现在这么写了以后,每一个service应该都有个数据分析的方法,所以我混入一下,咱们叫做with,诶诶,不对,咱们这个地方写上不叫with啊,咱们叫做它,嗯,T,咱们的service,好了,那我现在写完了之后,咱们接着回过头来,回过头来干什么呀,咱们现在的这个地方需要需要什么东西啊,同学们是不是需要那个道儿了,这个道你会发现发现什么东西啊,同学们,你会发现咱们当前的这个。
08:24
Read file,其实每一个持有城都可以读文件,不光能读文件,能不能读买circle啊,能不能读什么h base呀什么,应该也都有这个能力吧,对不对,只是看你怎么去连接了,所以我们的持久城这个应该是一个通用的功能,所以来我们写上叫做什么呢?拿过来我们叫做ta,叫DAO,给他一个treat好放过来,然后把这个代码我是原封不动拿过来,我为什么原封不动拿过来呢?因为他们读取的方式基本都是类似的,都是我们要靠一个环境去读取文件,给我一个pass,对不对?诶,就是这样,所以既然是通用的,那么就好办了,我们把咱们的这个位置打开,咱们写上叫做什么呢?我们的混入把这个加过来就可以了,好,那你现在加过来以后,同学们,我现在的这个地方就有个问题了,什么呢叫SC。
09:22
这个叫SC是啥东西啊,这个SC就是我们的那个上下文环境对象,而这个上下文的环境对象现在没有了,你没有的情况下,那你怎么读取文件呢?也就意味着呀,在咱们当前的这个道这个位置呀,我现在需要一个对象,这个对象干嘛呢?叫做SC,哎,可是我现在怎么了,发现我找不到了,我发现了,现在我没找到啊,那你没找到同学们怎么办?那我得判断一下那个SC在哪儿吧,所以回过头来咱们找一下那个SC在哪儿,咱们那个SC在哪儿啊,他不就在咱们的应用程序当中吗?应用程序当中有个叫t application sc是不是在这儿呢?
10:10
如果你的SC在这儿的话,它只在当前的这个地方有效,那么所以这就意味着在我们这个地方根本就拿不到,为什么它在我们的application当中,对不对?它在application当中,其实它是跟那个controller有关系的,所以SC你可以理解为是什么呢?在这儿我们这个环境啊,不光是包含了我们的这个定位方案,所以把这个SC放这儿。咱们看啊,我们的OB它有个SC,然后呢,我这需要个SC,但是我得不到,你该怎么办,同学们。啊,老师那简单呐,你的SC你先给这个controller传过去,大家看你把它传过去,传过去以后你再给这个传过去,Service再把它传过来,那不就行了吗?所以啊,我们会认为这种方式应该没问题,但是真的没问题吗?首先大家想想这个SC谁用?
11:08
这个SC是不是他用,我问你咱们的C着用吗?不用咱们的service用吗?也不用,你仅仅是为了让别人用,然后呢,把你的对象传过来,你会不会发现它增加了耦合性呢。它增加了我们这个SC跟当前对象的耦合性,所以这个并不是很好,哎,那如果我不这么传的话,那我怎么能够把application的对象当中的SC给他传过来呢?这个我们怎么能够做到,对不对,这是我们需要关心的。那到底怎么做到呢?首先大家有没有发现我画的是一个大的一个方块,叫EV,这个EV除了表示环境以外,还有一个表示。大家想一想,我们之前我们所有的代码都写在了什么位置?都写在了main方法的位置,他们是不是靠一个主线程来执行的,大家想想没问题吧,那么现在你分成了三层架构,我问你,你创建新的线程了吗?
12:13
你没创建对吗?那如果你没创建的情况下,你是不是还在同一个线程当中,所以说这个地方其实还是那个主线程吧。大家想想没问题吧,那既然没问题的话,我如果能够想办法在咱们线程对象当中,我开辟一块内存空间,大家看我在这儿啊,我诶在这儿。我开辟一块内存空间,诶就是这样的,那么开辟的内存空间我干嘛呀,我把咱们的这个地方,大家看我们的SC,我想办法给它加到这里面去,不就完事了吗?所以SC拷贝放到这里去,那么你如果想办法能把SC放进去的话,那我这如果想用的话,我从里面取是不是也就够了,哎,就是这样的,所以呀,你会发现咱们的什么OB啊,什么controller啊,Service啊,Door啊,其实他们都是在什么一个线程当中去处理的啊,只是我们为了让大家呢遵循一个架构模式,把它强制的分开了,但县城可没有变呢。
13:27
那没有变的情况下,是不是就意味着如果能把它放在这块内存当中,那就是OK的呀?好了,那么到底能不能放呢?肯定可以放,而且咱们Java它提供了一个工具类来操作这块内存,这个工具类的名字这个大家可能听说过,叫做什么呢?Thread local。我们的local它就可以啊,来它可以对我们的现成的内存啊,内存进行控制啊,然后呢,存储数据啊,共享数据没有问题,在同一个线程当中,它是可以共享数据的,那好,那怎么用呢?回过头来,同学们看这个是个工具类啊,为什么呢,它可以控制这块内存呢,是一种工具类的感觉,所以我们在咱们的这个U里面,我来创建一个new,创建一个什么东西呢?我们叫做来,我们叫做它,我们叫en nv叫U,就来创建咱们的环境,然后来我们点击OK,在这个地方我们给它来写上一个叫pro啊,咱们叫VL,咱们就叫SC啊,咱们叫做local本地的一个环境,然后等于new叫thread local,然后里。
14:50
边叫Spark,我们的contest,然后拿过来大家看一下,我现在的这个地方就已经把这个写好了,写好了之后干嘛呀,我现在就要往这个线程里面放数据,所以说我们写上叫DF,咱们叫put往里面放啊,那你放数据的话,你就得把数据给我传过来呀,所以我们SC,咱们冒号叫Spark contest,那么干嘛呀,咱们这么写拷贝。
15:21
拷贝以后点我们就叫set,把咱们的SC我放进去,那你能放,你是不是应该能够取,所以呢,DF咱们叫take啊,拿过来,拿过来以后从它往外取是可以的,那么这个呢,就叫做它了,诶往外取,那么你能放,你能取,但是我不用了,能不能删除呢?也可以,咱们叫做clear啊,咱们叫做clear,这个可呢,拿过来我们点一下叫做点我们叫做remove,那么这样的话呢,我的数据可以往线程里面放,也可以从线程往外举,还可以把它清除,对不对?那我们怎么用呢?我们一块儿来看看,这是一个工具类,那么工具类的话,是不是意味着我们在创建SC的时候可以把它放进去呀,所以大家看我们来给它放进去,你放进去的话,点我们叫做什么呢?Put把。
16:21
C放进去,那么你放进去以后,那是不是意味着在我们那个道当中我就可以把它取出来呀,所以说来工具类,咱们来点我们叫take take以后你看没问题,你能把它取出来,好,那我用完了呢,比方说咱们的那个,呃,这呢,我用完了给它stop,那你这个线程中还需要它吗?不需要了,所以呢,来点我们叫clear,你把它清除掉就可以了,对吗?所以整个我们的操作过程当中,就靠的是它中间的这个工具类它来完成啊,哎,老师,那你这个行不行啊。
17:04
你中间都不传数据了,这个数据能不能共享呢?我们来验证一下啊,咱们来验证一下同学们,我们现在呢,给它执行看一看,结果改善了半天,我们的这个程序的这个流程会不会受到影响啊呃,这个里面哦多了一个忘了删掉了,不管它去掉。去掉以后关掉,咱们重新把这个应用程序再跑一遍来运行,运行以后看结果。好,同学们看结果没有问题对吗?跟之前完全一样,但是你会发现我优化后的代码它就更具备通用性,对吗?
我来说两句