从鸭子应用开始。做一套模拟鸭子的游戏,游戏中会有各种各样的鸭子。我们要使用OO技术来实现此系统。
一、定义一个Duck超类,定义鸭子的特性。然后各种不同的鸭子作为子类,继承该Duck超类
1、超类:Duck.java
绿头鸭:MallardDuck.java
/** * 绿头鸭,可以呱呱叫,可以游泳,但是头是绿色的,所以要覆盖display()方法 */ public class MallardDuck extends Duck{ @Override public void display() { System.out.println("我的头是绿色的!"); } } 红头鸭:ReadheadDuck.java /** * 红头鸭,可以呱呱叫,可以游泳,但是头是红色的,所以要覆盖display()方法 */ public class ReadheadDuck extends Duck{ @Override public void display() { System.out.println("我的头是红色的!"); } } 3、测试类TestClass.java //测试鸭子的特性,是否和实际符合 public class TestClass { public static void main(String[] args) { MallardDuck mallardDuck=new MallardDuck();//绿头鸭 ReadheadDuck readheadDuck=new ReadheadDuck();//红头鸭 mallardDuck.display(); mallardDuck.quack(); mallardDuck.swim(); System.out.println("-------------------"); readheadDuck.display(); readheadDuck.quack(); readheadDuck.swim(); } }4、测试结果:
我是绿头鸭! 我可以呱呱叫 我可以游泳 ------------------- 我红头鸭! 我可以呱呱叫 我可以游泳二、基于上面的程序,我们又要对鸭子添加会飞的特性,于是我们在Duck.java超类中添加所有会飞的方法fly()
1、超类:Duck.java
System.out.println("我可以飞");
}} 2、各种不同的鸭子继承于它,绿头鸭,红头鸭不用改动。新加一个橡皮鸭,诱饵鸭
橡皮鸭:RubberDuck.java
/** * 橡皮鸭是吱吱叫的,不会飞的,可以叫,但不是呱呱叫,所以为了实现这些特性,不得不覆盖父类的方法 */ public class RubberDuck extends Duck{ @Override public void display() { System.out.println("我是橡皮鸭!"); } @Override public void fly() { //不会飞 } @Override public void quack() { System.out.println("我可以吱吱叫"); } }诱饵鸭:DecoyDuck.java/** * 诱饵鸭,不会飞,不会叫 */ public class DecoyDuck extends Duck{ @Override public void display() { System.out.println("我是诱饵鸭!"); } @Override public void quack() { //不会叫 } @Override public void fly(){ //不会飞 } } 3、测试类 public class TestClass { public static void main(String[] args) { MallardDuck mallardDuck=new MallardDuck();//绿头鸭 ReadheadDuck readheadDuck=new ReadheadDuck();//红头鸭 RubberDuck rubberDuck=new RubberDuck();//橡皮鸭 DecoyDuck decoyDuck=new DecoyDuck();//诱饵鸭 mallardDuck.display(); mallardDuck.quack(); mallardDuck.swim(); mallardDuck.fly(); System.out.println("-------------------"); readheadDuck.display(); readheadDuck.quack(); readheadDuck.swim(); readheadDuck.fly(); System.out.println("-------------------"); rubberDuck.display(); rubberDuck.quack(); rubberDuck.swim(); rubberDuck.fly(); System.out.println("-------------------"); decoyDuck.display(); decoyDuck.quack(); decoyDuck.swim(); decoyDuck.fly(); } }
4、测试结果:
我是绿头鸭! 我可以呱呱叫 我可以游泳 我可以飞 ------------------- 我是红头鸭! 我可以呱呱叫 我可以游泳 我可以飞 ------------------- 我是橡皮鸭! 我可以吱吱叫 我可以游泳 ------------------- 我是诱饵鸭! 我可以游泳可以看到,为了实现橡皮鸭和诱饵鸭的这些特性,我们不得不重写Duck父类的很多方法,并给出空的实现。如果,以后还添加一些特别的鸭子,我们不得不都去覆盖父类的方法。会造成许多缺点。
代码在多个子类中重复,很难知道所有鸭子的全部行为,鸭子的行为不容易改变,改变会牵一发而动全身,造成其他鸭子不想要的改变。
三、所以,可以明白上面的用超类继承的方法是不可用的。下面我们试试用接口如何。
因为不是所有的鸭子都会飞,不是所有鸭子都会叫,所以,将fly()方法拿出来,作为Flyable接口 ,将quack()方法拿出来,作为Quackable接口。
1、超类:Duck.java
Flyable接口:Flyable.java
3、所有子类可以根据自己的特性,选择性的实现这两个接口
绿头鸭:
红头鸭: /** * 红头鸭,会飞,会叫,实现两个接口 */ public class ReadheadDuck extends Duck implements Flyable,Quackable{ @Override public void display() { System.out.println("我是红头鸭!"); } @Override public void quack() { System.out.println("我会呱呱叫"); } @Override public void fly() { System.out.println("我会飞"); } }
橡皮鸭: /** * 橡皮鸭是吱吱叫的,不会飞的,所以实现Quackable接口 */ public class RubberDuck extends Duck implements Quackable{ @Override public void display() { System.out.println("我是橡皮鸭!"); } @Override public void quack() { System.out.println("我可以吱吱叫"); } }
诱饵鸭: /** * 诱饵鸭,不会飞,不会叫,不需要实现接口 */ public class DecoyDuck extends Duck{ @Override public void display() { System.out.println("我是诱饵鸭!"); } }
3、测试类 public class TestClass { public static void main(String[] args) { MallardDuck mallardDuck=new MallardDuck();//绿头鸭 ReadheadDuck readheadDuck=new ReadheadDuck();//红头鸭 RubberDuck rubberDuck=new RubberDuck();//橡皮鸭 DecoyDuck decoyDuck=new DecoyDuck();//诱饵鸭 mallardDuck.display(); mallardDuck.quack(); mallardDuck.swim(); mallardDuck.fly(); System.out.println("-------------------"); readheadDuck.display(); readheadDuck.quack(); readheadDuck.swim(); readheadDuck.fly(); System.out.println("-------------------"); rubberDuck.display(); rubberDuck.quack(); rubberDuck.swim(); System.out.println("-------------------"); decoyDuck.display(); decoyDuck.swim(); } }4、结果: 我是绿头鸭! 我会呱呱叫 我可以游泳 我会飞 ------------------- 我是红头鸭! 我会呱呱叫 我可以游泳 我会飞 ------------------- 我是橡皮鸭! 我可以吱吱叫 我可以游泳 ------------------- 我是诱饵鸭! 我可以游泳
可以发现,我们能实现这些功能,正确的表示鸭子的特性,可是,代码的重复变的更多了,并且无法复用了。如果,鸭子的种类变的更多,我们不得不去修改很多鸭子中的方法。所以,用接口的方法,也是不行的。下面,就该考虑使用我们的策略者模式了。