程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 使用Java設計一個圖書打折系統

使用Java設計一個圖書打折系統

編輯:關於JAVA

書店推出打折消息:

[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);
      break;
    default:
      throw new RuntimeException("Type not found.");
    }
    _copies += copies;
    payList.put(book.getName(), copies);
    _pay += copies * book.getPrice();
    _discount += copies * book.getDiscount();
   }
   public double originalPay() {
    return _pay;
   }
   public double actualPay() {
    return _pay - _discount;
   }
   public void setActualPay(double pay) {
    _pay = pay;
   }
   public double discount() {
    return _discount;
   }
   public void setDiscount(double discount) {
    _discount = discount;
   }
   public int getCopies() {
    return _copies;
   }
   public void printPayList() {
    System.out.println(toString());
   }
   public void addPolicy() {
   }
   public String toString() {
    return payList.toString();
   }
}

OrderDecorator是一個裝飾角色,它持有一個Order的引用。

OrderDecorator.java

package com.zj.order.decorator;
import com.zj.order.Order;
public class OrderDecorator implements Order {
   protected Order _order;
   public OrderDecorator(Order order) {
    _order = order;
   }
   public double actualPay() {
    return _order.actualPay();
   }
   public void setActualPay(double pay) {
    _order.setActualPay(pay);
   }
   public void buy(int copies, String name, int price, int type) {
    _order.buy(copies, name, price, type);
   }
   public double discount() {
    return _order.discount();
   }
   public void setDiscount(double discount) {
    _order.setDiscount(discount);
   }
   public double originalPay() {
    return _order.originalPay();
   }
   public int getCopies() {
    return _order.getCopies();
   }
   public void printPayList(){
    _order.printPayList();
   }
   public void addPolicy(){
    _order.addPolicy();
   }
}

根據打折消息[4]:“購買5本以上的圖書,固定折扣為20元”,得到具體裝飾角色CopyDecorator。它將重寫addPolicy()方法。

CopyDecorator.java

package com.zj.order.decorator;
import com.zj.order.Order;
public class CopyDecorator extends OrderDecorator {
   public CopyDecorator(Order order) {
    super(order);
   }
   public void addPolicy() {
    if (getCopies() > 5)
      setDiscount(discount() + 20);
    super._order.addPolicy();
   }
}

根據打折消息[5]:“在所有的折扣計算後,總的折扣價不得超過50元”,得到具體裝飾角色PayDecorator。它將重寫addPolicy()方法。

必須注意兩個裝飾類產生的先後順序。

PayDecorator.java

package com.zj.order.decorator;
import com.zj.order.Order;
public class PayDecorator extends OrderDecorator {
   public PayDecorator(Order order) {
    super(order);
   }
   public void addPolicy() {
    if (discount() > 50)
      setDiscount(50);
    super._order.addPolicy();
   }
}

4.客戶端實現

Client中先演示了沒有裝飾類,即只實現打折消息[1],[2],[3]的情況,此時原價300元的貨款折扣為36元;而後加上了兩個裝飾類後,由於購買六本書,另加29元折扣後總折扣變為56,超過50元的折扣上限,所以最終折扣為50元。

Client.java

package com.zj.client;
import com.zj.books.BookType;
import com.zj.order.Order;
import com.zj.order.PayOrder;
import com.zj.order.decorator.CopyDecorator;
import com.zj.order.decorator.PayDecorator;
public class Client {
    public static void main(String[] args) {
       Order order = new PayOrder(10, 0.1);
       order.buy(1, "Java", 40, BookType.COMPUTER);
       order.buy(1, "C++", 60, BookType.COMPUTER);
       order.buy(1, "Design Pattern", 100, BookType.COMPUTER);
       order.buy(1, "Manager", 60, BookType.MANAGEMENT);
       order.buy(1, "Apo", 20, BookType.NEW_RELEASE);

       order.buy(1, "droAq", 20, BookType.NEW_RELEASE);
       order.printPayList();
       System.out.println("===========");
       System.out.println("original\t"+order.originalPay());
       System.out.println("discount\t"+order.discount());
       System.out.println("actual\t\t"+order.actualPay());
       System.out.println("===========");
       order=new CopyDecorator(new PayDecorator(order));
       order.addPolicy();
       System.out.println("original\t"+order.originalPay());
       System.out.println("discount\t"+order.discount());
       System.out.println("actual\t\t"+order.actualPay());
    }
}

結果

{Apo=1, Manager=1, droAq=1, C++=1, Design Pattern=1, Java=1}
===========
original  300.0
discount  36.0
actual   264.0
===========
original  300.0
discount  50.0
actual   250.0

本文出自 “子 孑” 博客,請務必保留此出處http://zhangjunhd.blog.51cto.com/113473/64871

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved