策略模式能够将每一个策略封装到一个类中,这些类又具有共同接口,利用Java多态的特性就能够实现它们的相互替换。
例如我们去图书馆买书,会有很多种类的书,但是我们支付的时候都是去同一个地方支付的。因为收银员可以根据书本的条形码,执行不同的策略类计算书的价格。在这个时候,首先收银员要通过书的条形码知道是哪一本书,才能得到价格。策略模式也是如此,虽然策略类之间能够相互替换,但是收银员需要知道自己要调用哪一个策略类,才能知道金额。
案例
设计一个网上书店,该系统中所有的计算机类图书(ComputerBook)每本都有10%的折扣,所有的语言类图书(LanguageBook) 每本都有2元的折扣,小说类图书(NovelBook)每100元有10元的折扣。现使用策略模式来设计该系统,绘制类图并编程实现。
类图如下:
代码如下:
Book.java
public abstract class Book {
abstract Double discount(Double price);
}
NovelBook.java
public class NovelBook extends Book {
@Override
Double discount(Double price) {
return price-((int)(price/100))*10;
}
}
ComputerBook.java
public class ComputerBook extends Book {
@Override
Double discount(Double price) {
return 0.9*price;
}
}
LanguageBook.java
public class LanguageBook extends Book {
@Override
Double discount(Double price) {
return price-2;
}
}
User.java
public class User {
private Book book;
public void setBook(Book book) {
this.book = book;
}
public Double discount(Double price){
return book.discount(price);
}
}
测试代码:
public class Main {
public static void main(String[] args) {
User u=new User();
u.setBook(new ComputerBook());
System.out.println(u.discount(232.99));
u.setBook(new LanguageBook());
System.out.println(u.discount(232.99));
u.setBook(new NovelBook());
System.out.println(u.discount(232.99));
}
}
测试结果:
总结
当添加一个新的策略类时,无需改动原来的代码,遵循OCP原则。不同的策略类之间能够很容易的相互替换。但是使用策略模式,客户必须知道所有策略类,才能自行决定要使用哪一个类。这就意味着客户端必须理解这些类之间有什么区别,才能根据不同场景选择正确的类。 同时,策略模式的每一个策略都要单独封装为类,和命令模式一样也是1:1的关系,因此也会造成类数目过多。