首页 > 代码库 > Java设计模式之策略模式

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     @Override15     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     @Override12     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 paypal13         cart.pay(new PaypalStrategy("myemail@example.com", "mypwd"));14 15         //pay by credit card16         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中的策略模式实例教程

Java设计模式之策略模式