1. 程式人生 > >重構優化設計模式應用~一個榨汁機應用場景示例

重構優化設計模式應用~一個榨汁機應用場景示例

現在有這樣一個需求,通過java實現一個榨汁機示例。榨汁機呢,現在支援水果(比如蘋果,香蕉),不同水果出汁比例不一樣(比如,1kg蘋果智慧出0.3kg汁)。對於使用者(或者講客戶端)來講,他只關注只要能榨汁即可(不需要關注具體怎麼榨汁的,你搗鼓蘋果,它榨出蘋果汁,你搗鼓香蕉,它榨出香蕉汁)。對於使用者來講,榨汁機有普通版,升級版,豪華版,不同檔次榨汁機功能選單肯定也不一樣。 程式碼地址:原始碼地址

1、原料定義

我們分析需求,發現既然是榨汁機,那麼肯定是榨汁機能夠榨的東西,你給它塊石頭,也炸不出汁。

該抽象類AbstractFruit派生兩個子類,Apple和Banana,對於派生的其他水果,只需繼承這個抽象類即可。AbstractFruit包括name、color、weight屬性

抽象水果類:AbstractFruit

/**
 * @description: 抽象水果類
 * @Date : 2018/9/20 下午1:24
 * @Author : 石鼕鼕-Seig Heil(dongdong.sh[email protected])
 */
public abstract class AbstractFruit {
    /**
     * 名稱
     */
    protected String name;
    /**
     * 顏色
     */
    protected String color;
    /**
     * 重量
     */
    protected
double weight; public AbstractFruit() { } public AbstractFruit(String name, String color, double weight) { this.name = name; this.color = color; this.weight = weight; } public String getName() { return name; } public void setName(String name)
{ this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } @Override public String toString() { return "AbstractFruit{" + "name='" + name + '\'' + ", color='" + color + '\'' + ", weight=" + weight + '}'; } }

具體水果類:Apple

/**
 * @description: 蘋果類
 * @Date : 2018/9/20 下午1:27
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public class Apple extends AbstractFruit {

    public Apple() {
    }

    public Apple(String name, String color, double weight) {
        super(name, color, weight);
    }

    @Override
    public String toString() {
        return super.toString();
    }
}

具體水果類:Banana

/**
 * @description: 香蕉
 * @Date : 2018/9/20 下午1:27
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public class Banana extends AbstractFruit {

    public Banana() {
    }

    public Banana(String name, String color, double weight) {
        super(name, color, weight);
    }

    @Override
    public String toString() {
        return super.toString();
    }
}

2、機器定義

既然是榨汁機,肯定是個機器,機器呢,它支援榨汁,你給他原料(水果)它就可以榨汁,輸出是啥呢?肯定是果汁,所以這個機器可以榨汁,給它原料,輸出果汁。

榨汁介面:Juicing

/**
 * @description: 榨汁介面
 * @Date : 2018/9/20 下午1:20
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public interface Juicing {
    /**
     * 榨汁動作
     */
    void press();
}

果汁類:Juice

/**
 * @description: 果汁
 * @Date : 2018/9/20 下午1:54
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public class Juice {
    /**
     * 名稱
     */
    private String name;
    /**
     * 重量
     */
    private double weight;

    public Juice(String name, double weight) {
        this.name = name;
        this.weight = weight;
    }

    public String getName() {
        return name;
    }

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

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Juice{" +
                "name='" + name + '\'' +
                ", weight=" + weight +
                '}';
    }
}

抽象榨汁機:AbstractJuicer

/**
 * @description: 抽象榨汁機
 * @Date : 2018/9/20 下午1:19
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public abstract class AbstractJuicer implements Juicing {
    /**
     * 水果
     */
    protected AbstractFruit fruit;
    /**
     * 果汁
     */
    protected Juice juice;
    /**
     * 名稱
     */
    private String materialName;
    /**
     *
     */
    private double materialWeight;

    public AbstractJuicer(AbstractFruit fruit) {
        this.fruit = fruit;
    }

    /**
     * 初始化
     */
    protected void init(){
        materialWeight = fruit.getWeight();
        materialName = fruit.getName();
    }

    /**
     * 外部呼叫
     */
    public final void execute(){
        init();
        press();
    }

    @Override
    public void press() {
        AbstractJuiceStrategy strategy = StrategyFactory.create(materialName);
        ScaleContext scaleContext = new ScaleContext(materialWeight);
        strategy.setContext(scaleContext);
        strategy.execute();
        juice = new Juice(materialName,scaleContext.getOutWeight());
    }

    /**
     * 獲取果汁
     * @return
     */
    public Juice getJuice() {
        return juice;
    }
}

通用榨汁機類:GeneralJuicer

/**
 * @description: 通用榨汁機
 * @Date : 2018/9/20 下午7:40
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public class GeneralJuicer extends AbstractJuicer {
    public GeneralJuicer(AbstractFruit fruit) {
        super(fruit);
    }
}

3、榨汁比例策略

不同水果榨汁比例肯定不一樣,既然達到系統預置,肯定榨汁機根據選單預置功能從生產就確定的了。

比例配置類:ScaleConfig

這裡我們通過一個列舉定義,指定不同水果配置比例,後期擴充套件時,只需要新增列舉成員即可。

/**
 * @description: 比例配置
 * @Date : 2018/9/20 下午3:42
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public enum ScaleConfig {
    APPLE("蘋果",0.6),
    BANANA("香蕉",0.3)
    ;

    ScaleConfig(String meterial, double scale) {
        this.meterial = meterial;
        this.scale = scale;
    }

    /**
     * 原料
     */
    private String meterial;
    /**
     * 原料與榨汁輸出比例
     */
    private double scale;

    public String getMeterial() {
        return meterial;
    }

    public double getScale() {
        return scale;
    }

    public static double getScale(String meterial){
        for(ScaleConfig config : ScaleConfig.values()){
            if(config.getMeterial().equals(meterial)){
                return config.getScale();
            }
        }
        return 0d;
    }
}

榨汁策略上線文:ScaleContext

上下文類,包含原料重量和輸出重量,即榨汁配比。

/**
 * @description: 榨汁策略上線文
 * @Date : 2018/9/20 下午3:40
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public class ScaleContext {
    /**
     * 原料重量
     */
    protected double materialWeight;
    /**
     * 輸出
     */
    protected double outWeight;

    public ScaleContext(double materialWeight) {
        this.materialWeight = materialWeight;
    }

    public double getMaterialWeight() {
        return materialWeight;
    }

    public void setMaterialWeight(double materialWeight) {
        this.materialWeight = materialWeight;
    }

    public double getOutWeight() {
        return outWeight;
    }

    public void setOutWeight(double outWeight) {
        this.outWeight = outWeight;
    }
}

抽象榨汁輸出策略類:AbstractJuiceStrategy

這裡我們抽象出一個策略類,不同水果榨汁比例不一樣,只需派生該抽象類即可。 抽象類包含定義了一個抽象方法getScale,同時execute方法,把配比方法骨架封裝起來,使用模板方法模式。

/**
 * @description: 抽象榨汁輸出策略類
 * @Date : 2018/9/20 下午3:48
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public abstract class AbstractJuiceStrategy {
    /**
     * 榨汁上下文物件
     */
    protected ScaleContext context;

    /**
     * 原料名稱
     */
    protected String material;
    /**
     * 原料重量
     */
    protected double materialWeight;
    /**
     * 輸出
     */
    protected double outWeight;
    /**
     * 獲取比例
     * @return
     */
    abstract double getScale();

    public AbstractJuiceStrategy() {
    }

    /**
     * 建構函式
     * 通過建構函式注入context
     * @param context
     */
    public AbstractJuiceStrategy(String material,ScaleContext context) {
        this.material = material;
        this.context = context;
    }

    /**
     * 初始化
     */
    protected void init(){
        this.materialWeight = context.getMaterialWeight();
        System.out.println(MessageFormat.format("原料輸入中,當前原料={0},重量={1}",material,materialWeight));
    }

    /**
     * 配比加工
     */
    protected void match(){
        this.outWeight = this.materialWeight * getScale();
        System.out.println("輸出重量"+this.outWeight);
    }

    /**
     * 後置處理
     */
    protected void after(){
        this.context.setOutWeight(outWeight);
    }

    /**
     * 外部呼叫
     */
    public final void execute(){
        init();
        match();
        after();
    }

    public void setContext(ScaleContext context) {
        this.context = context;
    }
}

蘋果原料果汁榨汁配比策略類:AppleJuiceStrategy

/**
 * @description: 蘋果原料果汁榨汁配比策略類
 * @Date : 2018/9/20 下午3:58
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public class AppleJuiceStrategy extends AbstractJuiceStrategy {

    @Override
    double getScale() {
        return ScaleConfig.getScale(super.material);
    }

    public AppleJuiceStrategy() {
    }

    public AppleJuiceStrategy(String material, ScaleContext context) {
        super(material, context);
    }

    public AppleJuiceStrategy(ScaleContext context) {
        super("蘋果",context);
    }
}

香蕉原料果汁榨汁配比策略類:BananaJuiceStrategy

/**
 * @description: 香蕉原料果汁榨汁配比策略類
 * @Date : 2018/9/20 下午3:58
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public class BananaJuiceStrategy extends AbstractJuiceStrategy {

    @Override
    double getScale() {
        return ScaleConfig.getScale(super.material);
    }

    public BananaJuiceStrategy() {
    }

    public BananaJuiceStrategy(String material, ScaleContext context) {
        super(material, context);
    }

    public BananaJuiceStrategy(ScaleContext context) {
        super("香蕉",context);
    }
}

策略工廠類:StrategyFactory

對於呼叫發,我們通過簡單工廠實現策略類的例項建立,對於輸入原料,不關心具體如何配比,只需要傳入原料名稱即可,內部根據名稱獲取不同策略類。

/**
 * @description: 策略工廠類
 * @Date : 2018/9/20 下午4:04
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public enum StrategyFactory {
    APPLE("蘋果"),
    BANANA("香蕉"),
    ;

    StrategyFactory(String material) {
        this.material = material;
    }

    /**
     * 原料
     */
    private String material;

    public String getMaterial() {
        return material;
    }

    /**
     * 策略生產
     * @param material
     * @return
     */
    public static AbstractJuiceStrategy create(String material){
        switch (material){
            case "蘋果":
                return new AppleJuiceStrategy("蘋果",new ScaleContext(0d));
            case "香蕉":
                return new BananaJuiceStrategy("香蕉",new ScaleContext(0d));
        }
        return null;
    }
}

4、榨汁機整合器

為什麼這麼定義這個術語呢,既然是榨汁機,肯定是生產商在生產時,都已經把零部件整合安裝完畢,對於使用者來講,只需要暴露使用說明書。你不需要明白榨汁機具體怎麼榨汁,水果能榨汁多少,你只需要按照說明書上的要求,即可榨汁你放的水果。

執行器介面:Executor

/**
 * @description: 執行器介面
 * @Date : 2018/9/20 下午7:38
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public interface Executor {
    /**
     * 執行
     */
    void execute();
}

執行器上下文:WrapperContext

該上線文物件,包括幾個成員果汁機,原料,以及輸出果汁,所以它承載著是一個相當於中介的作用,對於果汁機,原料,以及輸出果汁無需呼叫彼此,只需要委託給上線文物件即可。

/**
 * @description: 程式上下文物件,承載果汁機和水果的包裝
 * @Date : 2018/9/20 下午1:31
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public class WrapperContext {
    /**
     * 果汁機
     */
    protected AbstractJuicer juicer;
    /**
     * 原料:水果
     */
    protected AbstractFruit fruit;
    /**
     * 果汁
     */
    protected Juice juice;

    public WrapperContext(AbstractJuicer juicer, AbstractFruit fruit) {
        this.juicer = juicer;
        this.fruit = fruit;
    }

    public AbstractJuicer getJuicer() {
        return juicer;
    }

    public void setJuicer(AbstractJuicer juicer) {
        this.juicer = juicer;
    }

    public Juice getJuice() {
        return juice;
    }

    public void setJuice(Juice juice) {
        this.juice = juice;
    }

    public AbstractFruit getFruit() {
        return fruit;
    }

    public void setFruit(AbstractFruit fruit) {
        this.fruit = fruit;
    }

    public WrapperContext(AbstractJuicer juicer, AbstractFruit fruit, Juice juice) {
        this.juicer = juicer;
        this.fruit = fruit;
        this.juice = juice;
    }
}

抽象包裝執行器:WrapperExecutor

果汁機,原料,以及輸出果汁委託給WrapperContext,那具體執行者,就委託給WrapperExecutor,內部承載著物件的呼叫。

/**
 * @description: 抽象包裝執行器
 * @Date : 2018/9/20 下午1:31
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public abstract class WrapperExecutor implements Executor{

    protected WrapperContext context;

    public WrapperExecutor(WrapperContext context) {
        this.context = context;
    }

    @Override
    public void execute() {
        AbstractJuicer juicer = context.getJuicer();
        juicer.execute();
        context.setJuice(juicer.getJuice());
    }
}

通用包裝執行器:GeneralExecutor

/**
 * @description: 通用包裝執行器
 * @Date : 2018/9/20 下午7:47
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public class GeneralExecutor extends WrapperExecutor {
    public GeneralExecutor(WrapperContext context) {
        super(context);
    }
}

5、測試

/**
 * @description:
 * @Date : 2018/9/20 下午7:39
 * @Author : 石鼕鼕-Seig Heil([email protected])
 */
public class JuicerTest {

    @Test
    public void apple(){
        AbstractFruit apple = new Apple(StrategyFactory.APPLE.getMaterial(),"紅色",1000);
        GeneralJuicer juicer = new GeneralJuicer(apple);
        WrapperContext context = new WrapperContext(juicer,apple);
        GeneralExecutor executor = new GeneralExecutor(context);
        executor.execute();
        System.out.println(context.getJuice());
    }

    @Test
    public void banana(
            
           

相關推薦

重構優化設計模式應用~一個榨汁應用場景示例

現在有這樣一個需求,通過java實現一個榨汁機示例。榨汁機呢,現在支援水果(比如蘋果,香蕉),不同水果出汁比例不一樣(比如,1kg蘋果智慧出0.3kg汁)。對於使用者(或者講客戶端)來講,他只關注只要能榨汁即可(不需要關注具體怎麼榨汁的,你搗鼓蘋果,它榨出蘋

設計模式】Java服務開發應用策略模式一個例子

當我們寫程式碼時遇到了需要if else 需要實現的問題時,就可以考慮是否引入某種設計模式,能讓程式碼寫得更加graceful。 假設我們現在有個設計使用者查詢的RESTful介面的需求,使用者可能有多個屬性,有id,firstName ,lastName,age,adr

MVC設計模式在網站中的應用

設計 分享 階段 可用性 狀態 代碼 img 多個 如果 MVC設計模式在網站中的應用 以淘寶的購物車為例 一、結合六個基本質量屬性 可修改性 采用MVC設計模式的時候,可以將視圖、模型、控制器分析,將用戶動作、數據表示、應用數據分離開來,如果用戶需要以不同的視圖來展示,只

設計模式在遊戲中的應用--原型模式(六)

markdown 什麽 java 原型模型 char mod 結構圖 void -s Prototype原型模式是一種創建型設計模式,Prototype模式同意一個對象再創建另外一個可定制的對象,根本無需知道不論什麽怎樣創建的細節,工作原理是:通過將一個

設計模式在遊戲中的應用--模板方法(七)

一次 cli ces 情況下 sheet skill 對象 cal 模式 模板方法這個名字看著非常陌生,事實上在遊戲中大量地使用了模板方法。由於遊戲中存在玩家、NPC

23種設計模式在Android中的應用

ets ros 而不是 auto 排隊 private eth mail 記錄 所有江湖偶遇,都是宿命相逢 ----《逆水寒》,只是覺得文案不錯,就用了。哈哈! 一.設計原則: 單一職責原則(SRP):任何一個對象都應給只有一個單獨的職責(“低耦合,高內聚”)裏氏替換原則(

Java學習——模板設計模式——抽象類的實際應用

設計模式的精髓:解耦。而模板設計模式是通過第三方進行解耦 什麼是內聚、解耦大家可以看一下博主 小異常 的博文:https://blog.csdn.net/sun8112133/article/details/81040275 模板設計模式:(基於抽象類)在一個方法中定義一個演算法的骨架,而將

設計模式在開發中的應用 -- 代理模式

代理模式 代理是一種模式,提供了對目標物件的間接訪問方式,即通過代理訪問目標物件。如此便於在 實現的基礎上增加額外的功能操作,前攔截,後攔截等,以滿足自身的業務需求,同時代理模式 便於擴充套件目標物件功能的特點也為多人所用。 靜態代理 靜態代理的實現比較簡

7.Java_模板設計模式---抽象類的實際應用(咖啡和茶的沖泡法),基於抽象類,核心是封裝演算法。引入鉤子方法。開閉原則。23種設計模式

基於抽象類的模板設計模式,核心是封裝演算法。 1、模板方法定義了一個演算法的步驟,允許子類為一個或多個步驟提供具體實現。 2、模板(模板方法)模式:(典型:Servlet),AQS 在一個方法中定義演算法的框架,將一些具體步驟延遲到子類中實現。 模板模式

23種設計模式(概念、原則、場景、優點、缺點、應用)簡述

《大話設計模式》中提到了 24種設計模式: 簡單工廠模式,策略模式、裝飾模式、代理模式、工廠方法模式、原型模式、模板方法模式、外觀模式、建造者模式、觀察者模式、抽象工廠模式、狀態模式、介面卡模式、備忘錄模式、組合模式、迭代器模式、單例模式、橋接模式、命令模式、職責鏈模式、中

Go # 設計模式(三)關閉應用

// WaitSignal awaits for SIGINT or SIGTERM and closes the channel func WaitSignal(stop chan struct{})

使用Adapter設計模式打造一個流式佈局FlowLayout

流式佈局可以說是在各種軟體中的出場率都很高的一個佈局方式,被廣泛使用,像一些關鍵字搜尋,標籤等等的場景,更是隨處可見,今天我們就來手把手打造一個FlowLayout。 FlowLayout由於是以一個容器的身份存在的,所以其需要繼承的是ViewGroup而不是

重構設計模式---2016最後一篇博文,也是這一年的心得。

重構是逐步改進程式碼和架構的過程,也是不斷嘗試的過程。 重構是在不修改或少量修改程式碼的外部行為的情況下,對其內部結構進行調整的過程;重構過程包括程式碼結構優化、演算法的優化,甚至一個變數的使用優化。 在軟體開發中,經常會發現一些這樣或那樣的問題,這時,我們

設計模式在遊戲中的應用--建造者模式(九)

建造者模式(Builder Pattern):將一個複雜物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示。建造者模式是一種物件建立型模式。通過這個定義,我們可以得出建造者是一種建立型模式,也就是說建造者模式的輸出是一個物件,也就是UML類圖中的pr

軟體重構設計模式培訓筆記

1.TDD 測試驅動開發:每次完成一個功能,測試成功後才繼續下一步開發。 這種開發模式特別適合重構,因為重構在不斷的修改原始碼,為了保證修改沒有改變原來的表現,所以沒完成一次修改都要測試一次。

設計模式在遊戲中的應用--外觀模式(八)

外觀模式(Facade),為子系統中的一組介面提供一個一致的介面,定義一個高層介面,這個介面使得這一子系統更加容易使用。外觀模式相當於KFC裡面的套餐,大多數人去FKC吃中飯,本質其實就是為了填飽肚子,消費者需要主食、飲料和小吃,有了各種套餐之後,消費者去KFC

詳解設計模式在Spring中的應用

三種 apache 運用 ebp tty int() 包裝 rand 錄像 設計模式作為工作學習中的枕邊書,卻時常處於勤說不用的尷尬境地,也不是我們時常忘記,只是一直沒有記憶。 今天,在IT學習者網站就設計模式的內在價值做一番探討,並以spring為例進行講解,只有領略了

幾種常見設計模式在專案中的應用<Singleton、Factory、Strategy>

一、前言   前幾天閱讀一框架文件,裡面有一段這樣的描述 “從物件工廠中………” ,促使寫下本文。儘管一些模式簡單和簡單,但是常用、有用。   結合最近一個專案場景回顧一下里面應用到的一些模式<Singleton、Factory、Strategy>。   示例程式碼:https://github.

研磨設計模式之迭代器業務場景

場景描述 專案客戶方收購了一家小公司,這家小公司有自己的工資系統,客戶方的工資系統內部採用List來記錄工資列表,新收購的小公司的工資系統內部採用陣列來記錄工資列表,整合兩個系統的工資表資料 已有系統程式碼示例 一個統一了的工資描述模型 /**