浅谈Java23种设计模式之11种行为型模式的使用场景(第三部分)

前言

行为型设计模式实际使用场景第三部分;

1.状态模式(State)

概念:

它允许对象在其内部状态改变时改变它的行为,对象看起来好像修改了它的类。这种模式主要用于当一个对象的行为依赖于它的状态(对象的状态改变,行为也随之改变)并且它必须在运行时根据状态改变它的行为。

实际使用场景:

假设我们在开发一款简单的ATM机软件,ATM机有多种状态,如空闲、用户认证中、取款、存款、退出等。每种状态下ATM机的行为不同,比如在空闲状态时可以插入银行卡,在取款状态时可以输入取款金额。使用状态模式可以很好地管理这些状态变化及其对应的行为。

直接上代码:

a.抽象状态接口

java 复制代码
public interface ATMState {
    void insertCard();
    void ejectCard();
    void insertPin(int pin);
    void requestCash(int amount);
}

b.具体状态类

java 复制代码
public class HasCardState implements ATMState {
    private ATMContext atmContext;

    public HasCardState(ATMContext context) {
        this.atmContext = context;
    }

    @Override
    public void insertCard() {
        System.out.println("Card is already inserted.");
    }

    @Override
    public void ejectCard() {
        System.out.println("Ejecting the card...");
        atmContext.setState(atmContext.getNoCardState());
    }

    @Override
    public void insertPin(int pin) {
        if (pin == 1234) {
            System.out.println("Correct PIN, proceeding...");
            atmContext.setState(atmContext.getHasPinState());
        } else {
            System.out.println("Incorrect PIN. Please try again.");
        }
    }

    @Override
    public void requestCash(int amount) {
        System.out.println("Please enter your PIN first.");
    }
}

c.上下文类

java 复制代码
public class ATMContext {
    private ATMState noCardState;
    private ATMState hasCardState;
    private ATMState hasPinState;
    private ATMState dispensingCashState;

    private ATMState currentState;

    public ATMContext() {
        noCardState = new NoCardState(this);
        hasCardState = new HasCardState(this);
        hasPinState = new HasPinState(this);
        dispensingCashState = new DispensingCashState(this);

        currentState = noCardState;
    }

    public void setState(ATMState state) {
        this.currentState = state;
    }

    public ATMState getState() {
        return currentState;
    }

    // 提供对外的接口,由当前状态决定行为
    public void insertCard() {
        currentState.insertCard();
    }

    public void ejectCard() {
        currentState.ejectCard();
    }

    public void insertPin(int pin) {
        currentState.insertPin(pin);
    }

    public void requestCash(int amount) {
        currentState.requestCash(amount);
    }
}

d.客户端代码

java 复制代码
public class StatePatternDemo {
    public static void main(String[] args) {
        ATMContext atm = new ATMContext();
        atm.insertCard();
        atm.insertPin(1234);
        atm.requestCash(100);
        atm.ejectCard();
    }
}

说明

在这个例子中,状态模式使得自动贩卖机的行为可以根据其当前状态动态变化,而不需要在ATMContext类中编写复杂的条件逻辑来判断每一步应该做什么。如果需要增加新的状态或修改已有状态的行为,只需添加或修改相应的状态类,而不影响到其他状态或ATMContext类,这大大提高了系统的可维护性和可扩展性。

2.策略模式(Strategy)

概念:

它使你能在运行时改变对象的行为。在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为模式。

实际使用场景:

假设我们正在开发一个电商网站的订单结算系统,该系统需要根据用户选择的配送方式(如普通快递、次日达、自提等)来计算不同的运费。这是一个非常适合使用策略模式的场景,因为每种配送方式的运费计算规则不同,但它们都遵循一个共同的接口。

直接上代码:

a.抽象策略接口

java 复制代码
public interface ShippingStrategy {
    double calculateShippingCost(double weight);
}

b.具体策略类

java 复制代码
public class RegularShippingStrategy implements ShippingStrategy {
    @Override
    public double calculateShippingCost(double weight) {
        return weight * 0.05; // 假设普通快递费用是重量的5%
    }
}
java 复制代码
public class ExpressShippingStrategy implements ShippingStrategy {
    @Override
    public double calculateShippingCost(double weight) {
        return weight * 0.1 + 20; // 假设次日达费用是重量的10%加上固定费用20元
    }
}

c.上下文类

java 复制代码
public class Order {
    private double weight;
    private ShippingStrategy shippingStrategy;

    public Order(double weight) {
        this.weight = weight;
    }

    public void setShippingStrategy(ShippingStrategy strategy) {
        this.shippingStrategy = strategy;
    }

    public double calculateTotalCost() {
        double shippingCost = shippingStrategy.calculateShippingCost(weight);
        // 假设还有其他成本,如商品价格等,这里简化处理
        return shippingCost; 
    }
}

d.客户端代码

java 复制代码
public class StrategyPatternDemo {
    public static void main(String[] args) {
        Order order = new Order(5); // 假设订单重量为5千克

        // 用户选择了次日达
        order.setShippingStrategy(new ExpressShippingStrategy());
        System.out.println("Express shipping cost: " + order.calculateTotalCost());

        // 用户改选普通快递
        order.setShippingStrategy(new RegularShippingStrategy());
        System.out.println("Regular shipping cost: " + order.calculateTotalCost());
    }
}

说明

在这个例子中,ShippingStrategy接口定义了不同的运费计算策略,而Order类根据用户选择的策略动态调整其运费计算行为。如果未来需要增加新的配送方式,只需添加新的策略类实现ShippingStrategy接口,然后在上下文中设置即可,无需修改现有代码,这极大地提高了系统的灵活性和扩展性。

3.模板方法模式(Template Method)

概念:

它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中实现。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

实际使用场景:

假设我们正在开发一个报告生成系统,系统需要支持多种类型的报告(如PDF报告、HTML报告等),虽然每种报告的生成流程大体相同(比如初始化、获取数据、格式化数据、输出报告),但是具体实现细节各不相同。这时,可以使用模板方法模式来定义报告生成的基本步骤,而将具体实现留给子类完成。

直接上代码:

a.抽象类(定义模板方法)

java 复制代码
public abstract class ReportGenerator {
    // 模板方法,定义了报告生成的步骤
    public final void generateReport() {
        initialize();
        fetchData();
        formatData();
        outputReport();
    }

    // 具体方法,所有子类共有的实现
    private void initialize() {
        System.out.println("Initializing report generation...");
    }

    // 抽象方法,由子类实现
    protected abstract void fetchData();

    // 抽象方法,由子类实现
    protected abstract void formatData();

    // 具体方法,所有子类共有的实现
    private void outputReport() {
        System.out.println("Outputting the report...");
    }
}

b.具体子类

java 复制代码
public class PDFReportGenerator extends ReportGenerator {
    @Override
    protected void fetchData() {
        System.out.println("Fetching data for PDF report...");
    }

    @Override
    protected void formatData() {
        System.out.println("Formatting data into PDF format...");
    }
}
java 复制代码
public class HTMLReportGenerator extends ReportGenerator {
    @Override
    protected void fetchData() {
        System.out.println("Fetching data for HTML report...");
    }

    @Override
    protected void formatData() {
        System.out.println("Formatting data into HTML format...");
    }
}

c.客户端代码

java 复制代码
public class TemplateMethodPatternDemo {
    public static void main(String[] args) {
        ReportGenerator pdfGen = new PDFReportGenerator();
        pdfGen.generateReport();

        System.out.println("\n");

        ReportGenerator htmlGen = new HTMLReportGenerator();
        htmlGen.generateReport();
    }
}

说明

在这个例子中,ReportGenerator抽象类定义了报告生成的模板方法generateReport(),它是一个固定流程,包括初始化、获取数据、格式化数据和输出报告四个步骤。其中,fetchData()和formatData()是抽象方法,由具体的子类(如PDFReportGenerator和HTMLReportGenerator)实现,以适应不同类型的报告生成需求。这样,模板方法模式既保证了算法的整体结构稳定,又允许子类灵活地重定义部分步骤,提高了代码的复用性和扩展性。

4.访问者模式(Visitor)

概念:

它允许你定义一个作用于某对象结构中的各个元素的操作,而无需改变它们的类。这种模式适用于需要对元素执行许多不同类型的复杂操作的情况,且这些操作在不断变化或增加时,可以方便地扩展。

实际使用场景:

设想一个电商系统,需要统计不同类型商品(如书籍、电子产品)的总价和总重量,但商品类型和统计需求可能会随时间增长。为了不修改商品类,可以使用访问者模式来动态添加新的统计功能。

直接上代码:

a.定义元素接口和具体元素

java 复制代码
// 商品元素接口,声明接受访问者的方法
public interface Product {
    void accept(Visitor visitor);
}
java 复制代码
// 具体商品类 - 书籍
public class Book implements Product {
    private String title;
    private double price;
    private double weight;

    public Book(String title, double price, double weight) {
        this.title = title;
        this.price = price;
        this.weight = weight;
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    // 获取价格和重量的方法
    public double getPrice() { return price; }
    public double getWeight() { return weight; }
}

b.访问者接口和具体访问者

java 复制代码
// 访问者接口,声明访问商品的方法
public interface Visitor {
    void visit(Book book);
    // 如果有其他商品类型,这里会添加相应的方法,如visit(Electronics electronics)...
}
java 复制代码
// 具体访问者 - 统计价格和重量
public class StatisticsVisitor implements Visitor {
    private double totalCost = 0.0;
    private double totalWeight = 0.0;

    @Override
    public void visit(Book book) {
        totalCost += book.getPrice();
        totalWeight += book.getWeight();
    }

    // 对于其他商品类型的visit方法...

    // 提供获取统计结果的方法
    public double getTotalCost() { return totalCost; }
    public double getTotalWeight() { return totalWeight; }
}

c.客户端代码

java 复制代码
public class VisitorPatternDemo {
    public static void main(String[] args) {
        // 创建商品集合
        List<Product> products = new ArrayList<>();
        products.add(new Book("Effective Java", 50.0, 1.2));
        products.add(new Book("Clean Code", 40.0, 0.9));
        // 假设还有其他商品如电子产品...

        // 创建访问者
        Visitor statisticsVisitor = new StatisticsVisitor();

        // 遍历商品,让每个商品接受访问者的访问
        for (Product product : products) {
            product.accept(statisticsVisitor);
        }

        // 输出统计结果
        System.out.println("Total cost: " + statisticsVisitor.getTotalCost());
        System.out.println("Total weight: " + statisticsVisitor.getTotalWeight());
    }
}

说明

在这个例子中,Product接口和其实现类(如Book)代表了元素,它们都包含了一个accept方法用于接收访问者。Visitor接口和实现类(如StatisticsVisitor)定义了对元素的操作。通过这种方式,可以很容易地添加新的统计逻辑(比如计算平均价格的访问者),而不必修改商品类,这大大提高了系统的可维护性和扩展性。

好了以上就是行为型设计模式的4种具体设计模式的使用场景;到此23种设计模式场景应用全部解析完毕,希望能给同学们带来帮助.

如果觉得有帮助的话动下鼠标点个赞,3Q啦,下班回家做饭喽OVO

相关推荐
Amarantine、沐风倩✨31 分钟前
设计一个监控摄像头物联网IOT(webRTC、音视频、文件存储)
java·物联网·音视频·webrtc·html5·视频编解码·七牛云存储
路在脚下@2 小时前
spring boot的配置文件属性注入到类的静态属性
java·spring boot·sql
森屿Serien2 小时前
Spring Boot常用注解
java·spring boot·后端
Damon_X2 小时前
桥接模式(Bridge Pattern)
设计模式·桥接模式
苹果醋33 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader3 小时前
深入解析 Apache APISIX
java·apache
菠萝蚊鸭3 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
旭东怪4 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
007php0074 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程
∝请叫*我简单先生4 小时前
java如何使用poi-tl在word模板里渲染多张图片
java·后端·poi-tl