设计模式学习之路-策略模式

工厂模式很简单,也很好上手,那么接下来学习策略模式,我们就以商场的收银系统作为需求,使用策略模式完成。达到学习了解策略模式的目的。

策略模式(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

(若跳转失败,在新开个页面,复制上面链接)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值