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中的策略模式实例教程

posted @ 2016-09-02 17:22  夏嘻嘻嘻嘻嘻  阅读(334)  评论(0编辑  收藏  举报