前言:
当前看官们对“java 状态模式和策略模式”大体比较讲究,我们都想要学习一些“java 状态模式和策略模式”的相关内容。那么小编在网上搜集了一些有关“java 状态模式和策略模式””的相关知识,希望兄弟们能喜欢,咱们一起来了解一下吧!什么是策略模式?
策略模式(Strategy Pattern)是一种行为设计模式,它定义了一组同类型的算法,在不同的类中封装起来,每种算法可以根据当前场景相互替换,从而使算法的变化独立于使用它们的客户端(即算法的调用者)。策略模式可以让算法的选择与使用分离,提高了代码的灵活性和可维护性。
在策略模式中,有三个核心角色:
1、 环境类(Context):它持有一个策略对象的引用,可以通过策略对象执行具体的算法。 2、 抽象策略类(Strategy):它定义了一个公共接口,用于所有具体策略类的统一调用。 3、 具体策略类(Concrete Strategy):它实现了抽象策略类定义的接口,提供具体的算法实现。
应用场景
1、 当有多个类似的算法,且客户端需要根据不同的情况选择使用不同的算法时,可以使用策略模式。它将算法的选择与使用分离,提高了代码的灵活性和可维护性。
2、 当一个类中有多个条件判断语句,并且每个条件执行不同的操作时,可以考虑使用策略模式。它可以避免大量的条件语句,使得代码更加清晰、可读性更高。
3、 当需要在运行时动态地切换算法时,策略模式可以提供一种简洁的方式。通过修改环境类持有的策略对象,可以在不影响客户端代码的情况下切换算法。
总的来说,策略模式可以帮助实现算法的封装和选择,提高代码的可维护性、可扩展性和可读性。
示例
实现用户购物下单场景
首先,我们定义一个抽象策略接口 DiscountStrategy:
// 抽象策略接口public interface DiscountStrategy { double calculateDiscount(double amount);}
然后,我们实现具体的策略类,比如会员折扣策略和新用户折扣策略:
// 具体策略类 - 会员折扣public class MemberDiscountStrategy implements DiscountStrategy { @Override public double calculateDiscount(double amount) { // 假设会员折扣为 10% return amount * 0.1; }}// 具体策略类 - 新用户折扣public class NewUserDiscountStrategy implements DiscountStrategy { @Override public double calculateDiscount(double amount) { // 假设新用户折扣为 20 元 return 20; }}
接下来,我们创建购物车类 ShoppingCart,它持有一个策略对象,并提供购物和生成订单的方法:
// 环境类 - 购物车public class ShoppingCart { private DiscountStrategy discountStrategy; private List<Item> items; public ShoppingCart(DiscountStrategy discountStrategy) { this.discountStrategy = discountStrategy; this.items = new ArrayList<>(); } public void addItem(Item item) { items.add(item); } public double calculateTotalAmount() { double totalAmount = 0; for (Item item : items) { totalAmount += item.getPrice(); } return totalAmount; } public double calculateDiscountAmount() { double totalAmount = calculateTotalAmount(); return discountStrategy.calculateDiscount(totalAmount); } public void generateOrder() { double totalAmount = calculateTotalAmount(); double discountAmount = calculateDiscountAmount(); double finalAmount = totalAmount - discountAmount; // 生成订单的逻辑 // ... System.out.println(totalAmount); System.out.println(discountAmount); System.out.println(finalAmount); } @AllArgsConstructor @NoArgsConstructor @Data public static class Item { private String goodsName; private double price; }}
最后,我们可以使用这些类进行示例测试:
public class Main { public static void main(String[] args) { // 创建购物车并设置会员折扣策略 DiscountStrategy memberDiscountStrategy = new MemberDiscountStrategy(); ShoppingCart cart = new ShoppingCart(memberDiscountStrategy); // 添加商品到购物车 Item item1 = new Item("iPhone", 999); Item item2 = new Item("Headphones", 99); cart.addItem(item1); cart.addItem(item2); // 生成订单 cart.generateOrder(); }}
这个示例演示了使用策略模式来处理用户购物下单场景。根据不同的折扣策略,购物车可以计算总金额并生成相应的订单。你可以根据实际需求定义更多的具体策略类,并在购物车中切换不同的策略来实现不同的折扣计算逻辑。
策略模式与函数式编程结合示例
当结合策略模式与函数式编程的思想时,可以使用 Map(映射)来存储不同策略的函数,并根据需要选择执行的函数。下面是一个示例,展示了策略模式与函数式编程的结合:
import java.util.HashMap;import java.util.Map;import java.util.function.Function;public class Main { public static void main(String[] args) { // 使用Map存储不同策略的函数 Map<String, Function<Void, Void>> strategyMap = new HashMap<>(); strategyMap.put("A", v -> { new StrategyA().execute(); return null; }); strategyMap.put("B", v -> { new StrategyB().execute(); return null; }); // 根据需要选择执行的函数 String strategyKey = "A"; Function<Void, Void> strategyFunction = strategyMap.get(strategyKey); if (strategyFunction != null) { strategyFunction.apply(null); } }}// 抽象策略接口interface Strategy { void execute();}// 具体策略类 - 策略Aclass StrategyA implements Strategy { @Override public void execute() { System.out.println("执行策略A"); }}// 具体策略类 - 策略Bclass StrategyB implements Strategy { @Override public void execute() { System.out.println("执行策略B"); }}
在上述示例中,我们定义了一个抽象策略接口 Strategy 和两个具体策略类 StrategyA 和 StrategyB。然后,我们使用 Map 存储不同策略的函数,键是策略的标识符,值是执行策略的函数。在示例中,我们使用了 Java 8 中的函数式接口 Function,该接口接受一个输入并返回一个输出。
在 main 方法中,我们选择了策略标识符为 "A" 的策略,并从 strategyMap 中获取对应的函数。如果找到了函数,我们就调用该函数来执行策略。这样,我们通过将策略与函数的映射存储在 Map 中,实现了策略模式与函数式编程的结合。
请注意,上述示例只是简单展示了策略模式与函数式编程的结合方式。在实际应用中,你可以根据需求扩展和定制更多的策略,并结合函数式编程的特性,使代码更加简洁和灵活。
注意事项
在使用策略模式时,有几个注意事项需要考虑:
1、 接口设计:确保抽象策略接口(或抽象基类)定义了所有具体策略类需要实现的方法,以确保策略对象的一致性。良好的接口设计可以提高代码的可扩展性和可维护性。
2、 策略切换:策略模式的核心是在运行时动态地切换策略对象。因此,确保在环境类中提供了切换策略的方法,使得客户端能够方便地更改策略。
3、 策略数量:在设计时需要仔细考虑策略的数量。如果策略过多,可能会导致类爆炸问题,增加代码复杂性。合理地组织和分类策略,避免策略类过于庞大和混乱。
4、 策略选择:在选择具体策略时,需要根据实际需求和场景进行权衡和选择。不同的策略可能有不同的性能、复杂度和效果,需要选择最适合的策略。
5、 策略耦合:策略模式将策略对象与环境类解耦,但策略对象之间可能存在一定的耦合关系。在实现具体策略时,需要注意避免策略之间的紧耦合,以保持策略的独立性和可替换性。
6、 策略和状态:策略模式与状态模式有一些相似之处,因为它们都涉及到在运行时选择不同的行为。但策略模式更侧重于算法的选择和封装,而状态模式更侧重于对象状态的管理和转换。因此,在使用策略模式时,需要明确区分策略和状态的概念。
综上所述,注意上述事项可以帮助你正确地应用策略模式,以实现灵活、可维护和可扩展的代码结构。
策略模式的缺点客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。策略类会增多,如果备选的策略很多的话,那么对象的数目就会很可观。这会增加系统的复杂性和维护成本。所有策略类都需要对外暴露,这可能会暴露一些内部的实现细节或者影响算法的安全性。
标签: #java 状态模式和策略模式