Java设计模式实战:策略模式在SimUDuck问题中的应用

一、前言

在面向对象编程中,设计模式是解决常见问题的可重用方案。今天,我将通过经典的SimUDuck问题,向大家展示如何使用策略模式(Strategy Pattern)来设计灵活、可扩展的鸭子模拟程序。

二、问题描述

SimUDuck是一个模拟鸭子行为的程序。最初的设计是有一个Duck超类,各种鸭子(如绿头鸭、红头鸭等)继承这个超类。但随着需求变化,需要让某些鸭子能飞,某些不能飞,某些鸭子发出"嘎嘎"叫,某些发出"吱吱"叫,甚至有些根本不叫。如果简单使用继承来实现这些行为,会导致代码难以维护和扩展。

三、解决方案:策略模式

策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。

UML类图分析

根据提供的UML图,我们可以看到以下结构:

  1. Duck类:作为所有鸭子的基类,包含两个行为接口的引用(FlyBehavior和QuackBehavior)

  2. 具体鸭子类:MallardDuck、RedheadDuck、RubberDuck、DecoyDuck等

  3. 行为接口

    • FlyBehavior:飞行行为接口

    • QuackBehavior:叫声行为接口

  4. 具体行为实现类

    • FlyWithWings、FlyNoWay:飞行行为实现

    • Quack、Squeak、MuteQuack:叫声行为实现

四、Java代码实现

复制代码
// 飞行行为接口
public interface FlyBehavior {
    void fly();
}

// 具体飞行行为实现
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("I'm flying with wings!");
    }
}

public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("I can't fly!");
    }
}

// 叫声行为接口
public interface QuackBehavior {
    void quack();
}

// 具体叫声行为实现
public class Quack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("Quack!");
    }
}

public class Squeak implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("Squeak!");
    }
}

public class MuteQuack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("<< Silence >>");
    }
}

// 鸭子基类
public abstract class Duck {
    protected FlyBehavior flyBehavior;
    protected QuackBehavior quackBehavior;
    
    public Duck() {}
    
    public abstract void display();
    
    public void performFly() {
        flyBehavior.fly();
    }
    
    public void performQuack() {
        quackBehavior.quack();
    }
    
    public void swim() {
        System.out.println("All ducks float, even decoys!");
    }
    
    // 动态设置行为
    public void setFlyBehavior(FlyBehavior fb) {
        flyBehavior = fb;
    }
    
    public void setQuackBehavior(QuackBehavior qb) {
        quackBehavior = qb;
    }
}

// 具体鸭子实现
public class MallardDuck extends Duck {
    public MallardDuck() {
        flyBehavior = new FlyWithWings();
        quackBehavior = new Quack();
    }
    
    @Override
    public void display() {
        System.out.println("I'm a real Mallard duck");
    }
}

public class RedheadDuck extends Duck {
    public RedheadDuck() {
        flyBehavior = new FlyWithWings();
        quackBehavior = new Quack();
    }
    
    @Override
    public void display() {
        System.out.println("I'm a real Redhead duck");
    }
}

public class RubberDuck extends Duck {
    public RubberDuck() {
        flyBehavior = new FlyNoWay();
        quackBehavior = new Squeak();
    }
    
    @Override
    public void display() {
        System.out.println("I'm a rubber duck");
    }
}

public class DecoyDuck extends Duck {
    public DecoyDuck() {
        flyBehavior = new FlyNoWay();
        quackBehavior = new MuteQuack();
    }
    
    @Override
    public void display() {
        System.out.println("I'm a decoy duck");
    }
}

// 测试类
public class MiniDuckSimulator {
    public static void main(String[] args) {
        Duck mallard = new MallardDuck();
        mallard.performQuack();
        mallard.performFly();
        
        Duck model = new DecoyDuck();
        model.performFly();
        // 动态改变行为
        model.setFlyBehavior(new FlyWithWings());
        model.performFly();
    }
}

五、设计优势

  1. 封装变化:将易变的行为(飞行和叫声)封装到单独的类中

  2. 多用组合,少用继承:通过组合方式使用行为,而不是继承

  3. 针对接口编程:依赖于抽象(接口),而不是具体实现

  4. 运行时动态改变行为:通过setter方法可以在运行时改变鸭子的行为

六、总结

策略模式让我们能够定义一系列算法,并将每个算法封装起来,使它们可以互相替换。这种模式让算法的变化独立于使用算法的客户,符合"开闭原则"(对扩展开放,对修改关闭)。在SimUDuck问题中,策略模式完美解决了鸭子行为多样化的问题,使系统更加灵活和可扩展。

相关推荐
青云交几秒前
Java 大视界 -- 基于 Java 的大数据机器学习模型在图像识别中的迁移学习与模型优化
java·大数据·迁移学习·图像识别·模型优化·deeplearning4j·机器学习模型
御承扬27 分钟前
编程素养提升之EffectivePython(Builder篇)
python·设计模式·1024程序员节
2501_9098008128 分钟前
Java 集合框架之 Set 接口
java·set接口
断剑zou天涯31 分钟前
【算法笔记】暴力递归尝试
java·笔记·算法
Nobody_Cares2 小时前
JWT令牌
java
沐浴露z2 小时前
Kafka入门:基础架构讲解,安装与使用
java·分布式·kafka
神秘的土鸡2 小时前
从数据仓库到数据中台再到数据飞轮:我的数据技术成长之路
java·服务器·aigc·数据库架构·1024程序员节
vir022 小时前
P1928 外星密码(dfs)
java·数据结构·算法·深度优先·1024程序员节
摇滚侠2 小时前
全面掌握PostgreSQL关系型数据库,备份和恢复,笔记46和笔记47
java·数据库·笔记·postgresql·1024程序员节
eguid_13 小时前
【开源项目分享】JNSM1.2.0,支持批量管理的jar包安装成Windows服务可视化工具,基于Java实现的支持批量管理已经安装服务的可视化工具
java·开源·jar·1024程序员节·windows服务·jar包安装成服务·exe安装成服务