重構優化設計模式應用~一個榨汁機應用場景示例
現在有這樣一個需求,通過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來記錄工資列表,新收購的小公司的工資系統內部採用陣列來記錄工資列表,整合兩個系統的工資表資料
已有系統程式碼示例
一個統一了的工資描述模型
/**