Java设计模式——策略模式

      我们写代码的时候,有时会写很多if...else if....else...的条件语句,或者switch...case...case... 。。。  这会使我们的代码非常臃肿,策略模式的目的就是避免了各种条件判断的臃肿代码,使代码更加可读,而且方便后期维护。

一、定义

策略模式定义了一系列算法或逻辑,并将每一个算法或逻辑封装起来,而且使它们可以相互替换,策略模式让算法或逻辑独立于使用者。使用者只需设置相应的策略去实现相应目的,而无需知道策略中的具体实现方法。

UML:

Context:用来操作策略的上下文环境

Stragety:策略的抽象定义

ConcreteStrageryA/B:具体的策略实现

二、使用场景

1、针对同一类型问题的多重处理方式,仅仅是具体行为有偏差。

2、需要安全的封装同一种类型操作。

3、出现同一抽象类有多个子类,而又需要使用if...else...或者switch..case...来选择具体子类。

同一问题有多种解决方案

三、简单实现

public class MainActivity extends AppCompatActivity {

    public static final String TAG = "MainActivity";
    public static final int AM = 0x010;//上午
    public static final int PM = 0x011;//下午

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        test("星期二", PM);
    }

    private void test(String day, int time) {
        String doSomething = "";
        switch (day) {
            case "星期一":
                if (time == AM)
                    doSomething = "敲代码";
                else if (time == PM)
                    doSomething = "开会";
                break;
            case "星期二":
                if (time == AM)
                    doSomething = "架构";
                else if (time == PM)
                    doSomething = "测试";
                break;
            case "星期三":
                if (time == AM)
                    doSomething = "写文档";
                else if (time == PM)
                    doSomething = "偷懒";
                break;
            default:
                doSomething = "闲待着";
                break;
        }
        Log.d(TAG, "今天我要做的事情是" + doSomething);
    }
}


我们可以看到,一直不停的case确实可以满足我们的需求,但是后期维护相当麻烦,比如添加周六,或者周日,要一直不停的case...很不好写,而且代码臃肿不堪,我们要降低代码的耦合性,什么是耦合性?耦合性是各模块间相互联系程度的一种度量,也就是说,我们要尽可能的独立每一个类,使其可以单独调用,而尽可能少的依赖其他类,下面介绍一下策略模式,大大降低耦合性,先写一个接口Day:

public interface Day {
    String doSomething(int time);
}


以星期一和星期二为例:

public class Monday implements Day {
    @Override
    public String doSomething(int time) {
        if (time == MainActivity.AM)
            return "敲代码";
        else
            return "开会";
    }
}


public class Tuesday implements Day {
    @Override
    public String doSomething(int time) {
        if (time == MainActivity.AM)
            return "架构";
        else
            return "测试";
    }
}


我们用的时候 只需这样:

 Day day = new Tuesday();
        String doSomething = day.doSomething(PM);
        Log.d(TAG, "今天我要做的事情是" + doSomething);


如果要添加新的种类 比如周日,不用再去写case...if else...只需要写一个Sunday然后实现Day接口就可以了!

public class Sunday implements Day {
    @Override
    public String doSomething(int time) {
        if (time == MainActivity.AM)
            return "吃饭、睡觉";
        else
            return "打豆豆";
    }
}

四、例子

写一个简单算法计算出行的价格

普通实现:

    public class PriceCalculator {

        private static final int BUS = 0x010;
        private static final int SUBWAY = 0x011;

        public static void main(String[] args) {
            PriceCalculator calculator = new PriceCalculator();
            System.out.print("坐16公里公交的价格为:" + calculator.make(16, BUS));
            System.out.print("坐16公里地铁的价格为:" + calculator.make(16, SUBWAY));
        }

        private int make(int km, int type) {
            if (type == BUS) {
                return bugMake(km);
            } else if (type == SUBWAY) {
                return subwayMake(km);
            } else {
                return 0;
            }
        }

        private int bugMake(int km) {
            if (km > 10) {
                return 3;
            } else {
                return 2;
            }

        }

        private int subwayMake(int km) {
            if (km < 6) {
                return 3;
            } else if (km > 6 && km < 12) {
                return 4;
            } else if (km > 12 && km < 22) {
                return 5;
            } else if (km > 22 && km < 32) {
                return 6;
            } else {
                return 7;
            }
        }
    }

上面的代码虽然计算上是没有问题,但是很明显违背了单一职责原则,而且当我们增加一种新的出行方式比如TAXI,我们就需要在PriceCalculator中增加一个计算方法,最后使得该类中的代码越来越臃肿,耦合性越来越大。

使用策略模式实现,使得每一种出行方式都有一个独立的类去计算:

public interface PriceCalculator {
        int make(int km);
}

 

public class BusPrice implements PriceCalculator {
    @Override
    public int make(int km) {
        if (km > 10) {
            return 3;
        } else {
            return 2;
        }
    }
}

 

public class SubwayPrice implements PriceCalculator {
    @Override
    public int make(int km) {
        if (km < 6) {
            return 3;
        } else if (km > 6 && km < 12) {
            return 4;
        } else if (km > 12 && km < 22) {
            return 5;
        } else if (km > 22 && km < 32) {
            return 6;
        } else {
            return 7;
        }
    }
}

 

    public class TaxiPrice implements PriceCalculator {
        @Override
        public int make(int km) {
            if (km < 6) {
                return 13;
            } else {
                int extarKm = km - 6;
                int extarMoney = extarKm * 3;
                return 13 + extarMoney;
            }
        }
    }

在使用的时候,我们只需要这样做:

    public class TrafficPriceCalculator {

        private PriceCalculator calculator;

        public static void main(String[] args) {
            TrafficPriceCalculator calculator = new TrafficPriceCalculator();
            calculator.setCalculator(new BusPrice());
            System.out.print("坐16公里公交的价格为:" + calculator.make(16));
            calculator.setCalculator(new SubwayPrice());
            System.out.print("坐16公里地铁的价格为:" + calculator.make(16));
            calculator.setCalculator(new TaxiPrice());
            System.out.print("坐16公里出租车的价格为:" + calculator.make(16));
        }

        public void setCalculator(PriceCalculator calculator) {
            this.calculator = calculator;
        }

        public int make(int km) {
            return calculator.make(km);
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值