动态多态分析及简单工厂模式分析
首先我们要知道动态多态是通过父类的引用指向子类的实例来实现的;
做了很多动态多态的题后;下图就是一个我们实现动态多态时常用的一个工厂化模式;
例题一:一只猫叫了,其他的猫也跟着有反应;人也有反应;老鼠也有反应;
在这里我们就可以分析,猫叫、猫有反应,老鼠也可以叫、老鼠也有反应,人也可以叫、人也有反应。
那么它们就可以共同指向一个可以有叫方法和反应方法的父类。
父类:动物 package com.inba.maya.dongwu; public class DongWu { protected String name; public void Jiao(){ } public void JingJue(){ } }
子类:人 package com.inba.maya.dongwu; public class Ren extends DongWu { private String name="小明"; public void Jiao(){ } public void JingJue(){ System.out.println(name+"说:臭猫别叫了!"); } }
子类:老鼠 package com.inba.maya.dongwu; public class LaoShu extends DongWu { private String name="老鼠"; public void Jiao(){ } public void JingJue(){ System.out.println(name+"说:猫来了快跑!"); } }
子类:猫 package com.inba.maya.dongwu; public class Mao extends DongWu { private String name="其他的猫"; public void JingJue(){ System.out.println(name+"说:别吵了睡觉呢!"); } public void Jiao(DongWu[] dw){ for(int i=0;i<dw.length;i++){ dw[i].JingJue(); } } } //注意因为是猫叫,引起其他动物的警觉方法; //那么我在重写Mao中的jiao方法时,就要写出其他动物的jingjue方法; //在这里我采用循环遍历每个方法(当然不嫌麻烦可以挨个写); //以为在循环遍历时时一个数组所以要以定义一个DongWu型的数组。 //注意:我们都知道上图所示的工厂化模式,仔细看DongWu[] dw不正是父类的引用吗!dw[i].JingJue不正是父类的引用指向子类的实例吗!虽然没有看到如上图所示的使用类,但是经过分析
我们知道我们只是把当前Mao作为使用类了。所以说灵活运用很重要。
package com.inba.maya.ceshi; import com.inba.maya.dongwu.*; import com.inba.maya.qiche.*; import com.inba.maya.siji.*; public class Text { public static void main(String[] args){ DongWu[] dw=new DongWu[3]; dw[0]=new Mao(); dw[1]=new LaoShu(); dw[2]=new Ren(); Mao m=new Mao(); m.Jiao(dw); } } 首先因为当猫叫的时候,所有动物都要调用jingjue的方法,所以我就要用new出所有的对象,那么我先要new父类,因为是个数组,所以先定义数组长度,后new出每个对象;
最后如上一部分代码所说,我们把Mao当成了使用类,所以就要new一个Mao,然后调用其中的叫方法;紧跟着的是填入猫叫后有反应的对象,很显然是dw。
例题2:输入两个数和+、-、*、/来进行计算;
第一种方法(这不是多态的,但是非常简便)注意:无论做什么都要根据情况而定,灵活运用;
父类:运算类 package com.inba.maya.yunsuan; public class JiSuan { protected double num1; protected double num2; public void YunSuan(){ } } 子类:加 package com.inba.maya.yunsuan; public class Jia extends JiSuan { public Jia(double n1,double n2){ this.num1=n1; this.num2=n2; } public void YunSuan(){ System.out.println(this.num1+this.num2); } } 子类:减 package com.inba.maya.yunsuan; public class Jian extends JiSuan { public Jian(double n1,double n2){ this.num1=n1; this.num2=n2; } public void YunSuan(){ System.out.println(this.num1-this.num2); } } 子类:乘 package com.inba.maya.yunsuan; public class Cheng extends JiSuan { public Cheng(double n1,double n2){ this.num1=n1; this.num2=n2; } public void YunSuan(){ System.out.println(this.num1*this.num2); } } 子类:除 package com.inba.maya.yunsuan; public class Chu extends JiSuan { public Chu(double n1,double n2){ this.num1=n1; this.num2=n2; } public void YunSuan(){ System.out.println(this.num1/this.num2); } }
package com.inba.maya.ceshi; import java.util.Scanner; import com.inba.maya.dongwu.*; import com.inba.maya.qiche.*; import com.inba.maya.siji.*; import com.inba.maya.yunsuan.*; public class Text { public static void main(String[] args){ Scanner sc=new Scanner(System.in); double n1=sc.nextDouble(); String fh=sc.next(); double n2=sc.nextDouble(); JiSuan js=null; if(fh.equals("+")){ js=new Jia(n1,n2); }else if(fh.equals("-")){ js=new Jian(n1,n2); }else if(fh.equals("*")){ js=new Cheng(n1,n2); }else if(fh.equals("/")){ js=new Chu(n1,n2); }else{ System.out.println("输入错误!"); } if(js != null){ js.YunSuan(); } } }
第二种方法(动态多态)
在这里由于父类与子类同上一方法相同,我就不再贴了。我只把使用类和主函数分析一下。
在这种方法中,我是把具体的运算细节放到了主函数中运行。
使用类: package com.inba.maya.shiyong; import com.inba.maya.yunsuan.*; public class ShiYong { public void YunSuan(JiSuan js){ js.YunSuan(); } } //定义一个使用类,其中的方法中定义一个父类类型的引用,用这个引用便会调出子类的YunSuan方法
主函数:main
package com.inba.maya.ceshi; import java.util.Scanner; import com.inba.maya.shiyong.ShiYong; import com.inba.maya.yunsuan.*; public class Text { public static void main(String[] args) {
//在控制台输入 Scanner sc=new Scanner(System.in); double n1=sc.nextDouble(); String fh=sc.next(); double n2=sc.nextDouble();
//实例化使用类 ShiYong sy=new ShiYong();
//定义一个父类的引用;赋值为空,当然也可以在输出的地方赋值为空,为什么要赋值为空?
为了使代码更加优化,如果不给一个初始的控制,那么在我new一个Jia()或者Jian()时,我就要紧跟着调用sy.YunSuan,这样显得很繁琐。
JiSuan js=null; if(fh.equals("+")){ js=new Jia(n1,n2); }else if(fh.equals("-")){ js=new Jian(n1,n2); }else if(fh.equals("*")){ js=new Cheng(n1,n2); }else if(fh.equals("/")){ js=new Chu(n1,n2); }else{ System.out.println("输入错误!"); }
最后判断,看js是否new了一个对象,如果new了就执行使用类中的YunSuan,并且把当前对象js传进去。js是谁,就调用谁的子类中的YunSuan方法;这就是父类的引用指向子类的实例 if(js != null){ sy.YunSuan(js); } } }
第三种方法:(动态多态)
在这里由于父类与子类同上一方法相同,我就不再贴了。我只把使用类和主函数分析一下。
在这种方法中,我是把具体的运算细节放到了使用类中运行。
使用类: package com.inba.maya.shiyong; import com.inba.maya.yunsuan.*; public class ShiYong { //首先使用父类引用指向子类的方法 public void YunSuan(JiSuan js){ js.YunSuan(); } //接着重载一下YunSuan方法,传进三个参数,进行判断后左后调用参数为js的YunSuan方法 public void YunSuan(double n1,String fh,double n2){ JiSuan js=null; if(fh.equals("+")){ js=new Jia(n1,n2); }else if(fh.equals("-")){ js=new Jian(n1,n2); }else if(fh.equals("*")){ js=new Cheng(n1,n2); }else if(fh.equals("/")){ js=new Chu(n1,n2); }else{ System.out.println("输入错误!"); } if(js != null){ this.YunSuan(js); } } }
package com.inba.maya.ceshi; import java.util.Scanner; 主函数: 因为我在实用类中,设计了计算的细节,那么在主函数中我只需要,对使用类实例化,然后调用里面的参数为(n1,fh,n2)的YunSuan方法。 import com.inba.maya.shiyong.ShiYong; import com.inba.maya.yunsuan.*; public class Text { public static void main(String[] args) { Scanner sc=new Scanner(System.in); double n1=sc.nextDouble(); String fh=sc.next(); double n2=sc.nextDouble(); ShiYong sy=new ShiYong(); sy.YunSuan(n1,fh,n2); } }