北邮JAVA高级语言程序设计(选修课)设计模式大作业
题目描述:
设计模式一(单子、工厂、策略模式)练习
1. 假设现在要设计一个贩卖各类书籍的电子商务网站的购物车系统。对所有的教材类图书 实行每本一元的折扣;对连环画类图书提供每本7%的促销折扣;而对非教材类的计算机图书有3%的折扣;对其余书没有折扣。使用策略模式、工厂模式、单子模式进行设计,类图如下。
类图说明:
Sale:代表依次销售。getTotal方法用于返回本次销售的优惠后总价。
SaleLineItem:代表一个销售项目。1次销售会对应多个销售项目。如顾客总共购买了2本《UML与模式应用》,3本《Java与模式》,则对应需要创建两个SaleLineItem对象,1个对应的是2本《UML与模式应用》的购买,1个对应的是3本《Java与模式》的购买。
ProductSpecification:书的描述信息,包括书的isbn号、书名、单价和书的类型。书的类型包括:非教材类的计算机图书、教材类图书、连环画类图书、其他共4种。在本例中共有5种书(见后面描述),因此需要创建5个ProductSpecification对象。
PricingStrategyFactory:策略工厂,负责根据书的类型提供对应的策略类,策略类将根据具体的优惠策略计算折扣后1个销售项目(SaleLineItem)的总价。要求:该策略工厂要设计成单子。
IPricingStrategy:策略类的接口,用于向SaleLineItem屏蔽具体的策略类。
FlatRateStrategy:按每本优惠x元的策略。
PercentageStrategy:按百分比进行优惠的策略。
NoDiscountStrategy:不进行优惠的策略。思考:为什么要设计这个类?如果没有这个类,会引发什么问题?
要求:设计中要考虑优惠的比例(如每本优惠1元、7%、3%)会发生变化?在设计时要考虑到这种变化,使得变化到来时,对现有代码的影响尽量小。
注意:本例中,策略是应用于1个SaleLineItem对象,而不是应用于Sale对象,为什么?
请用Java语言实现上述每一个类,并书写测试类,实现下述场景:
一次购物,购买了2本教材类图书《UML与模式应用》,单价是18元/本;购买了2本非教材类的计算机图书《Java与模式》,单价是34元/本;购买了1本非教材类的计算机图书《HeadFirst 设计模式》,单价是58元/本;购买了3本连环画类图书《爱丽丝历险记》,单价是30元/本;购买了1本其他类图书《煲汤大全》,单价是20元/本。请计算出本次购物优惠后价格。
源代码:
import java.util.ArrayList;
import java.util.Iterator;
public class TestClass {
public static void mian(String[] args)
{
ProductSpecification p1 = new ProductSpecification("00001","UML与模式应用",18,"A");
ProductSpecification p2 = new ProductSpecification("00001","Java与模式",34,"C");
ProductSpecification p3 = new ProductSpecification("00003","HeadFirst设计模式",58,"C");
ProductSpecification p4 = new ProductSpecification("00004","爱丽丝历险记",30,"B");
ProductSpecification p5 = new ProductSpecification("00005","煲汤大全",20,"D");
PricingStrategyFactory factor = PricingStrategyFactory.getInstance();
SaleLineItem item1 = new SaleLineItem(2,p1,factor.getPricingStrategy(p1.getType()));
SaleLineItem item2 = new SaleLineItem(2,p2,factor.getPricingStrategy(p2.getType()));
SaleLineItem item3 = new SaleLineItem(1,p3,factor.getPricingStrategy(p3.getType()));
SaleLineItem item4 = new SaleLineItem(3,p4,factor.getPricingStrategy(p4.getType()));
SaleLineItem item5 = new SaleLineItem(1,p5,factor.getPricingStrategy(p5.getType()));
Sale s = new Sale();
s.addItem(item1);
s.addItem(item2);
s.addItem(item3);
s.addItem(item4);
s.addItem(item5);
System.out.println("The total price is:"+String.format("%.2f",s.getTotal()));
}
}
//书的描述信息,包括书的isbn号、书名、单价和书的类型
class ProductSpecification
{
String ISBN;
String Name;
double Price;
String Type;
public ProductSpecification(String ISBN, String Name, double Price ,String Type)
{
this.ISBN = ISBN;
this.Name = Name;
this.Price =Price;
this.Type = Type;
}
public String getISBN()
{
return ISBN;
}
public String getName()
{
return Name;
}
public double getPrice()
{
return Price;
}
public String getType()
{
return Type;
}
}
//根据具体的优惠策略计算折扣后1个销售项目(SaleLineItem)的总价
class PricingStrategyFactory
{
private static PricingStrategyFactory instance = new PricingStrategyFactory();
private PricingStrategyFactory() {};
public static PricingStrategyFactory getInstance()
{
return instance;
}
public IPricingStrategy getPricingStrategy(String BookType)
{
if(BookType.equals("A"))
{
return new FlatRateStrategy(1);//教材类图书,每本1元折扣
}
else if(BookType.equals("B"))
{
return new PercentageStrategy(7);//连环画类图书,每本7%折扣
}
else if(BookType.equals("C"))
{
return new PercentageStrategy(3);//非教材类的计算机图书,每本3%折扣
}
else
{
return new NoDiscountStrategy();//其它,没有折扣
}
}
}
interface IPricingStrategy
{
public double getSubTotal(SaleLineItem sli);//得到单本图书优惠后的价格
}
class SaleLineItem
{
private int copies;
private ProductSpecification prodSpec;
private IPricingStrategy strategy;
public SaleLineItem(int copies, ProductSpecification prodSpec, IPricingStrategy strategy)
{
this.copies = copies;
this.prodSpec = prodSpec;
this.strategy = strategy;
}
public double getSubTotal()
{
return copies*(strategy.getSubTotal(this));
} //得到此种图书,优惠后的价格
public ProductSpecification getPro()
{
return prodSpec;
}
}
class FlatRateStrategy implements IPricingStrategy
{
private double discountPerBook;
public FlatRateStrategy(double a){
discountPerBook = a;
} //构造函数
public double getSubTotal(SaleLineItem sli) {
return sli.getPro().getPrice()-discountPerBook; //原先的价格-优惠的价格
}
}
class PercentageStrategy implements IPricingStrategy
{
private int discountPercentage;
public PercentageStrategy(int a)
{
discountPercentage = a;
}
public double getSubTotal(SaleLineItem sli)
{
double discount = discountPercentage/100.0;
return sli.getPro().getPrice()*(1-discount);
//原先的价格*(1-折扣力度)
}
}
class NoDiscountStrategy implements IPricingStrategy
{
public NoDiscountStrategy() {} //构造函数
public double getSubTotal(SaleLineItem sli)
{
return sli.getPro().getPrice();//直接返回价格
}
}
class Sale
{
private ArrayList<SaleLineItem> list = new ArrayList();
public Sale() {}
public void addItem(SaleLineItem it)
{
list.add(it);
}
public double getTotal()
{
double total =0;
for(Iterator<SaleLineItem> iter = list.iterator();iter.hasNext();)
{
total = total + iter.next().getSubTotal();
}
return total;
}
}