课时83:模板设计模式
摘要:
1.抽象类的定义
2.抽象类的实际应用
3.范例:实现代码
01.抽象类的定义
抽象类的本质上就属于一个加强型的类,那么对于类已经清楚了,可以描述一切的有关的现实事物,但是通过分析也可以发现抽象类的设计应该是比类更高一层的定义。
例如,有一个抽象位,用紫色文字描述,告知读者此处有一个抽象位 Abstract ,抽象位在整个设计过程中是必须的,尽管按照这种结构化设计,普通位应该在抽象位的下一步实现定义结构。因此,抽象位的操作应该比普通位更高一档。
02.抽象类的实际应用
那么下面来研究一下抽象类的实际应用。假设现在要描述有三类事物:
机器人:不休息,只知道补充能量和工;
人类:需要休息,需要吃饭,并且需要努力工作;
猪:需要休息,而不需要工作,只需吃饭。
因此人不努力工作就是猪。
例如,人类,机器人,猪。那么无论你是谁,只要获得这个对象,就能向你发出命令。通过一个按钮来指示开始工作。无论是机器人、人还是猪,它们都会对这样的指令做出反应。比如当命令吃饭时,无论是猪还是人,都会有所反应,这说明它们都有感知。如果去睡觉,人有反应,猪有反应,但是机器人没有反应。现在要求描述的是这样一个范围。
现在已经给三类描述。一类是机器人类,一类是人类,机器人和人类都有一份各自的范围描述,猪类也有一个操作。因此首先得出一个结论,有三种类型。但是现在的要求是需要有一种操作方式能够统一处理这些行为。机器人应该能够执行机器人的操作。在定义类的时候,应当考虑抽象类作为一个公共的集合点。假设有一个操作者在这个场景中,那么操作者应该以抽象类为基准。
生活中会遇到很多遥控器,如电视遥控器和空调遥控器。通常所有的遥控器都会使用到,空调或电视通常需要接通电源后才能操作,通过不同的方式不同的操作选项可以实现不同的效果。那么从用户或操作者的角度考虑,是否应该有一个公共的操作点来代表所有的具体类型呢?这个类不是具体的,它应该对三类操作进行某种抽象。
三类操作可以抽象的是行为。
+ eat(): void ; + sleep() : void ; + work() : void ;
因此,操作者是基于行为来判断的,而不是以具体的实物为主。人有人的行为,机器人有机器人的行为,猪也有猪的行为。正如之前所提到的,就像一个遥控器,人应该在一个能够发出命令的环境中给机器人发出命令。因此现在需要在这个地方对命令进行处理。在整个代码中,应该准备一个环节,让你能够接收指令。
+command(int code):void;
如果学过数字编码与非门的话,应该知道所有的遥控器都是与非门的设计结果。不同的操作或命令,例如频道上翻和下翻,能够带来不同的效果。频道上翻对应01,频道下翻对应10。每种操作或命令都应该有其特定的编码。所以需要为每种操作编译相应的编码。在代码中,如果传入的参数是一,可能认为它代表睡觉;如果是二,代表吃饭;如果是三,代表工作。
Eat=1; Sleep=5; Work=10;
如果用123,就是吃+睡=工作,在这种情况下,不会考虑将1、2、3相加的情况,而只关注一个结果,因为它们相加绝对不会得到第三个值。请记住在整个处理过程中,需要为它设置一些命令代码。这个程序是根据这些命令代码来实现的。
这个代码就是一个常量,因此根据这样的结构,可以实现当前设计的处理经济。来审视这段代码,探讨如何编写得更为合适。首先,行为是一个绝对抽象的概念。
03.范例:实现代码
行为是一个明确的抽象概念。既然是抽象,将用 abstract 进行声明。在整个代码中,给一个没有内容的抽象类。吃是一种标准的行为,行为是抽象的,它一定是个抽象的行为。而后具体的事物实现这个抽象行为,你睡觉能跟猪的睡觉方式一样吗?
Astract class action { public static final int EAT=1 ; public static final int SLEEP=5: public static final int WORK=10; public void command(int code){ switch(code){ case EAT :{ This.eat(); Break; } Case sleep:{ This.sleep(); Break; } Case work:{ This.work(); Break; } Case eat+sleep+work:{ This.eat(); This.sleep(); This.work(); Break; } } } public abstract void eat(); public abstract void sleep(); public abstract void work(); } Class robot extends action{ public void eat(){ System.out.println(“机器人需要接通电源充电。”); } public void sleep(){} public void work(){ System.out.println(“机器人按照固定的套路进行工作。”); } } Class person extends action{ public void eat(){ System.out.println(“饿的时候安静的坐下吃饭。”); } public void sleep(){ System.out.println(“安静的躺下,慢慢的睡着,而后做着美丽的春梦。”); } public void work(){ System.out.println(“人类是高级脑类动物,所有要有想法的工作。”); } } Class pig extends action{ public void eat(){ System.out.println(“吃食槽中的人类的剩饭。”); } public void sleep(){ System.out.println(“倒地就睡。”); } public void work(){} } public class JavaDemo { public static void main(string args[]){ Action robotAction = new Robot(); Action personAction = new Person(); Action pigAction =new pig(); System.out.println(“---------机器人行为----------”); robotAction.command( Action.sleep); robotAction.command( Action.work); System.out.println(“---------人类的行为----------”); personAction.command( Action.sleep+Action.eat+Action.work); System.out.println(“---------猪类的行为----------”); pigAction.work(); pigAction.eat(); } }
现在的程序已经完整实现了一个行为的抽象处理。但是也需要进行一些思考。现在定义的 Action 的父类主要的目的,对所有行为规范进行统一处理。假设目前只考虑一个子位,即机器人的子位。如果想让机器人补充能量,必须执行Eat方法。但如果想自行编写一个ADD方法来补充能量,这个方法父类不知道。
Class robot extends action{ public void eat(){ System.out.println(“机器人需要接通电源充电。”); } Public void add(){//这个方法父类不知道 } public void sleep(){} public void work(){ System.out.println(“机器人按照固定的套路进行工作。”); }
在执行操作时没有按照父类要求实现相应的方法,那么能量补充是不上。因此在这样的整体设计环境中,父类提供了一个操作模板。当填写任何表格时,都需要填写姓名、年龄、民族、籍贯,几乎所有的表格都会要求填写这些基本信息,先填写姓名,接着是生日,然后是籍贯,最后是民族。
姓名2009年10月10日,生日林小强,籍贯汉,民族广州。
现在有一个程序在读取数据时会出错,如果程序仅采用固定的方式编写,那么这种流程与模板非常相似。抽象类最大的好处对子类方法的统一管理,二是可以自身提供一些普通方法并且这些普通方法可以可以调用抽象方法(这些抽象方法必须由子类提供实现,否则它们将不会生效)。
通过这个代码应该明白,这种设计形式实质上是一种模板结构设计,为实现特定功能,需要按照父类要求重写方法。父类在编写时,自然会遵循标准进行调用。如果不遵循其标准行为,那么很抱歉,这些方法的代码将永远无法被调用,从而导致程序出现问题,这就是抽象类的使用。再次强调抽象类的使用确实是一门技术活,若想将抽象类运用至极致,这将是一段漫长的旅程。