章前准备
不同的考虑方式会得到不同的结果,比如我们之前处理的ifif,第一次封装成方法,第二次"封装"成对象,第三次创造(封装)一个控制之前封装对象的容器,以此实现流程与实现的分离,比如
/** * @author 程猿 * 封装流程方式 */ public class Paint { private Pipel pipel; public void setPipel(Pipel pipel) { this.pipel = pipel; } public static void main(String[] args) { Paint paint = new Paint(); //初始化paint,可以使用-->ioc //Pipel pipel = new IfElsePipel(); Pipel pipel = new IfIfPipel(); pipel.add(new PrintLF()); pipel.add(new PrintSL()); pipel.add(new PrintXMR()); pipel.add(new PrintSZ()); paint.setPipel(pipel); //调用 paint.print(new String[]{"lf","sl"},"", ""); } void print(String[] scene,String name,String id){ pipel.invoke(scene, name, id); } }
那我们换个方式,我认为这个方法中添加Print容器是很奇怪的,我对他进行修改,比如
/** * @author 程猿 * 管理流程的实现交给Paint * 即Paint就是pipel */ public class Paint implements Pipel { List<Print> prints = new ArrayList(); public static void main(String[] args) { Paint paint = new Paint(); // 初始化paint,可以使用-->ioc paint.add(new PrintLF()); paint.add(new PrintSL()); paint.add(new PrintXMR()); paint.add(new PrintSZ()); // 调用 paint.print(new String[] { "lf", "sl" }, "", ""); } void print(String[] scene, String name, String id) { invoke(scene, name, id); } public void invoke(String[] scene, String name, String id) { for (Print print : prints) { print.print(scene, name, id); } } @Override public void add(Print print) { prints.add(print); } }
当然处理这种ifif类型的问题肯定是非常常见的,就像ifelse中的servlet一样,java大叔肯定会尽量提供一种较为通用的解决方案,比如所谓的观察者,至少在看到观察者这种模式之前,我是想象不到还能这样处理,不敢怎样,将我们的呆使用自带的观察者试试吧
/** * @author 程猿 *使用jdk自带的观察者模式 */ public class Paint extends Observable { private String[] scene; public static void main(String[] args) { Paint paint = new Paint(); new PrintSZ(paint); new PrintSL(paint); new PrintLF(paint); paint.print(new String[] { "lf", "sl" }, "", ""); } void print(String[] scene, String name, String id) { this.scene=scene; setChanged(); notifyObservers(); } public String[] getScene() { return scene; } }
public class PrintLF implements Observer { Observable obs; public PrintLF(Paint paint) { obs=paint; paint.addObserver(this); } @Override public void update(Observable o, Object obj) { Paint p=(Paint)o; if(Arrays.asList(p.getScene()).contains("lf")){ System.out.println("路飞"); } } }
接口print我就直接干掉了(这只是懒。。。),当然这里使用观察者合适不合适先不管,感受一下区别吧,我认为大概有3个不同
1.在我们处理ifif问题时,通过封装和容器进行处理,当然容器与我们的业务(Print)
2.我们建立主对象与从对象关系是依靠add这种组合方式,观察者的从对象如果没有主对象显然没有存在的价值
3.最重要的是,观察者提供了一种思考问题,解决问题的方式,被观察者看起来可以在任何时候被添加进行,而在处理ifif中的问题,总让人觉得必须在某个地方一次完成初始化
第六章 生命周期
生命周期完全可以通过ifif(多种流程,不一定要if)的解决方式处理,通过此章以及对观察者的了解,让我再次对面向对象有了新的理解
面向对象是什么?
编程从机器码开始,不好记,改成了助记符(简单的说)-->汇编,在使用汇编时要关注3个区域,数据区域,入口区域,以及逻辑区域,程序猿可以正常的码了,但是作为一代码农,所谓的软件工程师,竟然需要了解硬件(如果用汇编的话),增加学习成本,提升了程序猿的个人价值,简单的说就是人不好招,还贵....那么新的语言就出现了,面向过程语言,主要关注与数据与过程,由助记符(汇编)演化而来,现在想来就是汇编最为直接的封装,编译的时候需要确定一下硬件就行了,程序猿再也不管什么硬件了,安静的软下去就好,做为这种数据与逻辑分离的思考方式,了解数据结构,了解算法设计就成了软见得代码,妈蛋,数据结构就不是人看的,搞算法设计的至少得当个研究僧吧....我们平时所思考,所见到的就不是数据和逻辑分离,软件工程师的学历依然不低,如果换一种思考方式,比如面向对象,是不是就简单了?比如男人会撒谎,母猪会上树,放以前我们需要男人和母猪的结构,在加上撒谎和上树的算法,那么现在男人下面加个撒谎的方法,母猪下面加个上树的方法就行了,和你想象中的一样,不需要分开,至此软件工程师的要求已经低到冰点以下,只要你会说话,脑经能转,看个基本语法就能当软件工程师了,这要求,在加上以前对软件工程师的高大上认识和待遇,码农大军轻轻松松变成搬砖大军
你说跨机器(平台)?这是顺带的,c也是跨机器的,只要告诉他指定的硬件,分分钟给你搞定,如果把这个指定硬件的任务封个装,变成一个工作平台的话,那就实现了你所想要的,在换个方式说,c将指定硬件的工作交给人,人来决定那个平台,你想怎么跨都行...java将指定硬件的工作交给jvm,机器环境必须装有jvm,如果jvm不被称为平台的话,那java赢了(这不是关键,关键是思考的方式不一样)
又跑题了,我的意思是说java做为面向对象语言,参考的方式是事物(对象)拥有方法,方法单独丢出来那个过程语言玩的方式,但是光这么玩会造成类多的你想吐,你需要使用一些面向过程的方式去处理,那这种不依靠面向对象方式去思考的方式说成面向过程肯定是不被允许的,那我们给他一个好听和通用的名字,俗称设计模式
所以我理解的设计模式,就是使用面向对象的思考方式解决会出现N多让人蛋疼事情时的解决方案,如果将编程方式理解为只有面向对象和面向过程的话,模式就是混合的思考方式,比如撒谎的方式有很多,为每个男人写实现当然可以,最后发现男人的谎话就那几条。。。我去找知道用面向过程了- -那就用呗,策略什么的还不够数据与过程分离啊
说道数据与过程分离,就让我想到令人伤心的bi屌丝程序猿的悲哀,我们只能写写前台,写写server,其实好好想想jsp不就是servlet吗?server写在jsp不行啊,我发现以前还真是这样干的,传说中的model1时代,传说要数据与逻辑分离,恩,这不就是过程化思考方式?好听点用策略或者组合轻轻松松搞定,搞毛线,什么MVC,什么MVP,搞那么高大上,吓死我了
又跑题了,回想一下我们tomcat实现的过程,从开始我们是以绝对的面向对象来处理问题的,直到第一次面对无休止的ifelse时,第一次面对ifif时,我们甚至会开始怀疑,我去,都是面向对象的思考方式,为毛我想不到?因为他们是从面向过程时代转换过来的- -再或者说无论是汇编,面向过程还是面向对象都需要考虑三块内容,结构,过程和入口(控制台),面向对象综合处理了结构和过程,对控制台的影响并没有专门的描述,你也会发现大多数设计都需要我们使用控制台(就是ioc啦)