Java设计模式之策略模式
1,什么是策略模式?
策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
2,策略模式有什么好处?
策略模式的好处在于你可以动态的改变对象的行为。
3,设计原则
设计原则是把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口(c++z中可以用虚类),然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。下面是一个例子。
策略模式属于对象行为型模式,主要针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响
到客户端的情况下发生变化。通常,策略模式适用于当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。
4 ,策略模式中有三个对象:
(1)环境对象(Context):该类中实现了对抽象策略中定义的接口或者抽象类的引用。
(2)抽象策略对象(Strategy):它可由接口或抽象类来实现。
(3)具体策略对象(ConcreteStrategy):它封装了实现同不功能的不同算法。
利用策略模式构建应用程序,可以根据用户配置等内容,选择不同有算法来实现应用程序的功能。具体的选择有环境对象来完成。采用这种方式可以避免由于使用条件语句而带来的代码混乱,提高应用程序的灵活性与条理性。
5,编写策略模式的一般步骤:
(1) 对策略对象定义一个公共接口
(2) 编写具体策略类,该类实现了上面的接口
(3) 在使用策略对象的类(即:环境角色)中保存一个对策略对象的引用
(4) 在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值
(5)客户端进行调用
6,实例
本文例子是,完成一个简单地购物车,两种付款策略可供选择,一为信用卡,另外一种为Paypal。
首先创建策略接口,在本文例子中,付款金额作为参数。
1 public interface PaymentStrategy { 2 3 public void pay(int amount); 4 }
现在实现使用信用卡及Paypal两种算法策略的实体类。
1 public class CreditCardStrategy implements PaymentStrategy { 2 3 private String name; 4 private String cardNumber; 5 private String cvv; 6 private String dateOfExpiry; 7 8 public CreditCardStrategy(String nm, String ccNum, String cvv, String expiryDate){ 9 this.name=nm; 10 this.cardNumber=ccNum; 11 this.cvv=cvv; 12 this.dateOfExpiry=expiryDate; 13 } 14 @Override 15 public void pay(int amount) { 16 System.out.println(amount +" paid with credit/debit card"); 17 } 18 19 }
1 public class PaypalStrategy implements PaymentStrategy { 2 3 private String emailId; 4 private String password; 5 6 public PaypalStrategy(String email, String pwd){ 7 this.emailId=email; 8 this.password=pwd; 9 } 10 11 @Override 12 public void pay(int amount) { 13 System.out.println(amount + " paid using Paypal."); 14 } 15 16 }
此时,算法策略已经准备就绪,现在需要实现购物车以及能够运用付款策略的支付方法。
1 public class Item { 2 3 private String upcCode; 4 private int price; 5 6 public Item(String upc, int cost){ 7 this.upcCode=upc; 8 this.price=cost; 9 } 10 11 public String getUpcCode() { 12 return upcCode; 13 } 14 15 public int getPrice() { 16 return price; 17 } 18 19 }
1 public class ShoppingCart { 2 3 //List of items 4 List<Item> items; 5 6 public ShoppingCart(){ 7 this.items=new ArrayList<Item>(); 8 } 9 10 public void addItem(Item item){ 11 this.items.add(item); 12 } 13 14 public void removeItem(Item item){ 15 this.items.remove(item); 16 } 17 18 public int calculateTotal(){ 19 int sum = 0; 20 for(Item item : items){ 21 sum += item.getPrice(); 22 } 23 return sum; 24 } 25 26 public void pay(PaymentStrategy paymentMethod){ 27 int amount = calculateTotal(); 28 paymentMethod.pay(amount); 29 } 30 }
注意,购物车的支付方法接受支付策略作为参数,但是不在其内部保存任何实例变量。
一个简单地测试程序。
1 public class ShoppingCartTest { 2 3 public static void main(String[] args) { 4 ShoppingCart cart = new ShoppingCart(); 5 6 Item item1 = new Item("1234",10); 7 Item item2 = new Item("5678",40); 8 9 cart.addItem(item1); 10 cart.addItem(item2); 11 12 //pay by paypal 13 cart.pay(new PaypalStrategy("myemail@example.com", "mypwd")); 14 15 //pay by credit card 16 cart.pay(new CreditCardStrategy("Pankaj Kumar", "1234567890123456", "786", "12/15")); 17 } 18 19 }
输出如下:
50 paid using Paypal.
50 paid with credit/debit card
策略模式UML图
重要点:
* 此处可以构建策略的实体变量,但是应该尽量避免这种情况。因为需要保证对于特定的任务能够对应某个具体的算法策略,与Collection.sort()和Array.sort()方法使用comparator作为参数道理类似。
* 策略模式类似与状态模式。两者之间的不同,状态模式中的Context(环境对象)包含了状态的实例变量,并且不同的任务依赖同一个状态。相反,在策略模式中策略是作为一个参数传递进方法中,context(环境对象)不需要也不能存储任何变量。
* 当一组算法对应一个任务,并且程序可以在运行时灵活的选择其中一个算法,策略模式是很好的选择。
转载自并发编程网 – ifeve.com链接地址: Java中的策略模式实例教程