前言:

  先不管方式, 把她和她的名字都忘了, 来看看难点 和 设计思路.
为什么要这样做. 

前言:

  先不管情势, 把她和她的名字都忘了, 来看望难题 和 设计思路.
为什么要如此做. 

场景:

  有一家商家, 里面有3个伙计, 售货员当然是要卖东西的哇,
客户进来买完东西, 找售货员结账, 那售货员得掌握一共多少钱吗?

一. 起始设计

  商品类:

package org.elvin.strategy;

/***/
public class Goods {
    /**
     * 商品名
     */
    private String name;

    /**
     * 商品价格
     */
    private Long Price;

    public Goods() { }

    public Goods(String name, Long price) {
        this.name = name;
        Price = price;
    }

    //region getter / setter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getPrice() {
        return Price;
    }

    public void setPrice(Long price) {
        Price = price;
    }
    //endregion
}

 

鉴于价位小编动用的是 Long 类型, 所以, 要有贰个转换输出的方法.

package org.elvin.strategy;

import java.text.MessageFormat;

public class MoneyUtils {
    public static String getYuan(Long money){
        Long yuan = money / 100;
        Long jiao = money % 100 /  10;
        Long fen = money % 10;

        return MessageFormat.format("{0}.{1}{2}", yuan, jiao , fen );
    }
}

售货员:

package org.elvin.strategy;

import org.elvin.strategy.calculator.*;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * 环境角色(Context)*/
public class Seller {

    /**
     * 姓名
     */
    private String name;

    /**
     * 编号
     */
    private String code;

    //region getter / setter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
    //endregion

    /**
     * 售卖商品
     */
    public void sellGoods(List<Goods> goods){
        Long sum = 0L;
        for (Goods good : goods) {
            sum += good.getPrice();
        }
        System.out.println("应付款: " + MoneyUtils.getYuan(sum) + " 元");
    }

    @Test
    public void func1(){
        List<Goods> goods = new ArrayList<>();
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("饼干", 250L));
        goods.add(new Goods("辣条", 300L));

        sellGoods(goods);
    }
}

来看一下计量结果:

图片 1

收获结果了, 没啥毛病, 挺好. 

明天首席营业官娘过生日, 突然想到, 要不要再店里搞个移动, 来个打折活动,
有些商品减价销售. 

次日业主过生日, 老董娘说, 老娘心花怒放, 你降价销售, 前几日自小编来个免单销售.

那未来如何是好呢? 今日过后, 价格势必又要东山再起到健康价格.  what the fuck! 

Seller类写死了, 难道作者在中间加几个总结格局? 

加进去貌似能够缓解当下题材, 可是, 后天借使业主的二叔过生日吗? 咋搞?

 

Ok, 到那里, 大致, 必要请出前几日的大神 : 策略方式.
让她来帮大家消除这些题材吧.

 

二. 设计改造

对于售货员来说, 她非得领会, 前天该怎么总计价格, 是减价照旧不减价,
或许是满多少钱, 送东西怎么的. 

那么, 将那些减价恐怕说价格的计量方法抽象出来, 成为3个接口恐怕抽象类. 

让减价大概不优惠达成或然延续他.

兑现格局:

此间, 笔者将她抽象为3个接口

package org.elvin.strategy.calculator;

import org.elvin.strategy.Goods;

import java.util.List;

/**
 * 抽象策略角色(Strategy)
 * 优惠接口
*/
public interface PreferentialPrice {
    public void getPrice(List<Goods> goods);
}

PreferentialPrice 需要作为一个属性,出现在 Seller 类中.

在Seller中加入

    /**
     * 计算优惠后的价格
     * 抽象角色, 次角色给出所有具体策略类所需的接口
     */
    private PreferentialPrice preferentialPrice;

    public PreferentialPrice getPreferentialPrice() {
        return preferentialPrice;
    }

    public void setPreferentialPrice(PreferentialPrice preferentialPrice) {
        this.preferentialPrice = preferentialPrice;
    }

 

那边提供三种计算形式:

  1. 好端端艺术

    /**

    • 切切实实策略剧中人物(ConcreteStrategy)
      */
      public class NoPreferential implements PreferentialPrice {

      @Override
      public void getPrice(List goods) {

       Long sum = 0L;
       for (Goods good : goods) {
           sum += good.getPrice();
       }
       System.out.println("应付款: " + MoneyUtils.getYuan(sum) + " 元");
      

      }
      }

  2. 免单格局

    /**

    • 具体策略剧中人物(ConcreteStrategy)
      */
      public class Free implements PreferentialPrice {
      @Override
      public void getPrice(List goods) {

       System.out.println("免单, 不要钱 !");
      

      }
      }

  3. 有的打折格局

    /**

    • 切实策略剧中人物(ConcreteStrategy)
      */
      public class ReduceSomeGoods implements PreferentialPrice {

      @Override
      public void getPrice(List goods) {

       Long sum = 0L;
       for (Goods good : goods) {
           switch (good.getName()) {
               case "泡面":
                   sum += good.getPrice() - 50L;
                   break;
      
               case "火腿":
                   sum += good.getPrice() - 20L;
                   break;
      
               case "鸡蛋":
                   sum += good.getPrice() - 10L;
                   break;
      
               default:
                   sum += good.getPrice();
                   break;
           }
       }
       System.out.println("应付款: " + MoneyUtils.getYuan(sum) + " 元");
      

      }
      }

  

 将Seller类中, 总结的办法修改一下:

    public void sellGoods(List<Goods> goods){
        if(preferentialPrice == null){
            setPreferentialPrice(new NoPreferential());
        }
        preferentialPrice.getPrice(goods);
    }

在总括的时候, 若是没有传来打折, 则默许使用无促销措施

再看测试方法:

    @Test
    public void func1(){
        List<Goods> goods = new ArrayList<>();
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("饼干", 250L));
        goods.add(new Goods("辣条", 300L));

        setPreferentialPrice(new Free());
        sellGoods(goods);
        System.out.println("-----------------------");
        setPreferentialPrice(new ReduceSomeGoods());
        sellGoods(goods);
        System.out.println("-----------------------");
        setPreferentialPrice(new NoPreferential());
        sellGoods(goods);
    }

结果:

  图片 2

政策方式作为一种对象行为格局, 在此处应该依旧呈现到了吧.

那总计一下?给个不简单精晓(网上抄的):

  策略方式属于对象的表现格局。其意图是本着一组算法,将每贰个算法封装到持有共同接口的独门的类中,从而使得它们可以互相替换。策略方式使得算法能够在不影响到客户端的情状下发生变化。

说的可比抽象, 来个有血有肉的呢:

  一帅哥喜欢约妹子, 那咋约出来吧? 不是兼备的胞妹都爱不释手进食看摄像吧.
那针对差其他阿妹, 使用分歧的法子来约. 约喜欢看录制的三妹看摄像,
约喜欢吃小吃的妹子吃小吃.

那吃饭, 看摄像, 吹海风…… 等等, 这几个招数,
指标都以为着让小姨子做他女对象(那里不探讨时间). 指标不变, 手段熟视无睹.
那几个办法, 就足以驾驭为区其余 strategy. 

 

因而地点的例子, 能够见见, 具体的算法与算法之间向来不借助关系,
都是如出一辙的(平等性), 能够相互替换的. 那在运行的时候,
每一趟都不得不使用一种(唯一性). 

场景:

  有一家商厦, 里面有一个营业员, 售货员当然是要卖东西的啊,
客户进来买完东西, 找售货员结账, 那售货员得领悟一共多少钱吧?

一. 先河设计

  商品类:

package org.elvin.strategy;

/***/
public class Goods {
    /**
     * 商品名
     */
    private String name;

    /**
     * 商品价格
     */
    private Long Price;

    public Goods() { }

    public Goods(String name, Long price) {
        this.name = name;
        Price = price;
    }

    //region getter / setter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getPrice() {
        return Price;
    }

    public void setPrice(Long price) {
        Price = price;
    }
    //endregion
}

 

是因为价位笔者动用的是 Long 类型, 所以, 要有多个更换输出的方法.

package org.elvin.strategy;

import java.text.MessageFormat;

public class MoneyUtils {
    public static String getYuan(Long money){
        Long yuan = money / 100;
        Long jiao = money % 100 /  10;
        Long fen = money % 10;

        return MessageFormat.format("{0}.{1}{2}", yuan, jiao , fen );
    }
}

售货员:

package org.elvin.strategy;

import org.elvin.strategy.calculator.*;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * 环境角色(Context)*/
public class Seller {

    /**
     * 姓名
     */
    private String name;

    /**
     * 编号
     */
    private String code;

    //region getter / setter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
    //endregion

    /**
     * 售卖商品
     */
    public void sellGoods(List<Goods> goods){
        Long sum = 0L;
        for (Goods good : goods) {
            sum += good.getPrice();
        }
        System.out.println("应付款: " + MoneyUtils.getYuan(sum) + " 元");
    }

    @Test
    public void func1(){
        List<Goods> goods = new ArrayList<>();
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("饼干", 250L));
        goods.add(new Goods("辣条", 300L));

        sellGoods(goods);
    }
}

来看一下盘算结果:

图片 3

获取结果了, 没啥毛病, 挺好. 

明日业主过生日, 突然想到, 要不要再店里搞个移动, 来个减价活动,
某些商品优惠销售. 

明天业主过生日, CEO娘说, 老娘喜形于色, 你减价销售, 后天自我来个免单销售.

这今后咋做呢? 明天过后, 价格一定又要回涨到正规价格.  what the fuck! 

Seller类写死了, 难道作者在内部加多少个计算方式? 

加进去貌似能够消除当下题材, 但是, 后天假若业主的娘亲人过生日吗? 咋搞?

 

Ok, 到此地, 大概, 必要请出明天的大神 : 策略情势.
让他来帮我们化解那个难题吧.

 

二. 设计改造

对此售货员来说, 她非得领悟, 明日该怎么总计价格, 是优化依旧不减价,
只怕是满多少钱, 送东西怎么的. 

那便是说, 将那几个降价或许说价格的计算方式抽象出来, 成为2个接口或然抽象类. 

让减价恐怕不减价完结大概接二连三他.

落到实处格局:

那里, 笔者将她抽象为1个接口

package org.elvin.strategy.calculator;

import org.elvin.strategy.Goods;

import java.util.List;

/**
 * 抽象策略角色(Strategy)
 * 优惠接口
*/
public interface PreferentialPrice {
    public void getPrice(List<Goods> goods);
}

PreferentialPrice 需要作为一个属性,出现在 Seller 类中.

在Seller中加入

    /**
     * 计算优惠后的价格
     * 抽象角色, 次角色给出所有具体策略类所需的接口
     */
    private PreferentialPrice preferentialPrice;

    public PreferentialPrice getPreferentialPrice() {
        return preferentialPrice;
    }

    public void setPreferentialPrice(PreferentialPrice preferentialPrice) {
        this.preferentialPrice = preferentialPrice;
    }

 

此地提供三种总计办法:

  1. 正规艺术

    /**

    • 现实政策角色(ConcreteStrategy)
      */
      public class NoPreferential implements PreferentialPrice {

      @Override
      public void getPrice(List goods) {

       Long sum = 0L;
       for (Goods good : goods) {
           sum += good.getPrice();
       }
       System.out.println("应付款: " + MoneyUtils.getYuan(sum) + " 元");
      

      }
      }

  2. 免单格局

    /**

    • 切切实实策略角色(ConcreteStrategy)
      */
      public class Free implements PreferentialPrice {
      @Override
      public void getPrice(List goods) {

       System.out.println("免单, 不要钱 !");
      

      }
      }

  3. 一对减价措施

    /**

    • 具体策略剧中人物(ConcreteStrategy)
      */
      public class ReduceSomeGoods implements PreferentialPrice {

      @Override
      public void getPrice(List goods) {

       Long sum = 0L;
       for (Goods good : goods) {
           switch (good.getName()) {
               case "泡面":
                   sum += good.getPrice() - 50L;
                   break;
      
               case "火腿":
                   sum += good.getPrice() - 20L;
                   break;
      
               case "鸡蛋":
                   sum += good.getPrice() - 10L;
                   break;
      
               default:
                   sum += good.getPrice();
                   break;
           }
       }
       System.out.println("应付款: " + MoneyUtils.getYuan(sum) + " 元");
      

      }
      }

  

 将Seller类中, 总计的章程修改一下:

    public void sellGoods(List<Goods> goods){
        if(preferentialPrice == null){
            setPreferentialPrice(new NoPreferential());
        }
        preferentialPrice.getPrice(goods);
    }

在测算的时候, 如若没有传来减价, 则暗许使用无促销措施

再看测试方法:

    @Test
    public void func1(){
        List<Goods> goods = new ArrayList<>();
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("泡面", 550L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("火腿", 150L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("鸡蛋", 70L));
        goods.add(new Goods("饼干", 250L));
        goods.add(new Goods("辣条", 300L));

        setPreferentialPrice(new Free());
        sellGoods(goods);
        System.out.println("-----------------------");
        setPreferentialPrice(new ReduceSomeGoods());
        sellGoods(goods);
        System.out.println("-----------------------");
        setPreferentialPrice(new NoPreferential());
        sellGoods(goods);
    }

结果:

  图片 4

策略格局作为一种对象行为方式, 在那里应该照旧显示到了吧.

那总括一下?给个不易于理解(网上抄的):

  策略形式属于对象的作为方式。其用意是指向一组算法,将每二个算法封装到具备协同接口的独自的类中,从而使得它们可以相互替换。策略情势使得算法能够在不影响到客户端的事态下产生变化。

说的可比空虚, 来个实际的吧:

  一帅哥喜欢约妹子, 那咋约出来吧? 不是享有的胞妹都爱好进食看录像吧.
那针对分化的阿妹, 使用不一样的章程来约. 约喜欢看摄像的堂妹看电影,
约喜欢吃小吃的妹子吃小吃.

那吃饭, 看录制, 吹海风…… 等等, 那些手段,
指标都以为着让四妹做她女对象(这里不研究时间). 目标不变, 手段家常便饭.
那一个主意, 就足以清楚为差异的 strategy. 

 

透过上边包车型大巴例子, 能够见到, 具体的算法与算法之间一贯不依赖关系,
都是同一的(平等性), 能够相互替换的. 那在运作的时候,
每一遍都只能利用一种(唯一性). 

相关文章