设计模式-策略模式

时间:2022-05-05 00:20:48

软件设计的原则

1: 找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起

2:针对接口编程,而不是针对实现编程

策略模式的定义

 定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

通俗的将就是使用动态注入的对象或实现来动态替换某种具体行为.

使用场景

1.针对同一类型问题的多种处理方式,仅仅是具体行为有差别 
2.需要安全的封装多种同一类型的操作 
3.出现同一抽象类有多个子类,而又需要使用条件语句来选择 具体子类时

关键点

一个抽象的策略或算法

一个或多个具体的抽象实现

一个操作策略或算法的上下文,持有抽象,可以动态注入具体实现


策略模式实例结构

                               1:环境对象

                               2:抽象策略角色:给出所有具体策略角色使用的接口

                               3:具体策略角色:抽象策略角色的实现类

设计模式-策略模式

经典案例

设计售卖各类图书的购物车系统

      思路:由于各类图书的折扣价不一致,而且可能后续还会有其他的折扣算法出现,所有为了系统的高扩展和高维护性,使用策略模式来进行实现

UML图设计模式-策略模式

策略抽象类

abstract public class DiscountStrategy {
    private int price = 0;
    private int copies = 0;


    /**  * 策略方法  * @return  */  public abstract int calculateDiscount();

    /**  * 初始化值  * @param price  * @param copies  */  public DiscountStrategy(int price, int copies) {
        this.price = price;
        this.copies = copies;
    }

策略具体实现类

public class FlatRateStrategy extends DiscountStrategy {

    private int price;
    private int copies;

    /**  * 初始化值  *  * @param price  * @param copies  */  public FlatRateStrategy(int price, int copies) {
        super(price, copies);
        this.price = price;
        this.copies = copies;
    }

    @Override
    public int calculateDiscount() {
        return 0;
    }
}
ublic class NoDiscountStrategy extends DiscountStrategy {
    private int price;
    private int copies;
    private int amount;

    /**  * 初始化值  *  * @param price  * @param copies  */  public NoDiscountStrategy(int price, int copies) {
        super(price, copies);
        this.price = price;
        this.copies = copies;
    }


    /**  * 策略的具体实现  * @return  */  @Override
    public int calculateDiscount() {
        return copies * amount;
    }

    public int getAmount() {
        return amount;
    }

    public void setAmount(int amount) {
        this.amount = amount;
    }
public class PercentageStrategy extends DiscountStrategy {
    private int precent;
    private int price;
    private int copies;

    /**  * 初始化值  *  * @param price  * @param copies  */  public PercentageStrategy(int price, int copies) {
        super(price, copies);
        this.price = price;
        this.copies = copies;
    }


    /**  * 策略的具体实现  * @return  */  @Override
    public int calculateDiscount() {
        return copies*price*precent;
    }

    public int getPrecent() {
        return precent;
    }

    public void setPrecent(int precent) {
        this.precent = precent;
    }
}

环境对象类

public class BookContext {

    /*私有化构造器*/
    private BookContext() {

    }

    /*策略对象*/
    private DiscountStrategy discountStrategy;

    /**  * 提供对外的方法  * @return  */  public int calculateDiscount(){
        return discountStrategy.calculateDiscount();
    }

    public static BookContext getInstance() {
        return BookContextLoadHolder.INSTANCE;
    }

    /**  * 内部类 提供独有的实例  */  public static final class BookContextLoadHolder {
        private static final BookContext INSTANCE = new BookContext();
    }

    public DiscountStrategy getDiscountStrategy() {
        return discountStrategy;
    }

    public void setDiscountStrategy(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }
}

测试类

public class TestStrategy {

    public static void main(String[] args) {
        BookContext context = BookContext.getInstance();
        context.setDiscountStrategy(new FlatRateStrategy(100, 10));
        System.out.println("FlatRateStategy---->"+context.calculateDiscount());
        NoDiscountStrategy noDiscountStrategy = new NoDiscountStrategy(100, 10);
        noDiscountStrategy.setAmount(10);
        context.setDiscountStrategy(noDiscountStrategy);
        System.out.println("NoDiscountStrategy------>"+context.calculateDiscount());
        PercentageStrategy percentageStrategy = new PercentageStrategy(100, 10);
        percentageStrategy.setPrecent(10);
        context.setDiscountStrategy(percentageStrategy);
        System.out.println("percentageStrategy------>"+context.calculateDiscount());
    }

这样我们就实现了根据业务的需求来灵活的变更折扣的计算方式

什么情况下使用策略模式

1:系统里面有许多类的区别仅在于它们的行为。

2:系统需要动态地在几种算法中选择一种

3:  当系统使用的算法需要保密的时候

4:   一个对象有很多的行为

策略模式的优点和缺点

优点

1:   提供了管理相关算法族的办法

2:    提供了可以替换继承关系的办法

3:    可以避免多重条件判断语句

缺点

1:    只适用于客户端知道所有的算法或行为的时候

2:    造成很多的策略类

言而总之策略模式能解决继承带来的负面效应,提高系统的灵活性与可扩展性,最大程度的体现了开闭原则.但是随之而来的是需要客户端对策略的行为或算法了解较为清楚,不然就会出来不知道到底使用哪一个具体的策略实现者这种情况.