买衣服计价问题——策略模式与OCP原则
2009-08-23 16:11
246 查看
假设某服装店正在进行促销活动。
T恤打八折,毛衣打五折,而衬衫价格不变,
怎样获得要购买的衣服的实际出售价格?
第一种实现方式:
[Clothes.java] 衣服类
public abstract class Clothes {
private double price;
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
[Shirt.java] 衬衫类
public class Shirt extends Clothes {
}
[Sweater.java] 毛衣类
public class Sweater extends Clothes {
}
[TShirt.java] T恤类
public class TShirt extends Clothes {
}
[CountClothesPriceSum.java] 计算总价类
import java.util.*;
public class CountClothesPriceSum {
private List<Clothes> list = new ArrayList<Clothes>();
public void addToList(Clothes clothes){
list.add(clothes);
}
public double countPriceSum(){
double sum = 0.0;
for(int i=0; i<list.size(); i++){
if(list.get(i) instanceof TShirt){
sum += list.get(i).getPrice()*0.8;
}else{
if(list.get(i) instanceof Sweater){
sum += list.get(i).getPrice()*0.5;
}else{
sum += list.get(i).getPrice();
}
}
}
return sum;
}
}
若此时,裙子跳楼价二折,又要如何?
我们怎样使所编写的代码能够扩展?
看看下面的实现:
//忘记怎么写了 - -。。 且先放着。。
// 总之仿佛是做一个Discount的接口,
// 让Clothes去实现它
// 它有一个discount属性,
// 即使不打折扣,也可以设置其为1
也许这是一个能解决打折问题的好方法,
但是……
但是,如果再来一个促销……满100返还20呢?
我们再定义一个Onsale的接口,让Clothes去实现?
不不不,这样做的话,
促销的产品多余了打折扣的方法,
而打折扣的产品则会多余促销的方法……
那么,我们该如何实现呢?
因此,我们在这里使用策略模式:
[Clothes.java]
public abstract class Clothes {
private double price;
private Policy policy = new Policy();
public double getPrice() {
return policy.getPrice(price);
}
public void setPrice(double price) {
this.price = price;
}
public Policy getPolicy() {
return policy;
}
public void setPolicy(Policy policy) {
this.policy = policy;
}
}
[Policy.java] 计价类
public class Policy {
public double getPrice(double price){
return price;
}
}
[DiscountPolicy.java] 折扣计价类
public class DiscountPolicy extends Policy {
private double discount;
public DiscountPolicy(double discount){
this.discount = discount;
}
public void setDiscount(double discount) {
this.discount = discount;
}
public double getPrice(double price){
return price*discount;
}
}
[OnsalePolicy.java] 促销计价类
public class OnsalePolicy extends Policy {
private int basePrice;
private double returnMoney;
public OnsalePolicy(int basePrice, double returnMoney){
this.basePrice = basePrice;
this.returnMoney = returnMoney;
}
public double getPrice(double price){
if(price>=basePrice){
return price-returnMoney;
}
return price;
}
public void setBasePrice(int basePrice){
this.setBasePrice(basePrice);
}
public void setReturnMoney(int returnMoney){
this.returnMoney = returnMoney;
}
}
[TShirt.java][Shirt.java][Sweater.java][Skirt.java]等衣服的子类略。
[CountClothesPriceSum.java] 计算总价类
public class CountClothesPriceSum {
private List<Clothes> list = new ArrayList<Clothes>();
public void addToList(Clothes clothes){
list.add(clothes);
}
public double countPriceSum(){
double sum = 0.0;
for(int i=0; i<list.size(); i++){
sum += list.get(i).getPrice();
}
return sum;
}
}
这样,如果还有新的计价策略,
我们只需要写一个类来继承Policy,重写它的getPrice(double)方法即可。
这便做到了“对扩展开放,对修改关闭。”
最后附上改进用的UT:
public class TestCases extends TestCase {
public void testCase1(){
CountClothesPriceSum count = new CountClothesPriceSum();
Shirt shirt = new Shirt();
shirt.setPrice(32);
count.addToList(shirt);
assertEquals(count.countPriceSum(), 32.0);
TShirt tShirt = new TShirt();
tShirt.setPrice(20);
tShirt.setPolicy(new DiscountPolicy(0.8));
count.addToList(tShirt);
assertEquals(count.countPriceSum(), 48.0);
DiscountPolicy discountPolicy = new DiscountPolicy(0.5);
tShirt.setPolicy(discountPolicy);
assertEquals(count.countPriceSum(), 42.0);
Sweater sweater = new Sweater();
sweater.setPrice(50);
sweater.setPolicy(discountPolicy);
count.addToList(sweater);
assertEquals(count.countPriceSum(), 67.0);
}
// For OnsalePolicy
public void testCase2(){
CountClothesPriceSum count = new CountClothesPriceSum();
Shirt shirt = new Shirt();
shirt.setPolicy(new OnsalePolicy(100,20));
shirt.setPrice(80);
count.addToList(shirt);
assertEquals(count.countPriceSum(), 80.0);
shirt.setPrice(100);
assertEquals(count.countPriceSum(), 80.0);
shirt.setPrice(120);
assertEquals(count.countPriceSum(), 100.0);
OnsalePolicy onsalePolicy = new OnsalePolicy(50,5);
Sweater sweater = new Sweater();
sweater.setPrice(75);
sweater.setPolicy(onsalePolicy);
count.addToList(sweater);
assertEquals(count.countPriceSum(), 170.0);
sweater.setPrice(20);
assertEquals(count.countPriceSum(), 120.0);
}
// For Skirt
public void testCase3(){
CountClothesPriceSum count = new CountClothesPriceSum();
Skirt skirt = new Skirt();
skirt.setPrice(50);
count.addToList(skirt);
assertEquals(count.countPriceSum(), 50.0);
skirt.setPolicy(new DiscountPolicy(0.3));
assertEquals(count.countPriceSum(), 15.0);
skirt.setPolicy(new OnsalePolicy(30,5));
assertEquals(count.countPriceSum(), 45.0);
}
}
策略模式(Strategy)
T恤打八折,毛衣打五折,而衬衫价格不变,
怎样获得要购买的衣服的实际出售价格?
第一种实现方式:
[Clothes.java] 衣服类
public abstract class Clothes {
private double price;
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
[Shirt.java] 衬衫类
public class Shirt extends Clothes {
}
[Sweater.java] 毛衣类
public class Sweater extends Clothes {
}
[TShirt.java] T恤类
public class TShirt extends Clothes {
}
[CountClothesPriceSum.java] 计算总价类
import java.util.*;
public class CountClothesPriceSum {
private List<Clothes> list = new ArrayList<Clothes>();
public void addToList(Clothes clothes){
list.add(clothes);
}
public double countPriceSum(){
double sum = 0.0;
for(int i=0; i<list.size(); i++){
if(list.get(i) instanceof TShirt){
sum += list.get(i).getPrice()*0.8;
}else{
if(list.get(i) instanceof Sweater){
sum += list.get(i).getPrice()*0.5;
}else{
sum += list.get(i).getPrice();
}
}
}
return sum;
}
}
若此时,裙子跳楼价二折,又要如何?
我们怎样使所编写的代码能够扩展?
看看下面的实现:
//忘记怎么写了 - -。。 且先放着。。
// 总之仿佛是做一个Discount的接口,
// 让Clothes去实现它
// 它有一个discount属性,
// 即使不打折扣,也可以设置其为1
也许这是一个能解决打折问题的好方法,
但是……
但是,如果再来一个促销……满100返还20呢?
我们再定义一个Onsale的接口,让Clothes去实现?
不不不,这样做的话,
促销的产品多余了打折扣的方法,
而打折扣的产品则会多余促销的方法……
那么,我们该如何实现呢?
因此,我们在这里使用策略模式:
[Clothes.java]
public abstract class Clothes {
private double price;
private Policy policy = new Policy();
public double getPrice() {
return policy.getPrice(price);
}
public void setPrice(double price) {
this.price = price;
}
public Policy getPolicy() {
return policy;
}
public void setPolicy(Policy policy) {
this.policy = policy;
}
}
[Policy.java] 计价类
public class Policy {
public double getPrice(double price){
return price;
}
}
[DiscountPolicy.java] 折扣计价类
public class DiscountPolicy extends Policy {
private double discount;
public DiscountPolicy(double discount){
this.discount = discount;
}
public void setDiscount(double discount) {
this.discount = discount;
}
public double getPrice(double price){
return price*discount;
}
}
[OnsalePolicy.java] 促销计价类
public class OnsalePolicy extends Policy {
private int basePrice;
private double returnMoney;
public OnsalePolicy(int basePrice, double returnMoney){
this.basePrice = basePrice;
this.returnMoney = returnMoney;
}
public double getPrice(double price){
if(price>=basePrice){
return price-returnMoney;
}
return price;
}
public void setBasePrice(int basePrice){
this.setBasePrice(basePrice);
}
public void setReturnMoney(int returnMoney){
this.returnMoney = returnMoney;
}
}
[TShirt.java][Shirt.java][Sweater.java][Skirt.java]等衣服的子类略。
[CountClothesPriceSum.java] 计算总价类
public class CountClothesPriceSum {
private List<Clothes> list = new ArrayList<Clothes>();
public void addToList(Clothes clothes){
list.add(clothes);
}
public double countPriceSum(){
double sum = 0.0;
for(int i=0; i<list.size(); i++){
sum += list.get(i).getPrice();
}
return sum;
}
}
这样,如果还有新的计价策略,
我们只需要写一个类来继承Policy,重写它的getPrice(double)方法即可。
这便做到了“对扩展开放,对修改关闭。”
最后附上改进用的UT:
public class TestCases extends TestCase {
public void testCase1(){
CountClothesPriceSum count = new CountClothesPriceSum();
Shirt shirt = new Shirt();
shirt.setPrice(32);
count.addToList(shirt);
assertEquals(count.countPriceSum(), 32.0);
TShirt tShirt = new TShirt();
tShirt.setPrice(20);
tShirt.setPolicy(new DiscountPolicy(0.8));
count.addToList(tShirt);
assertEquals(count.countPriceSum(), 48.0);
DiscountPolicy discountPolicy = new DiscountPolicy(0.5);
tShirt.setPolicy(discountPolicy);
assertEquals(count.countPriceSum(), 42.0);
Sweater sweater = new Sweater();
sweater.setPrice(50);
sweater.setPolicy(discountPolicy);
count.addToList(sweater);
assertEquals(count.countPriceSum(), 67.0);
}
// For OnsalePolicy
public void testCase2(){
CountClothesPriceSum count = new CountClothesPriceSum();
Shirt shirt = new Shirt();
shirt.setPolicy(new OnsalePolicy(100,20));
shirt.setPrice(80);
count.addToList(shirt);
assertEquals(count.countPriceSum(), 80.0);
shirt.setPrice(100);
assertEquals(count.countPriceSum(), 80.0);
shirt.setPrice(120);
assertEquals(count.countPriceSum(), 100.0);
OnsalePolicy onsalePolicy = new OnsalePolicy(50,5);
Sweater sweater = new Sweater();
sweater.setPrice(75);
sweater.setPolicy(onsalePolicy);
count.addToList(sweater);
assertEquals(count.countPriceSum(), 170.0);
sweater.setPrice(20);
assertEquals(count.countPriceSum(), 120.0);
}
// For Skirt
public void testCase3(){
CountClothesPriceSum count = new CountClothesPriceSum();
Skirt skirt = new Skirt();
skirt.setPrice(50);
count.addToList(skirt);
assertEquals(count.countPriceSum(), 50.0);
skirt.setPolicy(new DiscountPolicy(0.3));
assertEquals(count.countPriceSum(), 15.0);
skirt.setPolicy(new OnsalePolicy(30,5));
assertEquals(count.countPriceSum(), 45.0);
}
}
策略模式(Strategy)
相关文章推荐
- 设计模式之六大原则——开闭原则(OCP)
- 设计模式6大原则:开闭原则(OCP)
- 设计模式六大原则——开闭原则(OCP,Open Close Principle)
- 设计模式六大原则——开放封闭原则(OCP)
- 组合还是继承,这是一个问题?——由模式谈面向对象的原则之多用组合、少用继承
- 设计模式和原则:策略模式
- 从头认识设计模式-策略模式-04-引入设计原则:分离变化与不变的部分
- 《设计模式解析》 第14章 设计模式的原则与策略 复习题
- 开发模式学习笔记之——OCP 开放-封闭原则
- Java使用策略模式解决商场促销商品问题示例
- <总结> 设计模式之 开放封闭原则OCP C++示例
- 项目问题思考之策略模式
- 重构桌面飘着圣诞老人,利用策略模式和改造的代理模式让软件完全实现开闭原则,欢迎下载源代码分析
- 设计模式中的设计原则之开放封闭原则(Open Closed Principle - OCP)
- 组合还是继承,这是一个问题?——由模式谈面向对象的原则之多用组合、少用继承
- 设计模式之六大原则——开闭原则(OCP)
- IOS设计模式的六大设计原则之开放-关闭原则(OCP,Open-Close Principle)
- Http解析 OCP原则 设计模式
- 使用策略设计模式,反射,解决商城系统中的商品折扣问题
- 项目问题的思考之策略模式