工厂模式很简单,也很好上手,那么接下来学习策略模式,我们就以商场的收银系统作为需求,使用策略模式完成。达到学习了解策略模式的目的。
策略模式(strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
先看看策略模式的结构图:
通过Context的实例去调用不同具体实例的方法。那么根据策略模式的结构图,商场收银系统的UML
商场的收银算法多种多样,并且可能随时更改,那么在设计该系统时,模式选择上就应该注重系统的可扩展性,可维护性。那么我们就以商场有现金全额收费算法,打折算法,满返现算法。当然上诉分层结构时,在具体策略层可以加个工厂,这样可以提高代码的可复用性。
先从上到下,抽象算法
/**
*抽象策略,一个算法
*@author Shuwen
*created at 2016/8/25 15:54
*/
public abstract class CashSuper {
public abstract double CashMoney(double money);
public abstract String getType();
}
接着是具体策略
/**
* Created by Shuwen on 2016/8/25.
*/
public class CashDebate extends CashSuper {
private double debate = 1;
public CashDebate(double debate){
this.debate = debate;
}
@Override
public double CashMoney(double money) {
return money*debate;
}
@Override
public String getType() {
return "打"+debate+"折";
}
}
接着就是业务逻辑,整个银行系统,把它抽出来设计为一个自定义的View,这样可以增强代码的复用性,在其他地方要用,直接就可以用这个控件,而不用再去重复写业务逻辑。
package com.abings.strategymodel;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.abings.strategymodel.Strategy.CashContext;
import com.abings.strategymodel.StrategyFactory.CashFactory;
/**
* Created by Shuwen on 2016/8/25.
*/
public class BankSysView extends LinearLayout {
private EditText singlemoney;
private EditText number;
private Button sure;
private Button reset;
private TextView history;
private TextView total;
private StringBuilder stringBuilder;
private Context context;
private Spinner spinner;
private ArrayAdapter<String> adapter;
private CashContext cashContext;
private double totalMoney;
private double allMoney;
private String[]types = {"全额付款","打8折","打5折","满300返50"};
public BankSysView(Context context) {
this(context,null);
}
public BankSysView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BankSysView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context =context;
LayoutInflater.from(context).inflate(R.layout.cashmoneysys, this);
initView();
setEvents();
}
private void setEvents() {
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
cashContext = CashFactory.createCashSuper(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
sure.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
double singleMoney = Double.parseDouble(singlemoney.getText().toString().trim());
double numBer = Double.parseDouble(number.getText().toString().trim());
totalMoney = cashContext.getResult(singleMoney * numBer);
allMoney += totalMoney;
stringBuilder.append("单价:"+singleMoney+"元,"+"数量:"+(int)numBer+","+cashContext.getType()+",合计:"+totalMoney+"元\n");
total.setText("总计:" + allMoney + "元");
history.setText(stringBuilder);
}
});
reset.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
singlemoney.setText("");
number.setText("");
allMoney = 0;
stringBuilder.delete(0, stringBuilder.length());
history.setText("");
total.setText("总计:");
}
});
}
private void initView() {
singlemoney = (EditText) findViewById(R.id.singlemoney);
number = (EditText) findViewById(R.id.num);
sure = (Button) findViewById(R.id.sure);
reset = (Button) findViewById(R.id.reset);
history = (TextView) findViewById(R.id.history);
total = (TextView) findViewById(R.id.total);
spinner = (Spinner) findViewById(R.id.spinner);
adapter = new ArrayAdapter<>(context,R.layout.text,types);
stringBuilder = new StringBuilder();
}
}
最后根据需求,写个工厂类
package com.abings.strategymodel.StrategyFactory;
import com.abings.strategymodel.Strategy.CashContext;
import com.abings.strategymodel.Strategy.CashDebate;
import com.abings.strategymodel.Strategy.CashNormal;
import com.abings.strategymodel.Strategy.CashReturn;
/**
* Created by Shuwen on 2016/8/26.
*/
public class CashFactory {
public static CashContext createCashSuper(int position){
CashContext cashContext = null;
switch (position) {
case 0:
cashContext = new CashContext(new CashNormal());
break;
case 1:
cashContext = new CashContext(new CashDebate(0.8));
break;
case 2:
cashContext = new CashContext(new CashDebate(0.5));
break;
case 3:
cashContext = new CashContext(new CashReturn(300, 50));
break;
}
return cashContext;
}
}
这就是策略模式,一个抽象策略,多个具体策略,一个Context统一算法的调用,那么以后再添加算法,或是修改算法,只需要在具体算法层做改动,客户端和抽象策略不需要修改,这样代码的可维护性,可扩张性也提高了不少。很不错的设计模式。
附上git源码:
https://github.com/SingleShu/StrategyModel
(若跳转失败,在新开个页面,复制上面链接)