策略模式
意图
定义一系列算法,把他们一个个封装,并且使得算法可独立于他的客户而变化
适用性
1、许多相关的类仅仅是行为有异,策略模式提供了一种用多个行为中的一个行为来配置一个类的方法
2、需要使用一个算法的不同编特
3、算法使用客户不应该知道的数据,可食用策略模式避免暴露复杂的,与算法相关的数据结构
4、一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入他们各自的Strategy类中以代替这些条件语句
结构
Strategy
定义所支持的算法的公共接口,是所有策略类的父类,它可以是抽象类或具体类,也可以是接口。
ConcreteStrategy
它实现了在抽象策略类中声明的算法,在运行时,具体策略类将覆盖在环境类中定义的抽象策略类对象,使用一种具体的算法实现某个业务处理。
Context
环境类是使用算法的角色,维持一个对Strategy的引用,可定义一个接口来让Strategy访问他的数据,用于定义所采用的策略。
实现
策略模式比较简单,就拿华山旅游门票来说,不同的类型有不同的折扣,比如学生价8折,三种类型不叠加
package strategy;
/**
* @Author fitz.bai
* @Date 2018/9/10 19:42
*/
public class MountainHua {
private double price;
private Discount discount;
public void setPrice(double price) {
this.price = price;
}
public void setDiscount(Discount discount) {
this.discount = discount;
}
public double priceAfterDiscount() {
return discount.discount(this.price);
}
}
package strategy;
/**
* @Author fitz.bai
* @Date 2018/9/10 19:41
*/
interface Discount {
double discount(double price);
}
package strategy;
/**
* @Author fitz.bai
* @Date 2018/9/10 19:43
*/
public class AnnualTicketDiscount implements Discount {
@Override
public double discount(double price) {
return price * 0.7;
}
}
package strategy;
/**
* @Author fitz.bai
* @Date 2018/9/10 19:43
*/
public class ChildrenDiscount implements Discount {
@Override
public double discount(double price) {
return price * 0.5;
}
}
package strategy;
/**
* @Author fitz.bai
* @Date 2018/9/10 19:43
*/
public class StudentDiscount implements Discount {
@Override
public double discount(double price) {
return price * 0.8;
}
}
package strategy;
/**
* @Author fitz.bai
* @Date 2018/9/10 19:40
*/
public class Client {
public static void main(String[] args) {
MountainHua huaShan = new MountainHua();
huaShan.setPrice(100);
huaShan.setDiscount(new StudentDiscount());
// huaShan.setDiscount(new ChildrenDiscount());
// huaShan.setDiscount(new AnnualTicketDiscount());
double nowPrice = huaShan.priceAfterDiscount();
System.out.println("打折后的价格为" + nowPrice);
}
}
策略模式用于算法的自由切换和扩展,它是应用较为广泛的设计模式之一。策略模式对应于解决某一问题的一个算法族,允许用户从该算法族中任选一个算法来解决某一问题,同时可以方便地更换算法或者增加新的算法。只要涉及到算法的封装、复用和切换都可以考虑使用策略模式
优点
1、符合开闭原则,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为
2、策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族,恰当使用继承可以把公共的代码移到抽象策略类中,从而避免重复的代码
3、策略模式提供了一种可以替换继承关系的办法,符合“单一职责原则”
(4) 使用策略模式可以避免多重条件选择语句
(5) 策略模式提供了一种算法的复用机制,由于将算法单独提取出来封装在策略类中,因此不同的环境类可以方便地复用这些策略类。
缺点
1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况
2、策略模式将造成系统产生很多具体策略类,任何细小的变化都将导致系统要增加一个新的具体策略类
3、无法同时在客户端使用多个策略类,也就是说,在使用策略模式时,客户端每次只能使用一个策略类,不支持使用一个策略类完成部分功能后再使用另一个策略类来完成剩余功能的情况。