SimulateDuck游戏
场景:J o e上班的公司做了一套相当成功的模拟鸭子游戏:SimulateDuck。游戏中出现各种鸭子, 一边游泳戏水, 一边呱呱叫。此系统的内部设计使用了标准的O O 技术, 设计了一个鸭子超类(Superclass),并让各种鸭子继承此超类。
public abstract class Duck {
public void quack(){
System.out.println("呱呱-----");
}
public void swim(){
System.out.println("Swiming-----");
}
public abstract void display();
}
class MallardDuck extends Duck{
public void display() {
System.out.println("绿头-----");
}
}
class ReadheadDuck extends Duck{
public void display() {
System.out.println("红头-----");
}
}
说明:设计了一个鸭子超类(Duck),并让各种鸭子继承此超类,并实现Duck中的抽象方法。该方法实现简单,但是子类和父类的关系紧密,即耦合度高。
增加场景:主管认为, 此模拟程序需要会飞的鸭子。
Joe更改Duck类如下:
public abstract class Duck {
public void quack(){
System.out.println("呱呱-----");
}
public void swim(){
System.out.println("Swiming-----");
}
public abstract void display();
public void fly(){
System.out.println("Flying-----");
}
}
说明:该更改后导致所有的鸭子都会飞了,包括橡皮鸭子,导致改结果的原因是因为其在父类当中直接增加方法,而子类直接继承。故用继承的方法扩展性不好,虽然该方法复用性比较好。
更改实现方法:将fly 和 quack 方法取出,分别放入接口Flyable 和 Quackable,然后子类来继承这些接口
public abstract class Duck {
public void swim(){
System.out.println("Swiming-----");
}
abstract void display();
}
interface Flyable {
public void fly();
}
interface Quackable {
public void quack();
}
class MallardDuck extends Duck implements Flyable,Quackable{
void display() {
System.out.println("绿头-----");
}
public void fly() {
System.out.println("Flying-----");
}
public void quack() {
System.out.println("呱呱-----");
}
}
class RedheadDuck extends Duck implements Flyable,Quackable{
void display() {
System.out.println("红头-----");
}
public void fly() {
System.out.println("Flying-----");
}
public void quack() {
System.out.println("呱呱-----");
}
}
class RubberDuck extends Duck implements Quackable{
void display() {
System.out.println("橡皮鸭-----");
}
public void quack() {
System.out.println("吱-----");
}
}
class DecoyDuck extends Duck{
void display() {
System.out.println("诱饵鸭----");
}
}说明:采用接口,所有的子类都要去继承接口Flyable 和 Quackable,重复的代码太多,复用性和扩展性都不好,说明用接口也不是一个好的办法。
更改实现:用多态实现。。。
interface FlyBehavior{
public void fly();
}
class FlyWithWings implements FlyBehavior{
public void fly() {
System.out.println("Flying-----");
}
}
class FlyNOWay implements FlyBehavior{
public void fly() {}
}
interface QuackBehavior{
public void quack();
}
class Quack implements QuackBehavior{
public void quack() {
System.out.println("呱呱-----");
}
}
class Squack implements QuackBehavior{
public void quack() {
System.out.println("吱吱-----");
}
}
class MateQuack implements QuackBehavior{
public void quack() {}
}
abstract class Duck implements FlyBehavior,QuackBehavior {
private FlyBehavior f;
private QuackBehavior q;
public void swim(){
System.out.println("Swiming-----");
}
abstract void display();
public void setFlyBehavior(FlyBehavior ff){
f = ff;
}
public void setQuackBehavior(QuackBehavior qq){
q = qq;
}
public void fly(){
f.fly();
}
public void quack(){
q.quack();
}
}
class MallardDuck extends Duck{
void display() {
System.out.println("绿头-----");
}
public MallardDuck(){
this.setFlyBehavior(new FlyWithWings());
this.setQuackBehavior(new Quack());
}
}
class RedheadDuck extends Duck{
void display() {
System.out.println("红头-----");
}
public RedheadDuck(){
this.setFlyBehavior(new FlyWithWings());
this.setQuackBehavior(new Quack());
}
}
class RubberDuck extends Duck{
void display() {
System.out.println("橡皮鸭-----");
}
public RubberDuck(){
this.setFlyBehavior(new FlyNOWay());
this.setQuackBehavior(new Squack());
}
}
class DecoyDuck extends Duck{
void display() {
System.out.println("诱饵鸭----");
}
public DecoyDuck(){
this.setFlyBehavior(new FlyNOWay());
this.setQuackBehavior(new Squack());
}
}
public class Client {
public static void main(String[] args){
MallardDuck m = new MallardDuck();
RedheadDuck re = new RedheadDuck();
RubberDuck ru = new RubberDuck();
DecoyDuck d = new DecoyDuck();
m.display();
m.fly();
m.quack();
re.display();
re.fly();
re.quack();
ru.display();
ru.fly();
ru.quack();
d.display();
d.fly();
d.quack();
}
}
说明:采用多态实现,动态绑定,代码的复用性和扩展性都比较好,实现起来比较简单,更改或增加子类方便,不用修改之前类的代码。定义接口 FlyBehavior 和 QuackBehavior,其中有不同的飞和叫的方式,Duck去继承他们,重写各子类的构造器,当创建一个子类时,将飞和叫的相应参数传给父类中多态实现的方法,如 FlyBehavior 中有 FlyWithWings 和 FlyNOWay 的方法,当创建一只会飞的鸭子MallardDuck时,将FlyWithWings传给父类:
public MallardDuck(){
this.setFlyBehavior(new FlyWithWings());
this.setQuackBehavior(new Quack());
}
此方法的缺点是当一个行为有很多种可能时要去罗列那么多的可能,而且每个子类都必须去向父类传递参数,而且当很多种类共有一种行为时,还是要一一的说明。其实可以根据实际情况而采取多态和接口并用的方法,而不是一味的所有的有多种可能行为都采用多态实现。