策略模式
在策略模式(Strategy Pattern)中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
介绍
意图: 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决: 在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
何时使用: 一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决: 将这些算法封装成一个一个的类,任意地替换。
关键代码: 实现同一个接口。
应用实例:
- 商场促销方式,不同的打折、满减活动等
- 旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
- JAVA AWT 中的 LayoutManager。
优点:
- 算法可以自由切换。
- 避免使用多重条件判断。
- 扩展性良好。
缺点:
- 策略类会增多。
- 所有策略类都需要对外暴露。
使用场景:
- 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 一个系统需要动态地在几种算法中选择一种。 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项:
如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
策略模式包含以下几个核心角色:
环境(Context): 维护一个对策略对象的引用,负责将客户端请求委派给具体的策略对象执行。环境类可以通过依赖注入、简单工厂等方式来获取具体策略对象。
抽象策略(Abstract Strategy): 定义了策略对象的公共接口或抽象类,规定了具体策略类必须实现的方法。
具体策略(Concrete Strategy): 实现了抽象策略定义的接口或抽象类,包含了具体的算法实现。
策略模式通过将算法与使用算法的代码解耦,提供了一种动态选择不同算法的方法。客户端代码不需要知道具体的算法细节,而是通过调用环境类来使用所选择的策略。
代码实现
以购买商品为例子,不同的商品的优惠力度不一样,有满减、有打折,用户购买后按照折后价进行购买。
定义用户类
/**
* 账号
*/
public class Account {
private final String name;
private float totalMoney;
public Account(String name, float totalMoney)
{
this.name = name;
this.totalMoney = totalMoney;
}
public void buy(Goods goods){
float oldMoney = totalMoney;
float buyMoney = goods.getStrategy().money(goods.getPrice());
if(buyMoney > totalMoney){
System.out.printf("商品原价:%.2f,折后价:%.2f,%s账户余额不足,旧余额为:%.2f,新余额:%.2f\n",goods.getPrice(),buyMoney,name,oldMoney,totalMoney);
}else{
totalMoney -= buyMoney;
System.out.printf("商品原价:%.2f,折后价:%.2f,%s账户购买成功,旧余额为:%.2f,新余额:%.2f\n",goods.getPrice(),buyMoney,name,oldMoney,totalMoney);
}
}
}
定义价格策略接口
public interface Strategy {
float money(float money);
}
实现价格策略
/**
* 正常价格
*/
public class NormalStrategy implements Strategy{
@Override
public float money(float money) {
return money;
}
}
/**
* 满减活动
*/
public class FullReductionStrategy implements Strategy{
private float fullMoney;
private float reduceMoney;
public FullReductionStrategy(float fullMoney, float reduceMoney)
{
this.fullMoney = fullMoney;
this.reduceMoney = reduceMoney;
}
public float money(float money)
{
if (money >= fullMoney)
{
return money - reduceMoney;
}
else
{
return money;
}
}
}
/**
* 打折活动
*/
public class DiscountStrategy implements Strategy{
/**
* 折扣
*/
private float discount;
public DiscountStrategy(float discount){
this.discount = discount;
}
@Override
public float money(float money) {
return money*discount;
}
}
定义商品抽象类
/**
* 商品
*/
public abstract class Goods {
private String name;
private float price;
private Strategy strategy;
public Goods(String name, float price, Strategy strategy)
{
this.name = name;
this.price = price;
this.strategy = strategy;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
public Strategy getStrategy() {
return strategy;
}
}
定义书商品
public class Book extends Goods{
public Book(String name, float price, Strategy strategy) {
super(name, price, strategy);
}
}
定义鞋商品类
public class Shoes extends Goods{
public Shoes(String name, float price, Strategy strategy) {
super(name, price, strategy);
}
}
客户端
public class Client {
public static void main(String[] args) {
Account account = new Account("张三", 1000);
Book book = new Book("Java", 100, new NormalStrategy());//正常策略
Book book2 = new Book("C++", 100, new DiscountStrategy(0.8f));//打八折
Book book3 = new Book("Python", 100, new FullReductionStrategy(100, 50));//满100减50
Shoes shoes = new Shoes("NIKE", 100, new NormalStrategy());
Shoes shoes2 = new Shoes("Adidas", 100, new DiscountStrategy(0.8f));
Shoes shoes3 = new Shoes("Puma", 100, new FullReductionStrategy(100, 50));
Shoes shoes1 = new Shoes("NIKE VIP", 600, new NormalStrategy());
account.buy(book);
account.buy(book2);
account.buy(book3);
account.buy(shoes);
account.buy(shoes2);
account.buy(shoes3);
account.buy(shoes1);
}
}