软件设计模式Day01--简单的模拟鸭子应用

本文探讨了在鸭子模拟游戏中,如何从最初使用继承导致的问题转向使用接口和行为类的设计模式。通过引入FlyBehavior和QuackBehavior接口,实现了鸭子行为的抽象,使得不同类型的鸭子可以根据自身特性实现不同的行为,如飞行和叫声。这种设计遵循了开闭原则,提高了代码的灵活性和可复用性。示例代码展示了如何通过行为接口和实现类实现不同鸭子的行为差异化。
摘要由CSDN通过智能技术生成

问题描述:模拟鸭子游戏

鸭子分为绿头鸭子、红头鸭子、橡皮鸭子、诱饵鸭子,鸭子有的会游泳,有的会飞、有的会呱呱叫、有的会吱吱叫、外表不一样。

问题解决:

问题中所有的鸭子都会叫quack也会游泳swing,通过超类负责处理这部分代买,每种鸭子的外表都不一样,所以display()方法是抽象方法。

现在我们让鸭子飞起来:

我们在duck类中加上fly()方法,然后所有的鸭子都会继承fly()。

通过这样的设计,发生了可怕的问题:

并不是所有的鸭子都会飞(如橡皮鸭),在超类中加上fly(),就导致了所有的子类都具备fly(),连那些不具备fly()的子类也无法免除,说明了继承并不是一个实现的很好方法。

当然我们可以覆盖父类中的方法,如橡皮鸭类RubberDuck中的fly()方法覆盖掉(什么都不做);诱饵鸭类DecoyDuck要不具有其他的行为,只需要disply()方法。

继承不可以我们可以考虑使用接口吗?

从分析来看,使用继承来实现鸭子模拟游戏,当然也可以实现,但是这将会是对方法的多次覆盖,如fly()、quack().........................对一个程序员来来说,简直是一个无穷尽的恶梦!!!

然而,我们可以考虑使用接口,将fly()、quack()等存在变化的方法取出来。fly()放进一个Flyable接口中,只有会飞的鸭子才会实现此接口,同样的方式qucak()等方法也一样。从而得到如下的设计:

很明显,重复的代码变得更多了。使用接口解决了一部分问题(如不会有会飞的橡皮鸭),但是无法达到代码的复用,达不到设计的目的。只能再重新设计。。。。。。

问题解决的思想:

设计原则:找出可能需要变化的地方,把他们独立出出来,不要和那些不需要变化的代码混在一起。把会变化的部分取出来并封装好,让其他部分不会受到影响。这样一来代码变化之后,出其不意的部分变得很少,系统变得更加有弹性。

设计鸭子的行为:

设计原则:针对接口编程,而不是针对实现编程。

也就是说,鸭子的行为将被放在分开的类中,此类专门提供某行为的实现。这样,鸭子就不需要知道行为的实现细节。

我们利用接口代表每个行为,比方说,FlyBehavior与QuackBehavior,而行为的每个实现都必须实现这些接口之一。鸭子类Duck就不会负责实现Fly和Quack接口,反而是由其他类专门实现FlyBehavior和QuackBehavior,也就是行为类实现行为接口,二不是由Duck类实现行为接口。

部分实现代码:

  • FlyBehavior接口:
public interface FlyBehavior {
	
	public void fly();
}
  • FlyWithWings行为类实现会飞的行为:
package son;

import bb.FlyBehavior;

//会飞的行为
public class FlyWithWings implements FlyBehavior {

		public void fly() {
			System.out.println("I can fly");
		}
}

  • FlyNoWay行为类实现不会飞的行为:
package son;

import bb.FlyBehavior;

//不会飞的行为
public class FlyNoWay implements FlyBehavior {
	
	public void fly() {
		System.out.println("I can't fly");
	}

}
  • QuackBehavior接口:
package bb;

public interface QuackBehavior {

	public void quack();
}
  • Quack行为类,实现呱呱叫行为:
package son;

import bb.QuackBehavior;

public class Quack implements QuackBehavior {
	
	public void quack() {
		System.out.println("我能呱呱叫!!");
	}
}
  • Squack行为类,实现吱吱叫行为:
package son;

import bb.QuackBehavior;
public class Squeak implements QuackBehavior{
	
	public void quack() {
		System.out.println("我能吱吱叫!!");
	}
}
  • MuteQuack行为类,不会叫的行为:
package son;

import bb.QuackBehavior;
public class Squeak implements QuackBehavior{
	
	public void quack() {
		System.out.println("我不能叫!!");
	}
}

通过这样的设计,可以让鸭子的动作被其他对象复用,因为这些对象已经和鸭子类无关了。

整合鸭子的行为:

首先在鸭子类中加入两个实例变量flyBehavior和quackBehavior,声明为借口类型。

	public FlyBehavior flyBehavior; //飞的行为
	public QuackBehavior quackBehavior;//叫的行为

实现fly()和quack()应有的行为。不亲自处理,委托给借口对象来实现。

	public void performQuack() {//叫的行为
		quackBehavior.quack();
	}
	public void performFly() {//飞的行为
		flyBehavior.fly();
	}

整合MallardDuck类(其他鸭子类也是使用同样的方法):

package son;
import bb.Duck;
//绿头鸭---叫、飞、外表
public class MallarDuck extends Duck{
	public MallarDuck() {//构造函数,对鸭子的行为进行处理
		flyBehavior = new FlyWithWings();
		quackBehavior = new Quack();
	}
	public void display() {
		System.out.println("外观是绿头的");
	}	
}

代码测试:

编写测试类并运行:

package Main;
import bb.Duck;
public class Main {
	public static void main(String arg[]) {
		Duck Mallar = new MallarDuck();
		Mallar.performQuack();
		Mallar.performFly();

	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值