设计模式-策略模式 java实现

声明:本博客里面设计模式相关的文章,均是学习 《大话设计模式》 的笔记。

如果要做一个商场收银软件,输入商品的数量,单价,计算出收费总额,还要考虑商场的促销形式,比如打8折,满200减30等,先来看下使用简单工厂模式来实现这个需求的示例:

package strategy.pattern;
//现金收费抽象类
public abstract class CashSuper {
public abstract double acceptCash(double money);
}

//正常收费

public class CashNormal extends CashSuper {
@Override
public double acceptCash(double money) {
return money;
}
}

//打折收费
public class CashRebate extends CashSuper {
private double moneyRebate = 0.0d;
public CashRebate(double rebate){
moneyRebate = rebate;
}

@Override
public double acceptCash(double money) {
return money*moneyRebate;
}
}

//返利收费

public class CashReturn extends CashSuper {

private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;

public CashReturn(double condition,double mReturn){
moneyCondition = condition;
moneyReturn =mReturn;
}


@Override
public double acceptCash(double money) {
double result=0.0d;
if(money>moneyCondition){
result = money - Math.floor(money/moneyCondition)*moneyReturn;//Math.floor 取整数
}
return result;
}
}

//简单工厂模式,现金收费工厂
public class CashFactory {
public static CashSuper createCashAccept(int type){
CashSuper mCs =null;

switch (type){
case 1://normal
mCs = new CashNormal();
break;
case 2: //rebate
mCs = new CashRebate(0.8);
break;
case 3://return
mCs = new CashReturn(200,30);
break;
}
return mCs;
}
}

//客户端代码

import java.util.Scanner;
public class CashSystem {
double total =0.0d;
Scanner mScanner=null;
CashSuper mCashSuper= null;

public CashSystem() {
mScanner = new Scanner(System.in);
System.out.println("input rebate type :1 normal cash ,2 rebate 8 ,3 return (200-30)");
int type = mScanner.nextInt();
mCashSuper = CashFactory.createCashAccept(type);
}

void checkout(){
Scanner mScanner = new Scanner(System.in);

System.out.println("please input item price:");
double item_price = mScanner.nextDouble();

System.out.println("please input item numbers:");
double item_num = mScanner.nextDouble();

double totalPrices = item_price* item_num;
total =total+totalPrices;
double totalDis = mCashSuper.acceptCash(total);

System.out.println("item price:"+item_price+",item numbers:"+item_num+", normal totalPrices:"+total+",rebate prices:"+totalDis);
}

public static void main(String args[]){
CashSystem mCashSystem = new CashSystem();
mCashSystem.checkout();
}
}

输出截图:

简单工厂模式虽然解决了这个问题,但这个模式只是解决对象的创建问题,由于工厂本身包含了所有的收费方式,商场经常更改打折额度,返利额度,每次维护或者扩展收费方式都要改动这个工厂,会导致代码重新编译部署。面对这类算法的时常改动,应该有更好的解决模式,那就是策略模式。

策略模式(strategy),它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的替换不会影响到使用算法的客户。商场收银时如何促销,用打折还是返利,其实都是一些算法,用工厂来生成算法对象,这没有错,但算法本身只是一种策略,最重要的是这些算法是随时都可能互相替换的,这就是变化点,而封装变化点是我们面向对象的一种很重要的思维方式。策略模式结构图和基本代码:


//抽象算法类

abstract class Strategy{

//算法方法

public abstract void AlgorithmInterface();

}

//具体算法类

class ConcreteStrategyA : Strategy{

public override void AlgorithmInterface(){

//算法A的具体实现

}

}

具体算法类ConcreteStrategyB,ConcreteStrategyC略

//上下文

class Context{

Strategy mStrategy=null;

public Context(Strategy mStrategy){//传入具体的策略对象

this.mStrategy = mStrategy;

}

//上下文接口

public void ContextInterface(){//根据具体的策略对象,调用其算法的方法

mStrategy.AlgorithmInterface();

}

}

//客户端代码

static void main(Strings[] args){

Context mContext =null;

mContext = new Context(new ConcreteStrategyA());//由于实例化了不同的策略,所以最终调用mContext.ContextInterface()时,所获得的结果就不会相同

mContext.ContextInterface();

mContext = new Context(new ConcreteStrategyB());

mContext.ContextInterface();

mContext = new Context(new ConcreteStrategyC());

mContext.ContextInterface();

}

下面是依据策略模式来实现的商场收费系统的代码,原来的CashNorma,CashRebate,CashReturn,CashSuper 都不用改,只用增加一个CashContext类:

public class CashContext {
private CashSuper mCashSuper = null;
//这个构造函数的参数,可以是具体的策略类,但是要在客户端去判断具体是哪一种策略算法,这里是收费的类型,等于把原来放在客户端的判断拿到了这里。

//等于是策略与简单工厂模式的结合

public CashContext(int type){//根据构造方法传入的收费类型,生成具体的收费策略
switch (type){
case 1://normal
mCashSuper = new CashNormal();
break;
case 2: //rebate
mCashSuper = new CashRebate(0.8);
break;
case 3://return
mCashSuper = new CashReturn(200,30);
break;
}
}

public double getResult(double money){
return mCashSuper.acceptCash(money);//根据收费策略的不同获得收费结果
}
}

//重写的客户端代码

import java.util.Scanner;
public class CashClient {
double total =0.0d;
Scanner mScanner=null;
CashContext mCashContext = null;

public CashClient() {
mScanner = new Scanner(System.in);
System.out.println("input rebate type :1 normal cash ,2 rebate 8 ,3 return (200-30)");
int type = mScanner.nextInt();
mCashContext = new CashContext(type);
}

void checkout(){
Scanner mScanner = new Scanner(System.in);

System.out.println("please input item price:");
double item_price = mScanner.nextDouble();

System.out.println("please input item numbers:");
double item_num = mScanner.nextDouble();

double totalPrices = item_price* item_num;
total =total+totalPrices;
double totalDis = mCashContext.getResult(total);

System.out.println("item price:"+item_price+",item numbers:"+item_num+", normal totalPrices:"+total+",rebate prices:"+totalDis);
}

public static void main(String args[]){
CashSystem mCashSystem = new CashSystem();
mCashSystem.checkout();
}
}

比较上述2中收费系统的代码,简单工厂模式需要客户端认识两个类:CashSuper,CashFactory,而策略模式与简单工厂结合的用法,客户端只需要认识一个CashContext类就可以,耦合度降低了,而且使得具体的收费算法彻底地跟客户端分离。

策略模式是一种定义了一系列算法的方法, 从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类和使用算法类之间的耦合。

策略模式的strategy类层次为context定义了一系列的可供重用的算法或行为,继承有助于析取出这些算法中的公共功能。这里的公共功能就是获得计算收费的结果。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值