设计模式学习-策略模式

策略模式

策略模式一般用项目中算法功能的切换。对于解决某一个问题,假设存在一个算法族,如果希望某些时刻从其中选择一个合适的算法来实现功能,那么可以选择使用策略模式。策略模式将算法的表示功能和使用功能相分离,可以很方便的更换算法或者增加新的算法,符合开闭原则在实际应用中也比较常见。
策略模式的UML类图和状态模式比较相似,但两者在使用上存在根本的区别。状态模式是根据传入的参数,被动的选择合适的算法执行,因此必须有方法来控制状态的选择,比如购物的时候根据不同的金额自动计算不同的优惠价格;而策略模式是由调用者主动选择某种策略,比如去某地方式有步行、骑车、打车等,任选其一。

定义

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

结构

  • Context(环境类):调用算法的角色,内部维护了一个策略类实例,调用策略类的方法
  • Strategy(抽象策略类):抽象策略类为所有的算法声明了抽象方法,是所有实例算法的父类,被环境类对象调用
  • ConcreteStrategy(具体策略类):抽象策略类的子类,封装了具体的策略方法,实际被调用的对象
    在这里插入图片描述

实例

// 为不同的日子设置了不同的打折策略。平常不打折,国庆8折。比较复杂的还可以比如六一儿童节,针对类型为儿童产品的商品打5折,其他商品不打折。
import java.math.BigDecimal;
import java.util.List;

interface CaculateMethod {

    BigDecimal caculate(List<Shop> shops);
}

import java.math.BigDecimal;
import java.util.List;

public class NationalDayCaculateMethod implements CaculateMethod{
    // 国庆节计算方式打8折
    @Override
    public BigDecimal caculate(List<Shop> shops) {
        return shops.stream().map(Shop::getPrice).reduce(BigDecimal.ZERO,(a, b)->a.add(b)).multiply(new BigDecimal("0.8"));
    }
}

import java.math.BigDecimal;
import java.util.List;

public class DayCaculateMethod implements CaculateMethod{
    // 平常不打折
    @Override
    public BigDecimal caculate(List<Shop> shops) {
        return shops.stream().map(Shop::getPrice).reduce(BigDecimal.ZERO,(a, b)->a.add(b));
    }

}
import java.math.BigDecimal;

public class Shop {

    private Integer type;

    private String name;

    private BigDecimal price;

    public Shop(Integer type, String name, BigDecimal price) {
        this.type = type;
        this.name = name;
        this.price = price;
    }

    public Integer getType() {
        return type;
    }

    public String getName() {
        return name;
    }

    public BigDecimal getPrice() {
        return price;
    }

}
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

public class Person {

    private List<Shop> shops;

    private CaculateMethod caculateMethod;

    public Person(CaculateMethod caculateMethod) {
        this.caculateMethod = caculateMethod;
    }

    public void setShops(List<Shop> shops) {
        this.shops = shops;
    }

    public BigDecimal caculate() {
        if (Objects.nonNull(shops) && shops.size() > 0) {
            return caculateMethod.caculate(shops);
        }
        return BigDecimal.ZERO;
    }
}

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {

        CaculateMethod method = new NationalDayCaculateMethod();
        Person p = new Person(method);

        Shop shop1 = new Shop(1, "面包", new BigDecimal("10"));
        Shop shop2 = new Shop(2, "玩具车", new BigDecimal("1000"));
        Shop shop3 = new Shop(3, "网球", new BigDecimal("30"));

        List<Shop> shops = new ArrayList<>();
        shops.add(shop1);
        shops.add(shop2);
        shops.add(shop3);

        p.setShops(shops);

        System.out.println(p.caculate());
    }
}

优点

  • 策略模式符合开闭原则,对于新增策略,不需修改原有代码
  • 将策略内容单独分离出来,方便代码的复用
  • 避免了多重条件的判断
缺点
  • 调用者必须知道每个策略执行的方式,必须要了解每个策略
  • 一点细小的不同可能就需要新的策略,导致类的增多
  • 无法同时使用多个策略类

适用场景

  • 系统需要在多个算法中动态切换
  • 对象有多重行为,每个行为有不同的判断来引用
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值