一、策略者模式(Strategy Pattern)----1

本文介绍了通过面向对象编程和接口实现鸭子模拟系统的概念和实践,包括鸭子类的定义、不同鸭子类的继承、引入接口以增强系统灵活性,以及最终使用策略者模式解决代码冗余问题的过程。讨论了每种方法的优缺点,最终转向策略者模式以更高效地管理鸭子行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从鸭子应用开始。做一套模拟鸭子的游戏,游戏中会有各种各样的鸭子。我们要使用OO技术来实现此系统。

一、定义一个Duck超类,定义鸭子的特性。然后各种不同的鸭子作为子类,继承该Duck超类

1、超类:Duck.java

/** * 所有鸭子的父类,定义了鸭子的特性 */ public class Duck { public void quack(){ System.out.println("我可以呱呱叫"); } public void swim(){ System.out.println("我可以游泳"); } public void display(){ } } 2、各种不同的鸭子继承于它

绿头鸭: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

/** * 所有鸭子的父类,定义了鸭子的特性 */ public class Duck { public void quack(){ System.out.println("我可以呱呱叫"); } public void swim(){ System.out.println("我可以游泳"); } public void display(){ } public void fly(){
                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

/** * 所有鸭子的父类,定义了鸭子的特性 */ public class Duck { public void swim(){ System.out.println("我可以游泳"); } public void display(){ } } 2、Flyable接口,Quackable接口

Flyable接口:Flyable.java

/** * 会飞的鸭子实现此接口 */ public interface Flyable { void fly(); } Quackable接口:Quackable.java

/** * 会叫的鸭子实现此接口 */ public interface Quackable { void quack(); }
3、所有子类可以根据自己的特性,选择性的实现这两个接口

绿头鸭:

/** * 绿头鸭,会飞,会叫,实现这两个接口 */ public class MallardDuck 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("我会飞"); } }
红头鸭:

/** * 红头鸭,会飞,会叫,实现两个接口 */ 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、结果:

我是绿头鸭! 我会呱呱叫 我可以游泳 我会飞 ------------------- 我是红头鸭! 我会呱呱叫 我可以游泳 我会飞 ------------------- 我是橡皮鸭! 我可以吱吱叫 我可以游泳 ------------------- 我是诱饵鸭! 我可以游泳
可以发现,我们能实现这些功能,正确的表示鸭子的特性,可是,代码的重复变的更多了,并且无法复用了。如果,鸭子的种类变的更多,我们不得不去修改很多鸭子中的方法。所以,用接口的方法,也是不行的。下面,就该考虑使用我们的策略者模式了。




































                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值