iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0

介紹

策略模式跟工廠模式很像
我自己的理解,兩者的差別是這樣:

  • 策略模式:重視過程
  • 工廠模式:重視結果

這次的範例是會員買商品,會有三種促銷情境

  1. 單件折扣:買一件時打八折
  2. 第二個商品折扣:買兩件時,第二個商品打八折
  3. 沒有折扣:買一百件,沒有打折 (有錢人不需要折扣)

策略模式實作

  1. 建立促銷介面
public interface Promotion {
    String getType();
    BigDecimal getPrice(BigDecimal originalPrice, BigDecimal discount, int quantity);
}
  1. 寫單件折扣算式
public class ItemPromotion implements Promotion {

    @Override
    public String getType() {
        return "單件折扣";
    }

    @Override
    public BigDecimal getPrice(BigDecimal originalPrice, BigDecimal discount, int quantity) {
        BigDecimal price;
        price = originalPrice.multiply(discount);
        return price;
    }
}
  1. 寫第二個商品折扣算式
public class SecondItemPromotion implements Promotion {

    @Override
    public String getType() {
        return "第二個商品折扣";
    }

    @Override
    public BigDecimal getPrice(BigDecimal originalPrice, BigDecimal discount, int quantity) {
        BigDecimal price;
        price = originalPrice.multiply(discount);
        price = price.add(originalPrice);
        return price;
    }
}
  1. 寫沒有折扣算式
public class NoPromotion implements Promotion {

    @Override
    public String getType() {
        return "沒有折扣";
    }

    @Override
    public BigDecimal getPrice(BigDecimal originalPrice, BigDecimal discount, int quantity) {
        BigDecimal price;
        price = originalPrice.multiply(BigDecimal.valueOf(quantity));
        return price;
    }
}
  1. 建立會員類別,在getPayMoney方法寫促銷策略
public class Member {

    private String name;
    private Promotion promotion;

    public Member(String name) {
        this.name = name;
    }

    public BigDecimal getPayMoney(BigDecimal originalPrice, BigDecimal discount, int quantity) {
        BigDecimal money;

        switch (quantity) {
            case 1:
                promotion = new ItemPromotion();
                money = promotion.getPrice(originalPrice, discount, quantity);
                break;
            case 2:
                promotion = new SecondItemPromotion();
                money = promotion.getPrice(originalPrice, discount, quantity);
                break;
            default:
                promotion = new NoPromotion();
                money = promotion.getPrice(originalPrice, discount, quantity);
                break;
        }

        return money;
    }

    public String getName() {
        return name;
    }

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

    public Promotion getPromotion() {
        return promotion;
    }

    public void setPromotion(Promotion promotion) {
        this.promotion = promotion;
    }
}

策略模式測試

  1. 測試案例
    • 第一個會員 Andy 買一件商品,是單件折扣
    • 第二個會員 Jack 買兩件商品,是第二個商品折扣
    • 第三個會員 艾因利奇曼 買一百件商品,沒有折扣
public class JavaTest {

    @Test
    public void show() {

        StringBuilder text;
        text = new StringBuilder();
        text.append("\n");

        text.append(getMemberText(new Member("Andy"), 1));
        text.append("\n");

        text.append(getMemberText(new Member("Jack"), 2));
        text.append("\n");

        text.append(getMemberText(new Member("Rich"), 100));
        text.append("\n");

        assertEquals("測試", text.toString());
    }

    private String getMemberText(Member member, int quantity) {
        StringBuilder memberText;
        memberText = new StringBuilder();

        memberText.append("姓名:");
        memberText.append(member.getName());
        memberText.append(" / ");
        memberText.append("折扣名稱:");
        memberText.append(member.getPromotion().getType());
        memberText.append(" / ");
        memberText.append("付多少錢:");
        memberText.append(member.getPayMoney(new BigDecimal("100"), new BigDecimal("0.8"), quantity));

        return memberText.toString();
    }
}
  1. 執行測試
姓名:Andy / 折扣名稱:單件折扣 / 付多少錢:80.0
姓名:Jack / 折扣名稱:第二個商品折扣 / 付多少錢:180.0
姓名:Rich / 折扣名稱:沒有折扣 / 付多少錢:10000

上一篇
113/19 - 觀察者模式(Observer)- Kotlin
下一篇
113/21 - 策略模式(Strategy)- Kotlin
系列文
肯定會斷賽之在 Android 開發使用設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言