32. 策略模式

定义

策略模式(Strategy Pattern):定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。

通俗理解

每天我们都会思考三个问题,早餐吃什么?午餐吃什么?晚餐吃什么?这三个问题也被称为人生的三大问题。在思考这三个问题的时候,我们需要考虑多种因素,价格、食物类型、口味、是否有折扣等等,在思考这些问题的过程中,我们就不禁陷了进去?我们应该吃什么呢?

对此,我想到了一个十分简单粗暴的方式,就是按照时间来选择。假设现在有三家店,店A、店B、店C。周一、三、五我们去店A,周二、四我们去店B,周末我们去店C。那么我们就可以很好地解决掉我们人生的三大问题了。

像这种有不同解决方案的,就是策略。我们现在预想着要怎么去实现它。第一个选择就是if(1 || 3 || 5){return A;}else if(2 || 4){return B;}else{return C;},很好,这是实现了。但是考虑到扩展性,如果我们2 去 D了,那么我得修改源代码吧?这样修改起来,就违反了开闭原则了。

怎么办?那就需要采用策略模式了,说白了,就是定义一个策略的接口类,然后具体的策略去实现这个接口。然后设定一个环境类,维护策略的成员变量,更加这个变量的实际值调用不同的策略就可以了。在选择食物这里,策略的接口指的是选择不同的店家,具体的策略就是店家的实现,环境就是人类,维护了店家的接口。

示例

渣渣程序

食物接口

public class Food {
    public void selectFood(Day day) {
        switch (day) {
            case MON:System.out.println("A");break;
            case TUES:System.out.println("B");break;
            case WED:System.out.println("A");break;
            case THUR:System.out.println("B");break;
            case FRI:System.out.println("A");break;
            case SAT:System.out.println("C");break;
            case SUN:System.out.println("C");break;
            default:System.out.println("A");
        }
    }
    public enum Day{
        MON,TUES, WED, THUR, FRI, SAT, SUN
    }
}

程序入口

public class Main {
    public static void main(String[] args) {
        Food food = new Food();
        food.selectFood(Food.Day.SAT);
    }
}
//A

上面有两个问题:

  1. 职责不明确,选择店家不应该是食物选择的,而是人去选择;
  2. 扩展不友好,如果需要添加一个店家D,那么我需要修改源代码。

优化

类图

image

程序

食物接口和实现

public interface IFood {
    void selectFood();
}
public class AFood implements IFood {
    @Override
    public void selectFood() {
        System.out.println("A");
    }
}
// BFood、CFood类似

人类

public class Human {
    private IFood food;
    // 构造器、setter、getter省略
    public void selectFood() {
        food.selectFood();
    }
}

程序入口

public class Main {
    public static void main(String[] args) {
        IFood food = new AFood();
        Human human = new Human(food);
        human.selectFood();
    }
}
//A

如果我需要添加店家D,那我只需要把店家D作为一个新的实现就可以了。

优点

  1. 符合开闭原则,不修改源代码的情况下添加新的功能;
  2. 管理算法族,使用继承把公用的代码放到抽象类当中;
  3. 避免多条件的if...else;
  4. 复用,策略提供给不同的环境使用。

缺点

  1. 需要知道调用哪个具体的策略类;
  2. 很多的策略实现;
  3. 无法使用多个策略,意思是不能在一个策略完成之后,调用另外一个策略。

应用场景

  1. 替换if...else...

程序

e32_strategy_pattern

吐槽

其实还是感觉还是要用if...else来决定创建不同的对象,然后让他们入参,但是这个步骤移到了客户端(Main)来写,就是动态了,令人费解。其实还有一种方式,就是通过工厂模式去创建不同的对象,然后当做入参,if...else语句可以使用Xml配置文件去写,读取配置文件之后,然后根据配置文件的定义,去创建不同的对象。

https://www.jianshu.com/p/c6a173a39a06

你可能感兴趣的:(32. 策略模式)