注册 | 登录 忘记密码? 51cto首页 | 博客 | 论坛 | 招聘
热点文章 批处理帐号导入
 帮助

一个图书打折系统的设计


2008-03-10 00:50:56
版权声明:原创作品,如需转载,请与作者联系。否则将追究法律责任。
书店推出打折消息:
[1]对于“新书”,没有折扣;
[2]对于“计算机”类图书,固定折扣为10元;
[3]对于“经管”类图书,折扣的书价的10%
[4]购买5本以上的图书,固定折扣为20元;
[5]在所有的折扣计算后,总的折扣价不得超过50元。
 
1.使用Strategy模式
对于打折消息[1],[2],[3]针对三种类型的图书,可以使用Strategy模式。

NoDiscountStrategy代表购买“新书”的打折策略-没有折扣;
FlatRateStrategy代表购买“计算机”类图书的打折策略-固定折扣价;
PercentageStrategy代表购买“经管”类图书的打折策略-百分比折扣价。
<<abstract>>DiscountStrategy.java
package com.zj.books.strategy;
 
public abstract class DiscountStrategy {
    protected double _price = 0.0;
 
    public DiscountStrategy(double price) {
       _price = price;
    }
 
    abstract public double calculateDiscount();
……
}
_price代表图书的价格;抽象方法calculateDiscount()表示具体的打折计算逻辑,延迟到子类中实现。下面的三个子类的部分逻辑。
 
NoDiscountStrategy.java
package com.zj.books.strategy;
 
public class NoDiscountStrategy extends DiscountStrategy {
 
    public NoDiscountStrategy(double price) {
       super(price);
    }
 
    public double calculateDiscount() {
       return 0.0;
    }
}
 
FlatRateStrategy.java
package com.zj.books.strategy;
 
public class FlatRateStrategy extends DiscountStrategy {
    private double _discount = 0.0;
 
    public FlatRateStrategy(double price, double discount) {
       super(price);
       _discount = discount;
    }
   
    public double calculateDiscount() {
       return _discount;
    }
……
}
 
PercentageStrategy.java
package com.zj.books.strategy;
 
public class PercentageStrategy extends DiscountStrategy {
    private double _percent = 1.0;
 
    public PercentageStrategy(double price, double percent) {
       super(price);
       if (percent > 1.0)
           percent = 1.0;
       _percent = percent;
    }
 
    public double calculateDiscount() {
       return _price * _percent;
    }
……
}
使用一个抽象基类Book持有一个策略引用,这个策略是抽象基类的引用。这个类中提供一个重要的方法getDiscount()通过分配的具体策略的_strategy.calculateDiscount()方法来得到折扣。而如何实现Book具体子类与Strategy具体子类的配对,将使用工厂方法模式。

<<abstract>> Book.java
package com.zj.books;
 
import com.zj.books.strategy.DiscountStrategy;
 
public abstract class Book {
    protected String _name;
    protected int _typeCode;
    protected double _price;
    protected DiscountStrategy _strategy;
 
    public Book(String name, int bookType, double price) {
       _name = name;
       _typeCode = bookType;
       _price = price;
    }
 
    public double getDiscount() {
       return _strategy.calculateDiscount();
    }
   
……
}
2.使用 Factory Method模式
对于策略的分配,使用Factory Method模式。这样对于书的种类和打折策略都是可以扩展的。

三个具体的Publish类分别针对三种类型的书和三种打折策略,给出具体的对象。
<<interface>> Publisher.java
package com.zj.purchase;
 
import com.zj.books.Book;
 
public interface Publisher {
    Book bookFactory(String name,double price);
}
三个具体的子类实现bookFactory方法,分别生成配对的具体Book类和具体Strategy类。
ComputerBookPublish.java
package com.zj.purchase;
 
import com.zj.books.Book;
import com.zj.books.ComputerBook;
import com.zj.books.strategy.FlatRateStrategy;
 
public class ComputerBookPublish implements Publisher{
    private double _discount=0.0;
   
    public ComputerBookPublish(double discount){
       _discount=discount;
    }
 
    public Book bookFactory(String name,double price) {
       Book book=new ComputerBook(name,price);
       book.setStrategy(new FlatRateStrategy(price, _discount));
       return book;
    }
……
}
 
ManagementBookPublish.java
package com.zj.purchase;
 
import com.zj.books.Book;
import com.zj.books.ManagementBook;
import com.zj.books.strategy.PercentageStrategy;
 
public class ManagementBookPublish implements Publisher{
    private double _percent=1.0;
   
    public ManagementBookPublish(double percent){
       _percent=percent;
    }
 
    public Book bookFactory(String name,double price) {
       Book book=new ManagementBook(name,price);
       book.setStrategy(new PercentageStrategy(price, _percent));
       return book;
    }
……
}
 
NewReleaseBookPublisher.java
package com.zj.purchase;
 
import com.zj.books.Book;
import com.zj.books.NewReleaseBook;
import com.zj.books.strategy.NoDiscountStrategy;
 
public class NewReleaseBookPublisher implements Publisher{
 
    public Book bookFactory(String name,double price) {
       Book book=new NewReleaseBook(name,price);
       book.setStrategy(new NoDiscountStrategy(price));
       return book;
    }
}
3.使用Decorate模式
对于[4][5]可使用Decorate模式实现。

Order类是一个接口,定义了所有客户端可以使用的行为。其中buy()方法表示购买书,其中的参数依次表示册数,书名,单价,和图书类型;originalPay()方法表示原始货款;actualPay()表示实际货款;discount()表示折扣;addPolicy()方法将被应用于Decorate模式。
<<interface>>Order.java
package com.zj.order;
 
public interface Order {
    void buy(int copies,String name,int price,int type);
   
    double originalPay();
 
    double actualPay();
   
    void setActualPay(double pay);
 
    double discount();
   
    void setDiscount(double discount);
   
    int getCopies();
   
    void printPayList();
   
    void addPolicy();
}
PayOrder类是一个基于打折消息[1],[2],[3]的应用,在buy()方法中,根据具体的图书类型,产生一个具体的publisher类,继而可以获得相应的图书实例及折扣策略实例。
PayOrder.java
package com.zj.order;
 
import java.util.HashMap;
import java.util.Map;
 
import com.zj.books.Book;
import com.zj.books.BookType;
import com.zj.purchase.ComputerBookPublish;
import com.zj.purchase.ManagementBookPublish;
import com.zj.purchase.NewReleaseBookPublisher;
 
public class PayOrder implements Order {
    private Map<String, Integer> payList = new HashMap<String, Integer>();
    private double _pay = 0.0;
    private double _discount = 0.0;
    private int _copies = 0;
 
    private double _discountPolicy = 0.0;
    private double _percentagePolicy = 1.0;
 
    public PayOrder(double discountPolicy, double percentagePolicy) {
       _discountPolicy = discountPolicy;
       _percentagePolicy = percentagePolicy;
    }
 
    public void buy(int copies, String name, int price, int type) {
       Book book = null;
       switch (type) {
       case BookType.NEW_RELEASE:
           book = new NewReleaseBookPublisher().bookFactory(name, price);
           break;
       case BookType.COMPUTER:
           book = new ComputerBookPublish(_discountPolicy).bookFactory(name,
                  price);
           break;
       case BookType.MANAGEMENT:
           book = new ManagementBookPublish(_percentagePolicy).bookFactory(
                  name, price);