likes
comments
collection
share

设计模式Java实现-策略模式

作者站长头像
站长
· 阅读数 2

✨这里是第七人格的博客✨小七,欢迎您的到来~✨

🍅系列专栏:设计模式🍅

✈️本篇内容: 策略模式✈️

🍱本篇收录完整代码地址:gitee.com/diqirenge/d… 🍱

楔子

策略模式是一种行为型设计模式,其主要目标是根据运行时的需求选择对应的算法,而无需对客户端代码进行修改。这种模式将各种算法封装在抽象策略和具体策略类中,使得用户可以根据不同的需求选择具体的实现算法。例如,在一个支付系统中,可能会存在多种付款方式,如信用卡、借记卡和电子钱包等。在这种情况下,程序可以在运行时根据用户的选择来执行相应的支付操作。

策略模式的主要优点是提高了代码的复用性和可维护性,同时降低了系统的耦合度。通过使用策略模式,我们能够消除复杂的多重条件语句(说人话就是,可以使用策略类来消除大量的if-else)从而提高代码的可读性。然而,每个策略都需要一个单独的类,这可能会导致系统的类数量增加。

需求背景

我们现在有个活动,需要给用户发放福利,发放的福利可以是券、积分或者图文。现在让你来设计这个功能,你应该怎么设计呢?

分析设计

根据需求一把梭,我们可以创建一个名为Welfare的类,接着再创建一个枚举类型Type,用于表示福利的类型(券、积分或图文)。然后,我们可以在Welfare类中添加一个方法sendWelfare,该方法接受一个用户对象和一个福利类型作为参数,并根据福利类型执行相应的操作。这样虽然很快的完成了任务,但是对代码以后的拓展维护埋下了隐患。

所以我们尝试着优化它,首先,我们需要创建一个名为WelfareStrategy的接口,该接口包含一个名为sendWelfare的方法,用于发送福利。然后,我们可以为每种福利类型创建一个实现WelfareStrategy接口的具体策略类。接下来,我们需要创建一个名为WelfareContext的类,该类包含一个名为setStrategy的方法,用于设置当前的策略。在sendWelfare方法中,我们将调用当前策略的sendWelfare方法。

为了让客户端不用主动选择调用哪个策略,我们还可以创建一个名为WelfareFactory的工厂类,该类包含一个名为createWelfare的方法,用于创建不同类型的福利对象。然后,我们可以在WelfareContext类中使用WelfareFactory来创建福利对象。

UML图

根据分析设计,我们可以先画一个简单的UML图,后面通过UML图编码

设计模式Java实现-策略模式

模块名称

strategy

模块地址

gitee.com/diqirenge/d…

模块描述

策略模式代码示例

代码实现

一、代码一把梭

1、定义公共类

/**
 * 定义福利类型枚举
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/12/25
 */
public enum Type {
    COUPON, POINTS, IMAGE_TEXT
}
/**
 * 用户类
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/12/25
 */
public class User {
    private String name;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

2、编写福利类,并提供不同福利的发送方法

/**
 * 根据需求一把梭
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/12/25
 */
public class Welfare {

    // 发放福利的方法
    public void sendWelfare(User user, Type type) {
        switch (type) {
            case COUPON:
                sendCoupon(user);
                break;
            case POINTS:
                sendPoints(user);
                break;
            case IMAGE_TEXT:
                sendImageText(user);
                break;
            default:
                throw new IllegalArgumentException("Invalid welfare type");
        }
    }

    // 发放券的方法
    private void sendCoupon(User user) {
        // 在这里实现发放券的逻辑
        System.out.println("Sending coupon to " + user.getName());
    }

    // 发放积分的方法
    private void sendPoints(User user) {
        // 在这里实现发放积分的逻辑
        System.out.println("Sending points to " + user.getName());
    }

    // 发放图文的方法
    private void sendImageText(User user) {
        // 在这里实现发放图文的逻辑
        System.out.println("Sending image text to " + user.getName());
    }
}

3、编写测试类

/**
 * 测试策略模式
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/12/25
 */
public class StrategyTest {

    @Test
    public void testDemo01() {

        Welfare welfare = new Welfare();
        User user = new User("张三");

        welfare.sendWelfare(user, Type.COUPON);
        welfare.sendWelfare(user, Type.POINTS);
        welfare.sendWelfare(user, Type.IMAGE_TEXT);
    }

}

4、测试结果

Sending coupon to 张三

Sending points to 张三

Sending image text to 张三

二、使用策略模式优化代码

1、抽象福利策略接口

/**
 * 策略模式 - 福利策略接口
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/12/25
 */
public interface WelfareStrategy {
    void sendWelfare(User user);
}

2、编写具体实现类

/**
 * 策略模式 - 发放券策略类
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/12/25
 */
public class CouponStrategy implements WelfareStrategy {
    @Override
    public void sendWelfare(User user) {
        System.out.println("Sending coupon to " + user.getName());
    }
}
/**
 * 策略模式 - 发放图文策略类
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/12/25
 */
public class ImageTextStrategy implements WelfareStrategy {
    @Override
    public void sendWelfare(User user) {
        System.out.println("Sending image text to " + user.getName());
    }
}
/**
 * 策略模式 - 发放积分策略类
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/12/25
 */
public class PointsStrategy implements WelfareStrategy {
    @Override
    public void sendWelfare(User user) {
        System.out.println("Sending points to " + user.getName());
    }
}

3、编写福利类

/**
 * 策略模式 - 福利上下文类
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/12/25
 */
public class WelfareContext {
    private WelfareStrategy strategy;

    public void setStrategy(WelfareStrategy strategy) {
        this.strategy = strategy;
    }

    public void sendWelfare(User user) {
        strategy.sendWelfare(user);
    }
}

4、编写测试方法

@Test
public void testDemo02() {

    com.run2code.design.behavioral.strategy.demo02.WelfareContext welfareContext = new com.run2code.design.behavioral.strategy.demo02.WelfareContext();
    User user = new User("李四");

    // 使用发放券策略
    welfareContext.setStrategy(new CouponStrategy());
    welfareContext.sendWelfare(user);

    // 使用发放积分策略
    welfareContext.setStrategy(new PointsStrategy());
    welfareContext.sendWelfare(user);

    // 使用发放图文策略
    welfareContext.setStrategy(new ImageTextStrategy());
    welfareContext.sendWelfare(user);
}

5、测试结果

Sending coupon to 李四

Sending points to 李四

Sending image text to 李四

三、使用工厂模式优化代码

1、通过工厂类,组织具体的创建策略的逻辑即可

/**
 * 策略模式 - 福利工厂类
 * 关注公众号【奔跑的码畜】,一起进步不迷路
 *
 * @author 第七人格
 * @date 2023/12/25
 */
public class WelfareFactory {
    public static WelfareStrategy createWelfare(String type) {
        if (type == null) {
            return null;
        }
        if (type.equalsIgnoreCase("COUPON")) {
            return new CouponStrategy();
        } else if (type.equalsIgnoreCase("POINTS")) {
            return new PointsStrategy();
        } else if (type.equalsIgnoreCase("IMAGE_TEXT")) {
            return new ImageTextStrategy();
        }
        return null;
    }
}

2、编写测试方法

@Test
public void testDemo03() {

    com.run2code.design.behavioral.strategy.demo03.WelfareContext welfareContext = new com.run2code.design.behavioral.strategy.demo03.WelfareContext();
    User user = new User("王五");

    // 使用工厂方法创建发放券策略对象
    WelfareStrategy couponStrategy = WelfareFactory.createWelfare(Type.COUPON.name());
    welfareContext.setStrategy(couponStrategy);
    welfareContext.sendWelfare(user);

    // 使用工厂方法创建发放积分策略对象
    WelfareStrategy pointsStrategy = WelfareFactory.createWelfare(Type.POINTS.name());
    welfareContext.setStrategy(pointsStrategy);
    welfareContext.sendWelfare(user);

    // 使用工厂方法创建发放图文策略对象
    WelfareStrategy imageTextStrategy = WelfareFactory.createWelfare(Type.IMAGE_TEXT.name());
    welfareContext.setStrategy(imageTextStrategy);
    welfareContext.sendWelfare(user);

}

3、测试结果

Sending coupon to 王五

Sending points to 王五

Sending image text to 王五

实现要点

策略模式实现要点如下:

1、定义一个公共接口或抽象类,声明所有支持的方法。例子中为:WelfareStrategy

2、创建一系列实现了该接口或继承了该抽象类的类,这些类就是具体的算法。例子中为:CouponStrategy、ImageTextStrategy、PointsStrategy

3、在客户端代码中使用上下文对象来调用具体算法。上下文对象负责将算法的具体实现委托给相应的具体算法类。例子中为:WelfareContext

总结

策略模式是一种行为设计模式,它定义了一系列算法,并将每个算法封装在一个具有共同接口的独立类中,使得它们可以相互替换。策略模式让算法的变化独立于使用它们的客户端。至于如何创建策略,我们一般可以考虑引入工厂模式等其他设计模式。为了抽象得更合理,还经常搭配模版模式使用,等后面讲到模版模式的时候再细说。