简述-策略模式

事例

一个每天打饭的时候,都会打一个荤菜和一个素菜和一人饭。饭固定,一个人一块,素菜也是固定的,只要1.6元而荤菜则根据不同菜品和不同重量来计算。鸭肉需要1.5块一两,鸡肉需要2块一两,猪肉1.8块一两。换算到java中,我们要计算中午饭多少钱,可以用如下方式。

public class PriceClient{
    
    private static int pork=1;
    private static int chicken=2;
    private static int dock=3;

    public static void main(String[] args){
        PriceClient priceClient=new PriceClient();
        
        System.out.println("今天吃米饭+素菜+3两猪肉,价格是:"+priceClient.calcuatePrice(pork,3));
    }
    
    /**
    * 计算价格
    * @param liang 两数
    */
    float calcuatePrice(int type , int liang){
        float price=1+1.6;//先计算出米饭和素菜的价格
        if(pork==type){
            return price+porkPrice(liang);
        }else if(chicken==type){
            return price+chickenPrice(liang);
        }else{
            return price+dockPrice(liang);
        }
    }
    
    /**
    * 猪肉1.8一两
    * @param liang 两数
    */
    private float porkPrice(int liang){
        return 1.8*liang;
    }
    
    /**
    * 鸡肉2一两
    * @param liang 两数
    */
    private float chickenPrice(int liang){
        return 2*liang;
    }
    
    /**
    * 鸭肉1.5一两
    * @param liang 两数
    */
    private float dockPrice(int liang){
        return 1.5*liang;
    }
}

现在这代码看起来还是挺简单的吧,而且还是对每个肉类的价格是分开在不同方法内计算的了,看起来简单吗?但是如果肉类品种越来越多,那又得不断在后面加if-else来判断返回具体执行方法。然后这个类中的代码越来越臃肿,难以维护。另外增加的时候,可能很多时候是通过复制粘贴的方式,手动复制很容易引入错误。
就这里就违反了我们说的,开关闭原则,每次要增加都在这个类中修改。也违反了单一原则,一个类包含了多个计算方式。

在这里我们可以利用抽象来解决这个问题。

抽象实现

  • UML图

image

  • 创建一个接口,来定义价格计算方法:

/**
 * 价格策略计算接口
 */
public interface StragetyPrice {


    /**
     * 
     */
    public void calcuatePrice();

}
  • 实际计算类

/**
 * 猪肉计算
 */
public class ConcerateStragetyPork implements Stragety {

    /**
     * Default constructor
     */
    public ConcerateStragetyPork() {
    }

    /**
     * 计算价格
     */
    public float calcuatePrice(int liang) {
        return 1.8*liang;
    }

}

/**
 * 鸡肉计算
 */
public class ConcerateStragetyChicken implements Stragety {

    /**
     * Default constructor
     */
    public ConcerateStragetyChicken() {
    }

    /**
     * 计算价格
     */
    public float calcuatePrice(int liang) {
        return 2*liang;
    }

}

/**
 * 鸭肉计算
 */
public class ConcerateStragetyDock implements Stragety {

    /**
     * Default constructor
     */
    public ConcerateStragetyDock() {
    }

    /**
     * 计算价格
     */
    public float calcuatePrice(int liang) {
        return 1.5*liang;
    }

}

  • Client修改:
public class PriceClient{
    private Stragety stragety;

    public static void main(String[] args){
        PriceClient priceClient=new PriceClient();
        priceClient.setStragety(new ConcerateStragetyDock());//设置猪肉
        System.out.println("今天吃米饭+素菜+3两猪肉,价格是:"+priceClient.calcuatePrice(3));
    }
    
    public void setStragety(Stragety stragety){
        this.stragety=stragety;
    }
    
    /**
    * 计算价格
    * @param liang 两数
    */
    float calcuatePrice(int liang){
        float price=1+1.6;//先计算出米饭和素菜的价格
        return price+stragety.calcuatePrice(liang);
    }
}
    

这个样子来实现可变的部分,然后达到可扩展的效果,如果后面还有另外的荤菜,只需要加入一个实现Stragety接口就可以了。对之前的代码修改关闭,也体现了调用client的单一职责,它只需要调用和设置,真正的可变计算在各自实现类中。

总结

基本的简单实现到这里就结束了。策略模式也是一个使用很多的设计模式,优点在于替换if-else结构,在一个整体流程中,如果因为其中某一部分可变造成结果可变的不妨就使用策略模式。如果是全部都可变可替换,你还是可以考虑工厂模式,所以说所有设计模式都大同小异呢,但是使用场景和站的角度不同你就可以看成是不同的设计模式。最终结果是为了更优雅的实现方式即六大原则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值