策略模式
定义:策略模式对应于解决某一个问题的一个算法族,允许用户从该算法族中任选一个算法解决某一问题,同时可以方便的更换算法或者增加新的算法,并且由客户端决定调用哪个算法。
角色:
1)抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
2)具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
3)环境(Context)类:持有一个策略类的引用,最终给客户端调用。
本质:分离算法,选择实现
图示:
package com.offcn.designpattern.strategypattern; public class StragegypatternDemo { public static void main(String[] args) { Stragegy s1= new OldCustomerFewStragegy(); Context c1 = new Context(s1); c1.printPrice(543); Stragegy s2 = new NewCustomerManyStragegy(); Context c2 = new Context(s2); c2.printPrice(543); } } //上下文角色,负责和具体的策略类交互 class Context{ private Stragegy stragegy; public Context(Stragegy stragegy) { this.stragegy = stragegy; } public void printPrice(double price){ System.out.println("您该报价" stragegy.getPrice(price)); } } //策略接口 interface Stragegy{ public double getPrice(double price); } //新用户小批量购买 class NewCustomerFewStragegy implements Stragegy{ @Override public double getPrice(double price) { System.out.println("原价购买"); return price; } } //新用户,大批量购买 class NewCustomerManyStragegy implements Stragegy{ @Override public double getPrice(double price) { System.out.println("95折"); return price * 0.95; } } //老用户,小批量购买 class OldCustomerFewStragegy implements Stragegy { @Override public double getPrice(double price) { System.out.println("9折"); return price * 0.90; } } //老用户,大批量购买 class OldCustomerManyStragegy implements Stragegy{ @Override public double getPrice(double price) { System.out.println("85折"); return price * 0.85; } }
输出;
优点:
1)多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句。
2)策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
3)策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
4)策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
5)策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。
缺点:
1)客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
2)策略模式造成很多的策略类。
使用场景:
1) javase中的GUI编程,布局管理
2) spring框架中,resource接口,资源访问策略
3) javax.servlet.http.HttpServlet#service()