策略设计模式

一. 定义(此段为全文照抄)

  1. 针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换,使算法可以在不影响到客户端的情况下发生改变;
  2. 环境角色(上下文角色):屏蔽高层模块对策略的直接访问,持有一个策略类的引用;
  3. 抽象策略角色:对策略、算法进行抽象,通常定义每个策略或算法必须具有的方法和属性;
  4. 具体策略角色:实现抽象策略中的具体操作,有具体的算法;

二. 代码实现

1. 抽象策略角色

package com.xiaobai.design_pattern.strategy;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * @author wangtw
 * @ClassName DiscountStrategy
 * @description: 抽象策略角色
 * @date 2023/6/418:18
 */
@Getter // get方法
@AllArgsConstructor // 全参构造函数
public abstract class DiscountStrategy {

    // 书的价格
    private double price = 0;

    // 书的数量
    private int number = 0;

    // 策略方法,计算折扣额
    public abstract double calculateDiscount();
}

2. 具体策略角色

(1)无折扣策略

package com.xiaobai.design_pattern.strategy;

import lombok.AllArgsConstructor;

/**
 * @author wangtw
 * @ClassName NoDiscountStrategy
 * @description: 没有折扣额(具体策略角色)
 * @date 2023/6/418:24
 */
public class NoDiscountStrategy extends DiscountStrategy{
    // 构造方法
    public NoDiscountStrategy(double price, int number) {
        super(price, number);
    }

    /**
     * 具体策略方法,0折扣额
     * @return
     */
    @Override
    public double calculateDiscount() {
        return 0;
    }
}

(2)固定折扣策略

package com.xiaobai.design_pattern.strategy;

/**
 * @author wangtw
 * @ClassName FixDiscountStrategy
 * @description: 固定折扣值为1的算法(具体策略角色)
 * @date 2023/6/418:28
 */
public class FixDiscountStrategy extends DiscountStrategy{
    // 构造方法
    public FixDiscountStrategy(double price, int number) {
        super(price, number);
    }

    /**
     * 具体策略方法,固定折扣额
     * @return
     */
    @Override
    public double calculateDiscount() {
        return getNumber() * 1;
    }
}

(3)百分比折扣策略

package com.xiaobai.design_pattern.strategy;

/**
 * @author wangtw
 * @ClassName PercentageDiscountStragety
 * @description: 百分比策略(具体策略角色)
 * @date 2023/6/418:32
 */
public class PercentageDiscountStrategy extends DiscountStrategy{
    // 构造函数
    public PercentageDiscountStrategy(double price, int number) {
        super(price, number);
    }

    /**
     * 具体策略方法,折扣百分比为15%的算法
     * @return
     */
    @Override
    public double calculateDiscount() {
        return getNumber() * getPrice() * 0.15;
    }
}

3. 环境角色(上下文角色)

package com.xiaobai.design_pattern.strategy;

/**
 * @author wangtw
 * @ClassName ContextClient
 * @description: 环境角色(上下文角色)
 * @date 2023/6/418:35
 */
public class ContextClient {

    private DiscountStrategy discountStrategy;

    public ContextClient(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    public double contextCalDisc() {
        return discountStrategy.calculateDiscount();
    }
}

4. 策略测试类

package com.xiaobai.design_pattern.strategy;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

/**
 * @author wangtw
 * @ClassName StrategyTest
 * @description: 策略测试类
 * @date 2023/6/418:38
 */
@Slf4j
public class StrategyTest {

    @Test
    public void test() {
        // 无折扣
        ContextClient context0 = new ContextClient(new NoDiscountStrategy(48.5, 20));
        log.info("0折扣:{}", context0.contextCalDisc());

        // 固定折扣
        ContextClient contextFix = new ContextClient(new FixDiscountStrategy(46, 60));
        log.info("固定折扣:{}", contextFix.contextCalDisc());

        // 百分比折扣
        ContextClient contextPercentage = new ContextClient(new PercentageDiscountStrategy(38, 40));
        log.info("15%折扣:{}", contextPercentage.contextCalDisc());
    }
}

5. 计算结果

18:43:02.503 [main] INFO com.xiaobai.design_pattern.strategy.StrategyTest - 0折扣:0.0
18:43:02.508 [main] INFO com.xiaobai.design_pattern.strategy.StrategyTest - 固定折扣:60.0
18:43:02.510 [main] INFO com.xiaobai.design_pattern.strategy.StrategyTest - 15%折扣:228.0

三. 总结

1. 策略模式优点

(1)策略模式使用继承的方法可以把公共的代码移到父类中,避免代码重复;
(2)避免算法的使用者和算法本身混合到一起,便于扩展;
(3)可以避免使用多重条件转移语句;

2. 策略模式缺点

(1)策略模式只适用于客户端知道所有算法的情况;
(2)策略模式会造成很多的策略类,可以使用享元模式减少对象的数量;

韩敬海 设计模式(Java版)

你可能感兴趣的:(设计模式,设计模式,java,策略模式)