溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java設(shè)計(jì)模式中的策略模式如何實(shí)現(xiàn)

發(fā)布時(shí)間:2022-05-26 13:55:21 來源:億速云 閱讀:172 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹了Java設(shè)計(jì)模式中的策略模式如何實(shí)現(xiàn)的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇Java設(shè)計(jì)模式中的策略模式如何實(shí)現(xiàn)文章都會(huì)有所收獲,下面我們一起來看看吧。

1 概述

在平時(shí)開發(fā)中,往往會(huì)遇到這樣一種情況,實(shí)現(xiàn)一種功能有很多種算法或者策略,我們可以根據(jù)不同的算法或者策略來實(shí)現(xiàn)這種功能。比如:想要計(jì)算一種計(jì)算物流的計(jì)算方式,都是計(jì)費(fèi),不同的快遞有不同的計(jì)費(fèi)方式,像京東快遞、百世快遞、圓通快遞。它們之間計(jì)算運(yùn)費(fèi)的方式都是不同的。那我們?cè)趺磥韺?shí)現(xiàn)呢?簡(jiǎn)單的就是if...else...或者switch...case...。這兩種實(shí)現(xiàn)方式被稱之為硬編碼。如果又新增了一種計(jì)費(fèi)方式像韻達(dá)快遞,那么就要去修改我們算法的源代碼。這樣會(huì)使代碼變的較為臃腫,維護(hù)困難。

所以,我們需要想要實(shí)現(xiàn)一種方式就是各自有各自的算法,只需要在客戶端選擇哪種方式去調(diào)用就好了。

2 策略模式

2.1 組成部分

環(huán)境類(Context):用一個(gè)ConcreteStrategy對(duì)象來配置。維護(hù)一個(gè)對(duì)Strategy對(duì)象的引用??梢远x一個(gè)接口來讓Strategy訪問他的數(shù)據(jù)。

抽象策略類(Strategy):定義所有支持算法的公共接口。Context使用這個(gè)接口來調(diào)用某ConcreteStrategy定義的算法。

具體策略類(ConcreteStrategy):以Strategy接口實(shí)現(xiàn)具體的算法。

2.2 代碼示例

以不同快遞公司運(yùn)費(fèi)為例:

步驟一:定義一個(gè)抽象策略類(計(jì)費(fèi)方式)

public interface CommandStrategy {
    /**
     * 計(jì)費(fèi)方式
     * @param message
     */
    void calMoney(String message);
}

步驟二:定義具體的策略類(不同算法類實(shí)現(xiàn)該接口)

public class BaiShiCommand implements CommandStrategy {
    /**
     * 百世快遞計(jì)費(fèi)方式
     * @param message
     */
    @Override
    public void calMoney(String message) {
        System.out.println("百世快遞收費(fèi)方式:"+"起步20,每公斤6元");
    }
}
public class JingDongCommand implements CommandStrategy {
    /**
     * 京東快遞計(jì)費(fèi)方式
     * @param message
     */
    @Override
    public void calMoney(String message) {
        System.out.println("京東快遞收費(fèi)方式:"+"起步30,每公斤5元");
    }
}
public class YuanTongCommand implements CommandStrategy {
    /**
     * 圓通快遞計(jì)費(fèi)方式
     * @param message
     */
    @Override
    public void calMoney(String message) {
        System.out.println("圓通快遞收費(fèi)方式:"+"起步10,每公斤8元");
    }
}

步驟三:定義環(huán)境類

public class CommandContext {
    public CommandStrategy getInstance(String commandType) {
        CommandStrategy commandStrategy = null;
        Map<String, String> allClazz = CommandEnum.getAllClazz();
        //拿到對(duì)應(yīng)算法類對(duì)應(yīng)的路徑
        String clazz = allClazz.get(commandType.trim().toLowerCase());
        if (StringUtils.isNotEmpty(clazz)) {
            try {
                try {
                    //創(chuàng)建一個(gè)對(duì)象實(shí)例
                    commandStrategy = (CommandStrategy) Class.forName(clazz).newInstance();//調(diào)用無參構(gòu)造器創(chuàng)建實(shí)例
                } catch (InstantiationException | IllegalAccessException e) {
                    e.printStackTrace();
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        System.out.println("commandStrategy:"+commandStrategy);
        return commandStrategy;
    }
}

定義一個(gè)枚舉類:

public enum CommandEnum {
    JingDong("京東", "com.liubujun.design.command.JingDongCommand"), BaiShi("百世", "com.liubujun.design.command.BaishiCommand"), YuanTong("圓通", "com.liubujun.design.command.YuanTongCommand");
    private String name;
    private String clazz;
    public static Map<String, String> getAllClazz() {
        Map<String, String> map = new HashMap<>(8);
        System.out.println("==================="+Arrays.toString(CommandEnum.values())+"================");
        for (CommandEnum commandEnum : CommandEnum.values()) {
            map.put(commandEnum.getCommand(), commandEnum.getClazz());
        }
        return map;
    }
    public String getCommand() {
        return name;
    }
    CommandEnum(String command, String clazz) {
        this.name = command;
        this.clazz = clazz;
    }
    public void setCommand(String command) {
        this.name = command;
    }
    public String getClazz() {
        return clazz;
    }
    public void setClazz(String clazz) {
        this.clazz = clazz;
    }
}

客戶端:

public class MainStart {
    public static void main(String[] args) {
        String message = "京東";
        CommandContext commandContext = new CommandContext();
        //拿到message對(duì)應(yīng)算法的對(duì)象實(shí)例
        CommandStrategy commandStrategy = commandContext.getInstance(message);
        commandStrategy.calMoney(message);
    }
}

這樣在客戶端就可以直接調(diào)用哪一種快遞的計(jì)費(fèi)方式了

Java設(shè)計(jì)模式中的策略模式如何實(shí)現(xiàn)

2.3 優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

1) 相關(guān)算法系列 Strategy類層次為Context定義了一系列的可供重用的算法或行為。 繼承有助于析取出這些算法中的公共功能。

2) 提供了可以替換繼承關(guān)系的辦法: 繼承提供了另一種支持多種算法或行為的方法。你可以直接生成一個(gè)Context類的子類,從而給它以不同的行為。但這會(huì)將行為硬行編制到 Context中,而將算法的實(shí)現(xiàn)與Context的實(shí)現(xiàn)混合起來,從而使Context難以理解、難以維護(hù)和難以擴(kuò)展,而且還不能動(dòng)態(tài)地改變算法。最后你得到一堆相關(guān)的類 , 它們之間的唯一差別是它們所使用的算法或行為。 將算法封裝在獨(dú)立的Strategy類中使得你可以獨(dú)立于其Context改變它,使它易于切換、易于理解、易于擴(kuò)展。

3) 消除了一些if else條件語句 :Strategy模式提供了用條件語句選擇所需的行為以外的另一種選擇。當(dāng)不同的行為堆砌在一個(gè)類中時(shí) ,很難避免使用條件語句來選擇合適的行為。將行為封裝在一個(gè)個(gè)獨(dú)立的Strategy類中消除了這些條件語句。含有許多條件語句的代碼通常意味著需要使用Strategy模式。

4) 實(shí)現(xiàn)的選擇 Strategy模式可以提供相同行為的不同實(shí)現(xiàn)??蛻艨梢愿鶕?jù)不同時(shí)間 /空間權(quán)衡取舍要求從不同策略中進(jìn)行選擇。

缺點(diǎn):

1)客戶端必須知道所有的策略類,并自行決定使用哪一個(gè)策略類: 本模式有一個(gè)潛在的缺點(diǎn),就是一個(gè)客戶要選擇一個(gè)合適的Strategy就必須知道這些Strategy到底有何不同。此時(shí)可能不得不向客戶暴露具體的實(shí)現(xiàn)問題。因此僅當(dāng)這些不同行為變體與客戶相關(guān)的行為時(shí) , 才需要使用Strategy模式。

2 ) Strategy和Context之間的通信開銷 :無論各個(gè)ConcreteStrategy實(shí)現(xiàn)的算法是簡(jiǎn)單還是復(fù)雜, 它們都共享Strategy定義的接口。因此很可能某些 ConcreteStrategy不會(huì)都用到所有通過這個(gè)接口傳遞給它們的信息;簡(jiǎn)單的 ConcreteStrategy可能不使用其中的任何信息!這就意味著有時(shí)Context會(huì)創(chuàng)建和初始化一些永遠(yuǎn)不會(huì)用到的參數(shù)。如果存在這樣問題 , 那么將需要在Strategy和Context之間更進(jìn)行緊密的耦合。

3 )策略模式將造成產(chǎn)生很多策略類:可以通過使用享元模式在一定程度上減少對(duì)象的數(shù)量。 增加了對(duì)象的數(shù)目 Strategy增加了一個(gè)應(yīng)用中的對(duì)象的數(shù)目。有時(shí)你可以將 Strategy實(shí)現(xiàn)為可供各Context共享的無狀態(tài)的對(duì)象來減少這一開銷。任何其余的狀態(tài)都由 Context維護(hù)。Context在每一次對(duì)Strategy對(duì)象的請(qǐng)求中都將這個(gè)狀態(tài)傳遞過去。共享的 Strategy不應(yīng)在各次調(diào)用之間維護(hù)狀態(tài)。

關(guān)于“Java設(shè)計(jì)模式中的策略模式如何實(shí)現(xiàn)”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“Java設(shè)計(jì)模式中的策略模式如何實(shí)現(xiàn)”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI