建造者模式(11)

来源:http://www.cnblogs.com/xiaomowang/archive/2017/01/22/6322026.html
-Advertisement-
Play Games

今天,我們來講一下建造者模式。 一、案例 我們來用winform畫一個小人,一個頭,一個身體,兩隻手,兩條腿。 我們一般想到的代碼如下: 運行的效果: 嗯,好,下麵,我們再畫一個稍微胖一點的小人。 代碼如下: 運行效果如下 咦,我們好像少花了條腿哦。 哈哈,像這樣粗心的情況我們經常出現 二、演繹 1 ...


今天,我們來講一下建造者模式。

一、案例

我們來用winform畫一個小人,一個頭,一個身體,兩隻手,兩條腿。

我們一般想到的代碼如下:

 

 1         /// <summary>
 2         /// 畫小人
 3         /// </summary>
 4         /// <param name="sender"></param>
 5         /// <param name="e"></param>
 6         private void pictureBox1_Paint(object sender, PaintEventArgs e)
 7         {
 8             Graphics gThin = e.Graphics;
 9             Pen p = new Pen(Color.Black, 2);
10             gThin.DrawEllipse(p, 50, 20, 30, 30);
11             gThin.DrawRectangle(p, 60, 50, 10, 50);
12             gThin.DrawLine(p, 60, 50, 40, 100);
13             gThin.DrawLine(p, 70, 50, 90, 100);
14             gThin.DrawLine(p, 60, 100, 40, 150);
15             gThin.DrawLine(p, 70, 100, 85, 150);
16         }

運行的效果:

嗯,好,下麵,我們再畫一個稍微胖一點的小人。

代碼如下:

 1         private void pictureBox2_Paint(object sender, PaintEventArgs e)
 2         {
 3             Graphics gThin = e.Graphics;
 4             Pen p = new Pen(Color.Red, 2);
 5             gThin.DrawEllipse(p, 50, 20, 30, 30);
 6             gThin.DrawEllipse(p, 45, 50, 40, 50);
 7             gThin.DrawLine(p, 50, 50, 30, 100);
 8             gThin.DrawLine(p, 80, 50, 100, 100);
 9             gThin.DrawLine(p, 60, 100, 45, 150);
10         }

運行效果如下

咦,我們好像少花了條腿哦。

哈哈,像這樣粗心的情況我們經常出現

二、演繹

1、第一步演繹

 1     /// <summary>
 2     /// 建造瘦小人的類
 3     /// </summary>
 4     class PersonThinBuilder
 5     {
 6         private Graphics _g;
 7         private Pen _p;
 8 
 9         public PersonThinBuilder(Graphics g, Pen p)
10         {
11             this._g = g;
12             this._p = p;
13         }
14         /// <summary>
15         /// 建造小人
16         /// </summary>
17         public void Build()
18         {
19             _g.DrawEllipse(_p, 50, 20, 30, 30);
20             _g.DrawRectangle(_p, 60, 50, 10, 50);
21             _g.DrawLine(_p, 60, 50, 40, 100);
22             _g.DrawLine(_p, 70, 50, 90, 100);
23             _g.DrawLine(_p, 60, 100, 40, 150);
24             _g.DrawLine(_p, 70, 100, 85, 150);
25         }
26     }

客戶端

1         private void pictureBox1_Paint(object sender, PaintEventArgs e)
2         {
3             Pen p = new Pen(Color.Black);
4             Graphics gThin = e.Graphics;
5             PersonThinBuilder ptb = new PersonThinBuilder(gThin, p);
6             ptb.Build();
7         }

我們進行了第一步的改革,看了一下代碼,將客戶端的畫小人的過程一直到了一個類中,客戶端只需要調用這個類就可以了,但是,這仍然沒有解決我們上面提到的問題,如果我們要畫一個胖一點的小人,我們還需要建一個類,然後再寫一遍創建過程,很難保證落下什麼東西(比如:少了一隻手也說不定哦)

好,那麼我們到底該如何解決呢?

下麵就是我們將要介紹的 建造者模式。

 建造者模式:將一個對象複雜的構建,與它的表示分離,使得同樣的構建,可以創建不同的表示。

如果我們使用了建造者模式,那麼,用戶只需要指定建造的類型就可以得到他們了,而具體的建造的細節和過程就不需要知道了。

那麼,我們畫小人的案例該怎樣使用建造者模式呢?我們一步步來分析。

畫小人,都需要畫,頭、身體、左手、右手、左腿、右腿。

好,下麵呢,我們就先來定義一個抽象的畫小人的類,將這個過程固定住,不讓任何人遺忘當中的任何一步。

 1     abstract class PersonBuilder
 2     {
 3         protected Graphics G;
 4         protected Pen P;
 5 
 6         protected PersonBuilder(Graphics g, Pen p)
 7         {
 8             G = g;
 9             P = p;
10         }
11 
12         public abstract void BuildHead();
13         public abstract void BuildBody();
14         public abstract void BuildArmLeft();
15         public abstract void BuildArmRight();
16         public abstract void BuildLegLeft();
17         public abstract void BuildLegRight();
18     }

然後,我們需要建造一個瘦一點的小人,我們可以讓瘦一點的小人去繼承這個抽象類。那麼這個類就必須重寫抽象類中的方法了,要不編譯不通過的。所以,畫小人就不會丟三落四了。

 1     class PersonThinBuilder : PersonBuilder
 2     {
 3         public PersonThinBuilder(Graphics g, Pen p) : base(g, p)
 4         {
 5         }
 6 
 7         public override void BuildHead()
 8         {
 9             G.DrawEllipse(P, 50, 20, 30, 30);
10         }
11 
12         public override void BuildBody()
13         {
14             G.DrawRectangle(P, 60, 50, 10, 50);
15         }
16 
17         public override void BuildArmLeft()
18         {
19             G.DrawLine(P, 60, 50, 40, 100);
20         }
21 
22         public override void BuildArmRight()
23         {
24             G.DrawLine(P, 70, 50, 90, 100);
25         }
26 
27         public override void BuildLegLeft()
28         {
29             G.DrawLine(P, 60, 100, 40, 150);
30         }
31 
32         public override void BuildLegRight()
33         {
34             G.DrawLine(P, 70, 100, 85, 150);
35         }
36     }

同理,胖子小人類也用上面的方式,繼承抽象類,代碼差不多,就不在寫了。

這樣就完事了嗎?如果完事了的話,那麼我在客戶端調用的時候,還是需要調用類裡面的方法,萬一哪一個方法沒有調用,也就會出現丟三落四的情況了,這根本沒有解決問題呀。所以,到這裡,我們還沒有完事呢。

建造者模式還有一個非常重要的類,指揮者類。指揮者類是用來控制建造過程的,同時它也是隔離用戶與建造過程的關聯的。

好,下麵我們來寫一個指揮者類。

 1     class PersonDirector
 2     {
 3         private PersonBuilder pb;
 4         //用戶告訴指揮者,我需要什麼樣的小人
 5         public PersonDirector(PersonBuilder pb)
 6         {
 7             this.pb = pb;
 8         }
 9         //根據用戶的選擇建造小人
10         public void CreatePerson()
11         {
12             pb.BuildHead();
13             pb.BuildBody();
14             pb.BuildArmLeft();
15             pb.BuildArmRight();
16             pb.BuildLegLeft();
17             pb.BuildLegRight();
18         }
19     }

這樣,指揮者類寫好了。其實指揮者類就是根據用戶的選擇,來一步一步的建造小人,而建造的過程在指揮者裡面已經完成了,用戶就不需要知道了。

那麼,客戶端就是這樣的了。

1         private void pictureBox1_Paint(object sender, PaintEventArgs e)
2         {
3             //瘦小人
4             PersonBuilder pb = new PersonThinBuilder(e.Graphics, new Pen(Color.Black));
5             //告訴建造者,我要創建一個瘦小人
6             PersonDirector pd = new PersonDirector(pb);
7             //開始創建
8             pd.CreatePerson();
9         }

ok,這樣就成功的將我們的案例用建造者模式構建出來了。

好了,建造者模式今天就講到這裡了,下篇博文我們將 觀察者模式


本系列將持續更新,喜歡的小伙伴可以點一下關註和推薦,謝謝大家的支持。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 網路基礎 協議的概念 什麼是協議 從應用的角度出發,協議可理解為“規則”,是數據傳輸和數據的解釋的規則。 假設,A、B雙方欲傳輸文件。規定: 第一次,傳輸文件名,接收方接收到文件名,應答OK給傳輸方; 第二次,發送文件的尺寸,接收方接收到該數據再次應答一個OK; 第三次,傳輸文件內容。同樣,接收方接 ...
  • 說明 關於Redis:一個基於鍵值對存儲的NoSQL記憶體資料庫,可存儲複雜的數據結構,如List, Set, Hashes。 關於Spring Data Redis:簡稱SDR, 能讓Spring應用更加方便配置和訪問Redis。 本工程基於spring boot ,spring data redi ...
  • 最近在複習Servlet,發現其中有很多細節方面的東西都沒有接觸到,只是學了大概 1.請求轉發和請求重定向的區別 2.輸入參數為中文時候的亂碼問題 3.Web工程中的目錄寫法 下麵分別闡述 1.請求轉發和請求重定向的區別 請求轉發: 請求重定向: 請求轉發是伺服器行為,本質上是一次請求,所以參數可以 ...
  • 讀取HeidiSQL 配置文件中的密碼 2017 1 21 5:42:01 codegay HeidiSQL是一款開源的SQL管理工具,用管理MYSQL,MSSQL 等資料庫, 很多管理工具都會把密碼存在本地,HeidiSQL也是的,但是只是經過非常簡單的編碼,所以我經過簡單的分析後就知道瞭解密的方 ...
  • 一、Spring是什麼? 二、具體描述Spring 三、搭建Spring環境 3. Spring的配置文件:一個典型的Spring項目需要創建一個或多個Bean配置文件,這些配置文件用於在Spring IOC容器中配置Bean。Bean的配置文件可以放在classpath下,也可以放在其他目錄下。 ...
  • bean的作用域 使用bean的 scope 屬性來配置bean的作用域 scope="singleton" : 預設是單例模式 即容器初始化創建bean實例,在整個容器的生命周期內只創建這一個bean; scope="prototype" : 原型的 ,即容器初始化時不創建bean的實例,而在每次 ...
  • 對彈幕功能主要利用環信來實現的,讀者也許對環信這個東西很陌生,請先自行瞭解這環信再來看這文章。 環信開發文檔:http://docs.easemob.com/im/400webimintegration/10webimintro 請大家看文檔看WebIM這個模塊,環信官網也提供了小程式的demo,建 ...
  • FFmpeg DXVA2解碼得到的數據使用surface來承載的,surface限制很多,如果能用紋理來渲染的話,那我們就可以充分開發D3D,比如可以用坐標變換來實現電子放大的功能,還可以用坐標變換來實現視頻圖像任意角度的旋轉等功能。而對於我來說,最重要的是紋理渲染可以使得解碼後的數據能夠用像素著色... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...