书店推出打折消息:
[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,
"
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}
{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
本文转自zhangjunhd51CTO博客,原文链接:http://blog.51cto.com/zhangjunhd/64871,如需转载请自行联系原作者