嗯wwww一区二区三区视频,不卡的日韩播放视频在线观看,国产日本高清视频在线播放,国产精品无毒不卡久久久,国产片aⅴ在线观看国语

從奧軟件(上海)有限公司
SOLID設(shè)計原則依賴倒置原則

SOLID設(shè)計原則依賴倒置原則

提供復(fù)雜邏輯的高級模塊應(yīng)易于重用,并且不受提供實用程序功能的低級模塊的更改的影響。

技術(shù)開發(fā) 編程 技術(shù)框架 技術(shù)發(fā)展

 

SOLID設(shè)計原則依賴倒置原則

提供復(fù)雜邏輯的高級模塊應(yīng)易于重用,并且不受提供實用程序功能的低級模塊的更改的影響。

依賴倒置原則的定義

該原理的基本思想很簡單,即很重要:提供復(fù)雜邏輯的高級模塊應(yīng)易于重用,并且不受提供實用程序功能的低級模塊的更改的影響。為此,您需要引入一個抽象,該抽象將高級模塊和低級模塊彼此分離。

基于此思想,Robert C. Martin對依賴倒置原則的定義包括兩個部分:

  • 高級模塊不應(yīng)依賴于低級模塊。兩者都應(yīng)依賴抽象。

  • 抽象不應(yīng)依賴細(xì)節(jié)。細(xì)節(jié)應(yīng)取決于抽象。

該定義的一個重要細(xì)節(jié)是,高層和低層模塊取決于抽象。設(shè)計原理不僅會改變依賴關(guān)系的方向,就像您第一次閱讀依賴關(guān)系的名稱時所期望的那樣。通過在高級模塊和低級模塊之間引入抽象,它在高級模塊和低級模塊之間劃分了依賴關(guān)系。因此,最后,您得到兩個依賴項:

高級模塊取決于抽象,并且低層依賴于相同的抽象。

基于其他SOLID原則

這聽起來可能比通常要復(fù)雜得多。因此,如果您在代碼中應(yīng)用了“打開/關(guān)閉原則”和“ Liskov替換原則”,則它也將遵循“依賴倒置原則”。

打開/關(guān)閉原則要求打開軟件組件以進(jìn)行擴(kuò)展,但關(guān)閉軟件組件以進(jìn)行修改。您可以通過引入可以提供不同實現(xiàn)的接口來實現(xiàn)這一點。接口本身已關(guān)閉以進(jìn)行修改,您可以通過提供新的接口實現(xiàn)輕松地對其進(jìn)行擴(kuò)展。

您的實現(xiàn)應(yīng)遵循Liskov替換原理,以便您可以在不破壞應(yīng)用程序的情況下將它們替換為同一接口的其他實現(xiàn)。

讓我們看一下CoffeeMachine項目,我將在其中應(yīng)用所有這三個設(shè)計原理。

用依賴倒置原理沖泡咖啡

您可以購買許多不同的咖啡機(jī)。較為簡單的是使用水和磨碎的咖啡來沖泡過濾咖啡,而高級的則包括用研磨機(jī)新鮮研磨所需量的咖啡豆,并且可以用來沖泡不同種類的咖啡。

如果您構(gòu)建了一個咖啡機(jī)應(yīng)用程序,該應(yīng)用程序會在早上自動為您沖泡一杯新鮮的咖啡,則可以將這些咖啡機(jī)建模為BasicCoffeeMachine和PremiumCoffeeMachine類。

依賴反轉(zhuǎn)原理與代碼示例

實施BasicCoffeeMachine

BasicCoffeeMachine的實現(xiàn)非常簡單。它僅實現(xiàn)一個構(gòu)造函數(shù)和兩個公共方法。您可以調(diào)用addGroundCoffee方法來重新填充研磨咖啡,并調(diào)用brewFilterCoffee方法來沖泡一杯過濾咖啡。

image.png

import java.util.Map;public class BasicCoffeeMachine implements CoffeeMachine {

    private Configuration config;
    private Map<CoffeeSelection, GroundCoffee> groundCoffee;
    private BrewingUnit brewingUnit;

    public BasicCoffeeMachine(Map<CoffeeSelection, GroundCoffee> coffee).   
        this.groundCoffee = coffee;
        this.brewingUnit = new BrewingUnit();
        this.config = new Configuration(30, 480);
    }

    @Override
    public Coffee brewFilterCoffee() {
        // get the coffee
        GroundCoffee groundCoffee = this.groundCoffee.get(CoffeeSelection.FILTER_COFFEE);
        // brew a filter coffee  
       return this.brewingUnit.brew(CoffeeSelection.FILTER_COFFEE, groundCoffee, this.config.getQuantityWater());
    }

    public void addGroundCoffee(CoffeeSelection sel, GroundCoffee newCoffee) throws CoffeeException { 
        GroundCoffee existingCoffee = this.groundCoffee.get(sel);
        if (existingCoffee != null) {
            if (existingCoffee.getName().equals(newCoffee.getName())) {
                existingCoffee.setQuantity(existingCoffee.getQuantity() + newCoffee.getQuantity())
            } else {
                throw new CoffeeException("Only one kind of coffee supported for each CoffeeSelection.")
            }
        } else {
            this.groundCoffee.put(sel, newCoffee)
        }
    }  }

要實現(xiàn)遵循依賴倒置原則的類并可以使用BasicCoffeeMachine或PremiumCoffeeMachine類來沖泡咖啡,您需要應(yīng)用“打開/關(guān)閉”和“ Liskov替換”原理。這需要少量的重構(gòu),在此期間您將為兩個類引入接口抽象。

引入抽象

這兩種咖啡機(jī)的主要任務(wù)是沖泡咖啡。但是它們使您可以沖泡不同種類的咖啡。如果使用BasicCoffeeMachine,則只能沖泡過濾咖啡,而使用PremiumCoffeeMachine,則可以沖泡過濾咖啡或濃縮咖啡。那么,哪種接口抽象最適合兩個類?

正如所有咖啡愛好者都會同意的那樣,過濾咖啡和濃縮咖啡之間存在巨大差異。這就是為什么我們使用不同的機(jī)器來釀造它們的原因,即使如此,某些機(jī)器也可以做到。因此,我建議創(chuàng)建兩個獨立的抽象:

所述FilterCoffeeMachine接口定義了咖啡brewFilterCoffee()方法,并得到由能夠沖泡過濾咖啡的所有咖啡機(jī)類實現(xiàn)的。

您可以用來釀造意式濃縮咖啡的所有類均實現(xiàn)EspressoMachine接口,該接口定義了Coffee brewEspresso()方法。

如下面的代碼片段所示,兩個接口的定義都非常簡單。

public interface CoffeeMachine {
    Coffee brewFilterCoffee();}public interface EspressoMachine {
    Coffee brewEspresso();}

在下一步中,您需要重構(gòu)兩個咖啡機(jī)類,以便它們實現(xiàn)這兩個接口中的一個或兩個。


重構(gòu)BasicCoffeeMachine類

讓我們從BasicCoffeeMachine類開始。您可以使用它來沖泡過濾咖啡,因此它應(yīng)該實現(xiàn)CoffeeMachine接口。該類已經(jīng)實現(xiàn)了brewFilterCoffee()方法。您只需要將實現(xiàn)CoffeeMachine添加到類定義中。

public class BasicCoffeeMachine implements CoffeeMachine {
    private Configuration config;
    private Map<CoffeeSelection, GroundCoffee> groundCoffee;
    private BrewingUnit brewingUnit;

    public BasicCoffeeMachine(Map<CoffeeSelection, GroundCoffee> coffee) {
        this.groundCoffee = coffee;
        this.brewingUnit = new BrewingUnit();
        this.config = new Configuration(30, 480);
    }

    @Override
    public Coffee brewFilterCoffee() {
        // get the coffee
        GroundCoffee groundCoffee = this.groundCoffee.get(CoffeeSelection.FILTER_COFFEE);
        // brew a filter coffee
        return this.brewingUnit.brew(CoffeeSelection.FILTER_COFFEE, groundCoffee, this.config.getQuantityWater());
    }

    public void addGroundCoffee(CoffeeSelection sel, GroundCoffee newCoffee) throws CoffeeException {
        GroundCoffee existingCoffee = this.groundCoffee.get(sel);
        if (existingCoffee != null) {
            if (existingCoffee.getName().equals(newCoffee.getName())) {
                existingCoffee.setQuantity(existingCoffee.getQuantity() + newCoffee.getQuantity());
            } else {
             throw new CoffeeException("Only one kind of coffee supported for each CoffeeSelection.");
           }
        } else {
            this.groundCoffee.put(sel, newCoffee);
        }
    } }

重構(gòu)PremiumCoffeeMachine類

PremiumCoffeeMachine的重構(gòu)也不需要很多工作。您可以使用咖啡機(jī)沖煮過濾咖啡和濃縮咖啡,因此PremiumCoffeeMachine類應(yīng)實現(xiàn)CoffeeMachine和EspressoMachine接口。該類已經(jīng)實現(xiàn)了兩個接口定義的方法。您只需要聲明它實現(xiàn)了接口。

import java.util.HashMap;import java.util.Map;public class PremiumCoffeeMachine implements CoffeeMachine, EspressoMachine {
    private Map<CoffeeSelection, Configuration> configMap;
    private Map<CoffeeSelection, CoffeeBean> beans;
    private Grinder grinder;
    private BrewingUnit brewingUnit;

    public PremiumCoffeeMachine(Map<CoffeeSelection, CoffeeBean> beans) {
        this.beans = beans;
        this.grinder = new Grinder();
        this.brewingUnit = new BrewingUnit();
        this.configMap = new HashMap<>();
        this.configMap.put(CoffeeSelection.FILTER_COFFEE, new Configuration(30, 480));
        this.configMap.put(CoffeeSelection.ESPRESSO, new Configuration(8, 28)); 
    }

    @Override
    public Coffee brewEspresso() {
        Configuration config = configMap.get(CoffeeSelection.ESPRESSO);
        // grind the coffee beans
        GroundCoffee groundCoffee = this.grinder.grind(
           this.beans.get(CoffeeSelection.ESPRESSO),
           config.getQuantityCoffee());
       // brew an espresso
       return this.brewingUnit.brew(CoffeeSelection.ESPRESSO, groundCoffee,
           config.getQuantityWater());
    }

    @Override
    public Coffee brewFilterCoffee() {
        Configuration config = configMap.get(CoffeeSelection.FILTER_COFFEE);
        // grind the coffee beans
        GroundCoffee groundCoffee = this.grinder.grind(
            this.beans.get(CoffeeSelection.FILTER_COFFEE),
            config.getQuantityCoffee());
        // brew a filter coffee
        return this.brewingUnit.brew(CoffeeSelection.FILTER_COFFEE, 
            groundCoffee,config.getQuantityWater());
    }

    public void addCoffeeBeans(CoffeeSelection sel, CoffeeBean newBeans) throws CoffeeException {
        CoffeeBean existingBeans = this.beans.get(sel);
        if (existingBeans != null) {
            if (existingBeans.getName().equals(newBeans.getName())) {
                existingBeans.setQuantity(existingBeans.getQuantity() + newBeans.getQuantity());
            } else {
                throw new CoffeeException("Only one kind of coffee supported for each CoffeeSelection.");
            }
        } else {
            this.beans.put(sel, newBeans);
        }
    }}

直接依賴于其中一個實現(xiàn)類的唯一代碼是CoffeeAppStarter類,該類實例化CoffeeApp對象并提供CoffeeMachine接口的實現(xiàn)。您可以通過使用依賴項注入框架(例如Spring或CDI)在運行時解析依賴項來完全避免這種編譯時依賴項。

image.png

public class CoffeeApp {
    private CoffeeMachine coffeeMachine;

    public CoffeeApp(CoffeeMachine coffeeMachine) {
     this.coffeeMachine = coffeeMachine    }

    public Coffee prepareCoffee() throws CoffeeException {
        Coffee coffee = this.coffeeMachine.brewFilterCoffee();
        System.out.println("Coffee is ready!");
        return coffee;
    }  }


import java.util.HashMap;import java.util.Map;public class CoffeeAppStarter {
    public static void main(String[] args) {
        // create a Map of available coffee beans
        Map<CoffeeSelection, CoffeeBean> beans = new HashMap<CoffeeSelection, CoffeeBean>();
        beans.put(CoffeeSelection.ESPRESSO, new CoffeeBean(
            "My favorite espresso bean", 1000));
        beans.put(CoffeeSelection.FILTER_COFFEE, new CoffeeBean(
             "My favorite filter coffee bean", 1000))
        // get a new CoffeeMachine object
        PremiumCoffeeMachine machine = new PremiumCoffeeMachine(beans);
        // Instantiate CoffeeApp
        CoffeeApp app = new CoffeeApp(machine);
        // brew a fresh coffee
        try {
           app.prepareCoffee();
        } catch (CoffeeException e) {
            e.printStackTrace();
        }
    }}

    

概要

依賴倒置原則是我們在本系列中討論的第五個也是最后一個設(shè)計原則。它引入了上層和下層軟件組件之間的接口抽象,以消除它們之間的依賴關(guān)系。

正如在示例項目中看到的那樣,您僅需要在代碼庫中應(yīng)用“打開/關(guān)閉”和“ Liskov替換”原理。完成此操作后,您的類也將遵循“依賴倒置原則”。這使您能夠更改上層和下層組件,而不會影響任何其他類,只要您不更改任何接口抽象即可。

技術(shù)開發(fā) 編程 技術(shù)框架 技術(shù)發(fā)展

湄潭县| 和硕县| 潜山县| 阿巴嘎旗| 噶尔县| 鸡泽县| 天峨县| 环江| 汉中市| 宜兴市| 张家港市| 梓潼县| 修文县| 宁南县| 麟游县| 满城县| 墨玉县| 华蓥市| 项城市| 吉木乃县| 伊宁县| 建湖县| 民乐县| 清丰县| 普兰店市| 弥勒县| 吉安县| 镇沅| 绥宁县| 莎车县| 报价| 富民县| 宜良县| 金塔县| 临泽县| 措美县| 浦县| 建水县| 灌阳县| 隆安县| 宁强县|