1. 程式人生 > 實用技巧 >一步一步學習c#的設計模式與一個專案——第1部分

一步一步學習c#的設計模式與一個專案——第1部分

內容 在第1部分中我們將學習哪些模式和概念? 介紹 設計模式VS架構模式VS架構風格 設計模式的定義 酷店專案:-一期 軟體架構是一種演進 什麼是實體? 第一步:-識別你的實體/物件 步驟2:-確定實體之間的關係 步驟3:-從一個公共類派生 的技術背景 三層架構——管理變更 三層VS三層 步驟4:-建立使用者介面 固體的S(單一責任原則) SRP同義詞關注分離(SOC) 分離需要抽象思維——建立介面 步驟6:- PIC模式用於解耦(簡單的工廠模式) 第7步:- RIP模式(用多型性替換IF) IOC有思想,DI有實現 所有在家庭:- SOC,SRP, IOC和DI 步驟8:-提高工廠類的效能 延遲載入工廠 家庭作業:-使用Lazy關鍵字自動載入懶惰 步驟10:-實現克隆(原型模式) 步驟11:-自動化簡單的工廠使用Unity 第12步:-抽象類-半定義的東西 步驟13:-通用工廠 步驟14:-驗證策略模式 消費並讓它活起來 下一部分是什麼? 在第1部分中我們將學習哪些模式和概念? RIP:-用多型替換IF。 簡單工廠:-移動“新”關鍵字在中央類。 延遲載入:-按需載入物件。 原型模式:-建立一個物件的克隆。 策略模式:-動態新增演算法。 IOC控制概念:-不必要的工作應該轉移到其他地方。 依賴注入實現IOC。 堅實的原則:- SRP和OCP涵蓋了堅實的原則。 介紹 在本文中,我們將學習如何使用c#語言實現設計模式和架構模式。我們不會一種模式一種模式地去做,而是拿一個示例專案,嘗試在相同的基礎上實現這些東西。 那麼,為什麼本文采用基於專案的方法,而不是基於例項的方法呢? 設計模式和架構模式是思維過程。思維過程無法用PPT、UML圖表等來解釋。您需要檢視程式碼,您需要感受它,將它與真實的專案場景對映到一起。 如果你在網際網路或書籍上看到大多數設計模式的文章都是用UML圖(不是所有的開發人員都理解UML)或者像Car, Tree, Human’s等這樣的例子來解釋的,這些例子並不能讓你覺得這些例子是真實的。 因此,讓我們拿一個示例專案需求,讓我們開始編碼和設計一個應用程式,並讓設計模式自然地沿著這個過程。 誤解1:對於一個好的架構來說,所有的設計模式都必須在一個專案中實現。 事實:-模式自然產生,完全按需。 在你開始一些沉重的事情之前的一個小笑話 面試官:-告訴我你在現實生活中在哪裡使用過設計模式。 應聘者:-只在面試的時候。 設計模式VS架構模式VS架構風格 誤解2:設計模式和架構模式是相同的。 事實:設計模式至少在虛擬碼級別,而架構模式在元件級別。 單詞“Pseudo”的意思:-大致看起來是這樣的。 我們看到很多人交替使用這些詞彙。但是它們的工作方式有很大的不同。 首先讓我們試著理解“模式”這個詞,然後我們再深入瞭解。 如果你明白pattern的簡單英語含義:-它們是重複發生的和可預測的事件。 例如,氣候變化遵循一種模式。一般來說(至少在印度是這樣),夏天之後是下雨,然後是寒冷。人類識別這些模式,以更好的方式組織自己。 同樣,在軟體世界中,出現的問題大多有特定的模式,許多開發人員已經解決了這些問題並提出瞭解決方案。後來,其中一些解決方案在一段時間內證明了它們的價值,併成為該問題模式的標準解決方案。 例如,如果你想排序,那麼你有時間測試的演算法,如氣泡排序,插入排序等。 設計模式是虛擬碼級解決方案,而體系結構模式是在元件級定義的30,000英尺級解決方案。簡單地說,如果有人說“X”是一種設計模式,那麼就需要程式碼,如果有人說“Y”是一種架構模式,那麼就需要某種元件級的框圖。 建築風格是一種思維過程,一種原則,它只出現在一行之內。例如,REST是一種我們重視HTTP的架構風格。 下面是他們各自的一些例子。 設計模式工廠,迭代器,單例架構模式mvc, MVP, mvvm架構風格rest, SOA, IOC 設計pattern定義 在我們繼續專案之前,讓我們試著給設計模式下一個定義,之後我們將定義體系結構模式。 如果你看到設計模式的官方定義,它是這樣的:- “反覆出現的架構問題的久經考驗的解決方案”。 但是坦白地說,當您開始實現和閱讀設計模式時,這個定義並不適用。有時你會發現設計模式完全是關於好的面向物件程式設計(OOP)原則。 所以讓我根據我的理解和經驗來定義我的定義。我可以保證,當我們開始執行所有的設計模式時,這個定義會更加清晰。 “針對反覆出現的OOP問題的久經考驗的解決方案”。 在這次訪談中,GOF團隊自己也重複了這個定義。 誤解3:設計模式讓你成為一個完整的架構師。 事實:設計模式是一個建築師的事情。它會讓你的OOP更好。 實際上,設計模式只是讓你在面向物件(OOP)方面變得更好,這是成為架構師的一個方面。但這並不是成為建築師的唯一途徑。我們也可以說設計模式是理解面向物件方案的一種方式。 因此,讓我們不要浪費更多的時間,從一個典型的軟體需求開始 酷店專案:-一期 “酷店”是一家大型零售購物中心,在孟買和浦那市擁有連鎖購物中心。公司管理層希望為他們的零售商店提供一個簡單的客戶管理系統,具有以下功能。公司決定分階段啟動這個專案。 第一階段,他們只想獲取客戶資訊。以下是更詳細的要求:- 應用程式現在將捕獲5個欄位:客戶名稱、電話號碼、賬單金額、賬單日期和客戶地址。在階段1中收集了兩種型別的客戶資料。一個是引導者,另一個是顧客。lead指的是來到酷店卻什麼也不買的人。他只是問了問就走了。顧客就是來商店買東西的人。客戶實際上是在進行金融交易。當它是一個領先的客戶名稱和電話號碼是強制性的,但對於客戶,所有欄位都是強制性的。系統應該有無縫新增新驗證規則的規定,這些驗證規則應該是靈活的和可重用的,可以應用到系統中。系統應該能夠顯示,新增,更新和刪除客戶資料。目前系統將使用SQL Server和ADO。NET作為資料層技術。但在接下來的幾個月裡,我們將把這個資料層遷移到實體框架。遷移應該是無縫的,不需要跨系統進行很多更改。系統應該有能力取消在螢幕上做的任何修改。因此,如果客戶正在編輯一條記錄,並且更改了一些值,那麼他應該有機會恢復到舊值。 軟體架構是一種演進 誤解4:-架構應該在第一時間就完美無誤。 事實:——建築是一種進化。從小處開始,然後不斷改進。 對於新架構師來說,這是他們最大的信條之一。軟體架構會自然地演進,模式也會在這個過程中逐漸衰落,最終形成最終的結果。 許多人試圖通過一個接一個的程式碼和一個接一個的模式來學習設計和架構模式。這種學習模式是非常有害的,因為你只是看到一些學術程式碼,但它永遠不會成為你自然的一部分。 學習設計模式的最佳方法是通過做一個專案來觀察整個演變過程,然後讓模式在整個過程中自然地逐漸消失。 因此,我們不會學習一個接一個的模式,我們只會嘗試構建上面的專案,隨著模式的出現,我們會自然而然地指出模式。 因此,讓我們首先從簡單的OOP概念、類、物件和隨需而來的模式開始。 什麼是實體? 我們需要做的第一件事是識別實體。讓我們來理解實體在英語中的確切含義。 實體是你在現實世界中看到的事物。這些可以唯一地標識。例如,一個人,地點,事物等等都是實體的例子。 在OOP世界中,實體的技術名稱是物件。所以我們在這篇文章中可以互換使用這兩個詞。 第一步:-識別你的實體/物件 思維過程1:-軟體程式碼應該複製真實的世界,真實的人。如果你是一個會計在你的軟體程式碼中,你應該有一個叫做會計的實體。 軟體應用程式的建立是為了使真實世界和真實的人自動化。因此,如果你的軟體程式碼複製了現實世界的物件,你可以管理你的軟體在一個更好的和可控的方式。 這就是面向物件程式設計的全部內容。OOP說你的鱈魚e應該反映你的域行為和域的實體。 域是指業務單元,其規則和它是如何工作的。 所以第一步是識別實體/物件從上面的要求。所以從頂部下面的要求確定名詞:- 孟買浦那客戶帶來涼爽的商店 思維過程2:名詞成為實體和動詞成為實體的行為。代詞成為這些實體的屬性和行為。 許多建築師遵循實踐之一是識別名詞、代詞和動詞。這些名詞然後分析和確定為物件/實體。但是要小心使用此方法,因為你可以得到多餘的名詞和動詞。所以只保留那些名詞和動詞與最終的軟體系統。 如果你回顧上述識別實體現在“孟買”和“普”是城市的名字和與軟體沒有直接聯絡。“CoolShop”,這是商場的名稱也沒有直接聯絡。 所以此刻唯一有用的實體在階段1是“領導”和“客戶”。我們將新增、更新、刪除資料的客戶。 現在這樣的實體來住在你的電腦,你需要的程式碼和邏輯。所以我們需要某種形式的一個模板,我們可以編寫這段程式碼中,這就是我們術語“類”。這個類將thenbe例項化建立物件和實體在你的電腦。 OOP過程分為三個階段:- 模板建立:建立類和編寫邏輯的類。這些類的例項化:建立實體/物件並將他們住在RAM /電腦。執行:與這些物件來實現軟體功能。 現在作為一名開發人員你會遇到常見/重複designproblems在所有這三個階段。OOP設計模式解決方案問題在所有這三個階段。設計模式分為三類,它們覆蓋這些階段如下:- OOP階段設計模式類別模板結構設計模式/類的建立問題。建立型設計模式例項化問題。執行時行為設計模式的問題。 讓我們建立兩個類一個是領導,另一個是客戶。 下面是對於兩個類的程式碼。 注意:——我從這裡可以看到人表裡不一的擔憂我的下面的程式碼。不久我將解決他們,繼續讀。 隱藏,複製Code

namespace CustomerLibrary
{
public class Lead
    {
        public string LeadName { get; set; }
        public string PhoneNumber { get; set; }
        public string PhoneNumber { get; set; }
        public decimal BillAmount { get; set; }
        public DateTime BillDate { get; set; }
        public string Address { get; set; }
    }
    public class Customer
    {
        public string CustomerName { get; set; }
        public string PhoneNumber { get; set; }
        public decimal BillAmount { get; set; }
        public DateTime BillDate { get; set; }
        public string Address { get; set; }
    }
}

步驟2:確定實體之間的關係 現實世界中實體相互作用,他們之間的關係。我們的下一步是確定實體之間的關係。如果你想象的關係,存在於現實世界中,他們是主要的兩種型別“是一個”和“有”。 例如兒子”是一個“孩子他父親和兒子”有一個“汽車的他的父親。”是一個“更多的是父母的孩子的關係(層次),而“有”更多的是一種利用關係(聚合、組合和相關)。 如果你讀的要求第二,這顯然意味著:- “鉛是一種型別的客戶用更少的驗證”。 現在我們班變成了如下所示的程式碼。“領導”是一個子類繼承了從“客戶”類。 隱藏,複製Code

public class Customer
{
        public string CustomerName { get; set; }
        public string PhoneNumber { get; set; }
        public decimal BillAmount { get; set; }
        public DateTime BillDate { get; set; }
        public string Address { get; set; }
}
public class Lead : Customer
{

}

“客戶”實體客戶的名字,電話號碼,金額和賬單日期是強制性的。以下程式碼中,我們建立了一個簡單的“驗證”方法檢查上面的所有屬性。 最重要的一點是,“驗證”方法是由虛擬。這新類可以覆蓋驗證邏輯。 隱藏,複製Code

public class Customer
    {
// All properties are deleted for simplification
        public virtual void Validate()
        {
            if (CustomerName.Length == 0)
            {
                throw new Exception("Customer Name is required");
            }
            if (PhoneNumber.Length == 0)
            {
                throw new Exception("Phone number is required");
            }
            if (BillAmount > 0)
            {
                throw new Exception("Bill is required");
            }
            if (BillDate >= DateTime.Now)
            {
                throw new Exception("Bill date  is not proper");
            }
        }
    }

下一步是建立一個“領導”類繼承自“客戶”類和覆蓋驗證方法。討論了“鉛”類將限制較少,因為它只需要姓名和電話號碼。下面是程式碼覆蓋客戶類少驗證。 隱藏,複製Code

public class Lead : Customer
    {
        public override void Validate()
        {
            if (CustomerName.Length == 0)
            {
                throw new Exception("Customer Name is required");
            }
            if (PhoneNumber.Length == 0)
            {
                throw new Exception("Phone number is required");
            }
        }}

思維過程3:——“是一個”的關係是一個家長孩子的關係,而“有”是一個使用關係。 步驟3:源於一個共同的階級 如果你讀要求4號表示,系統應該能夠新增新的客戶型別的明天。 按這個要求我們班設計看起來不符合邏輯的。一個邏輯的方法是,應該有一個定義的“一半”類與所有屬性和“驗證”方法應該是空的(半)定義的。這個空的方法可以被子類覆蓋取決於他們的行為。 換句話說,我們應該有某種的基類我們可以得到客戶和領導階級。 下面是客戶基礎類和所有屬性和“驗證”方法保持空定義它的子類。 隱藏,複製Code

public class CustomerBase
{
        public string CustomerName { get; set; }
        public string PhoneNumber { get; set; }
        public decimal BillAmount { get; set; }
        public DateTime BillDate { get; set; }
        public string Address { get; set; }
        public virtual void Validate()
        {
         // Let this be define by the child classes 
        }
}

注意:——一些高階的人讀這篇文章已經尖叫,使這類“抽象”。是的,很快。我想推遲進一步ca理解抽象類的實時使用。 因此,現在如果我們想建立一個customer類,我們只需從基customer類繼承並放入驗證即可。 隱藏,複製Code

public class Customer : CustomerBase
    {
        public override void Validate()
        {
            if (CustomerName.Length == 0)
            {
                throw new Exception("Customer Name is required");
            }
            if (PhoneNumber.Length == 0)
            {
                throw new Exception("Phone number is required");
            }
            if (BillAmount > 0)
            {
                throw new Exception("Bill is required");
            }
            if (BillDate >= DateTime.Now)
            {
                throw new Exception("Bill date  is not proper");
            }
        }
    }

如果我們想建立一個只驗證姓名和電話號碼的Lead類,我們可以再次從“CustomerBase”類繼承並相應地編寫驗證。 隱藏,複製Code

public class Lead : CustomerBase
    {
        public override void Validate()
        {
            if (CustomerName.Length == 0)
            {
                throw new Exception("Customer Name is required");
            }
            if (PhoneNumber.Length == 0)
            {
                throw new Exception("Phone number is required");
            }
        }
    }

的技術背景 以上定義的三個類都以“的形式儲存在硬碟中。CS”擴充套件。現在需要做兩件事:- 一些UI應該呼叫這些類,把這些實體放到RAM中。第二,一旦終端使用者完成了他的操作,我們需要將這些實體儲存到硬碟中。 換句話說,我們的實體需要IT基礎設施來執行。它需要一個UI基礎設施(WPF、Flash、HTML)用於呼叫,需要一個持久化基礎設施(Sql Server、Oracle)用於儲存到硬碟。 如果你把這些情況的可檢視片和技術背景放在一起,它看起來就像這樣。所以我們可以有消費者上下文,可以是HTML, WPF, Windows等形式。我們可以有持久的上下文,它可以是一個檔案或RDBMS,如SQL Server, Oracle等。 有了以上的想法,我們以三種類型的部分結束:- 消費者部分,主要是UI。包含類和業務邏輯的域部分。持久部分,除了你的RDBMS,檔案等。 思維過程4:-當你想象一個類總是他們在這兩個技術上下文和業務實體上下文。 三層架構——管理變更 軟體架構的試金石測試是在變更期間進行的。當你在一個地方改變,如果你在很多地方改變,這意味著這是一個糟糕的架構的標誌。 因此,為了避免在所有地方都發生變化,我們需要做出適當的分層和劃分,並在這些分層上放上類似性質的責任。因此,正如在技術上下文中所討論的,我們目前至少有三個部分,UI、領域/業務層和資料層。 在同一個專案中,我們為UI部分新增一個簡單的Windows UI。 我們需要類庫一個用於“資料訪問”,另一個用於客戶實體。 所以現在你的解決方案看起來如下圖所示。三種不同的專案層次。 那麼,分層是如何幫助我們更好地管理變化的呢?因為我們已經將專案劃分為邏輯層,所以很容易知道在哪個層中必須進行哪些更改。例如,如果我們想升級資料訪問層,我們只需要改變第三層,如果我們想從一種UI技術轉移到另一種,我們需要改變UI層,等等。 上述架構稱為“三層架構”。 思維過程5:-總是把你的專案分成邏輯層次,每一層次都應該有一些獨特的責任。 三層VS三層 架構世界中一個令人困惑的術語是“層”架構與“層”架構。在三層架構中,我們只有邏輯分離。在三層中,所有這三個層都部署在獨立的物理機器上。 步驟4:-建立使用者介面 在UI層中,我們為UI放置了必要的控制元件。 在這個UI層中,我們添加了對“Customer”庫的引用,在下拉選單中,我們建立了一個“Lead”物件或“Customer”物件。 隱藏,複製Code

private void btnAdd_Click(object sender, EventArgs e)
{
            CustomerBase custbase = null;
            if (cmbCustomerType.SelectedIndex == 0)
            {
                custbase = new Lead();
            }
            else
            {
                custbase = new Customer();
            }
            custbase.CustomerName = txtCustomerName.Text;
            custbase.Address = txtAddress.Text;
            custbase.PhoneNumber = txtPhoneNumber.Text;
            custbase.BillDate = Convert.ToDateTime(txtBillingDate.Text);
            custbase.BillAmount = Convert.ToDecimal(txtBillingAmount.Text);
}

所以你能猜到上面的程式碼有什麼問題嗎?想? ?。 好的,我們在下面圈出了這個問題來幫助你理解這個問題。問題是“改變”。正如在需求4中定義的那樣,未來可以新增新的客戶型別。因此,當新增新的客戶型別時,我們需要更改UI程式碼,或者讓我來推斷許多這樣的UI螢幕。 記住我們說過的,一個好的架構是這樣的架構當我們在一個地方改變時,我們不需要在所有地方都改變。 固體的S(單一責任原則) 是時候談談堅實的原則了。如果我們遵循這些原則,我們的OOP就會更好。 單一責任原則(SRP)。開閉原則(OCP)利斯科夫替代原則(LSP)介面分離原則(ISP)依賴反演原則。 現在讓我們不要談論所有的SOLID原則,如果你想現在就瞭解它,你可以閱讀這篇c# SOLID文章,它只討論SOLID原則。 現在讓我們只集中在堅實的“S”,即單一責任原則(SRP)。 SRP說一個類應該一次只做一個工作,而不是不相關的事情。如果你看到UI,它應該做佈局,視覺,輸入等等。但現在他正在建立一個“客戶”物件,這不是他的職責。 換句話說,UI正在處理多種職責,這使得類在以後變得更加複雜和難以維護。 思考過程6:堅持堅定的原則當你在做設計。 SRP同義詞的關注點分離(SOC) 的一個同義詞SRP SOC -分離的問題。分離關注點原則說,一個類應該只有他的擔憂和任何不必要的擔憂應該搬到其他類。例如在這種情況下,介面不應該直接建立“客戶”物件。 所以下次當你看到SOC你可以認為這是一個同義詞SRP反之亦然。 注意:——我不知道先SOC還是SRP的歷史。但他們肯定有相同的目標。 第五步:建立介面——分離需要抽象思維 為了實現解耦的UI和客戶型別,使用者介面必須看到客戶型別在一種抽象的方式而不是處理具體類。 抽象:這是一個OOP原則,我們只顯示消費者必要的事情。 UI應該只與純粹的定義而不是具體類實現。這就是介面來的照片。幫助你建立純定義介面。UI將指出這些純粹的定義,而不是擔心在後臺實現類。 讓我們建立一個單獨的類庫使用一個名稱“ICustomerInterface”相同的解決方案。這個介面我們將參考在UI中。下面是介面如何“ICustomer”的樣子,只是空定義和空方法。 隱藏,複製Code

public interface ICustomer
{
         string CustomerName { get; set; }
         string PhoneNumber { get; set; }
         decimal BillAmount { get; set; }
         DateTime BillDate { get; set; }
         string Address { get; set; }
         void Validate();

}

現在整個解決方案從架構的角度看起來如下所示。現在的介面之間的調停人UI和客戶類庫。 所以,如果你現在看到它變成了我們的客戶程式碼如下所示。 隱藏,複製Code

ICustomer icust = null;
if (cmbCustomerType.SelectedIndex == 0)
{
icust = new Lead();
}
else
{
icust = new Customer();
}
icust.CustomerName = txtCustomerName.Text;
icust.Address = txtAddress.Text;
icust.PhoneNumber = txtPhoneNumber.Text;
icust.BillDate = Convert.ToDateTime(txtBillingDate.Text);
icust.BillAmount = Convert.ToDecimal(txtBillingAmount.Text);

但實際上事情並沒有改變。如果我們新增一個新的類我們仍然需要建立具體實現類的物件。 所以我們需要更多的東西,看下一步的解決方案。 思維過程7:介面的主要工作是互相分離的類。 步驟6:圖片模式解耦(簡單工廠模式) 圖片的縮略詞是“多型性+介面+集中物件建立” 如果你密切關注程式碼的你會得到的核心原因仍然不是脫鉤。因為所有的“新”字。“新”字兩個系統的主要原因之一是緊密耦合的。 所以第一步是擺脫“新”字從消費者端。讓我們開始的“新”字中央工廠類。 所以我們增加了一個新的類庫專案稱為“FactoryCustomer”下面的程式碼。 隱藏,複製Code

public class Factory
{
        public ICustomer Create(int CustomerType)
        {
            if (CustomerType == 0)
            {
                return new Lead();
            }
            else
            {
                return new Customer();
            }
        }
}

它有一個簡單的“工廠”類的建立方法。這種“創造”方法接受一個數字值,根據數值建立一個“領導”物件或一個“客戶”物件。但這種“創造”的專業函式,它返回“ICustomer”介面型別。 現在控制檯應用程式UI使用建立物件的“工廠”,因為“創造”函式返回“ICustomer”型別的UI並不需要擔心具體客戶類的後端。 隱藏,複製Code

ICustomer icust = null;
Factory obj = new Factory();
icust = obj.Create(cmbCustomerType.SelectedIndex);

在上面的程式碼中可以看到沒有參考具體類的“領導”或“客戶”型別,顯示UI不是與核心客戶庫類。 如果你想知道為什麼我們叫類“工廠”。在現實世界中意味著創造(製造)事物的一個實體,我們的“工廠”類正是這樣建立物件。所以名字同樣有著密切聯絡。 思維過程8:——“新”字是緊密耦合的罪魁禍首。 第七步:把模式(如果換成多型性) 如果你看步驟6的程式碼我們剛剛通過了美元。“如果”條件是在UI中部分是現在工廠哪個更好的一部分,但在現實中,“如果”條件仍然存在。只是它一直從UI搬到工廠。 集中物件建立的優勢是,如果我們在很多地方使用具體類和客戶在其他地方我們不需要改變。 現在讓我們開始思考我們如何消除“如果”條件。你一定聽說過以下最佳實踐宣告:- “如果有多型性,這意味著如果你看到很多條件多型的好處不是剝削”。 刪除“如果”條件過程分為三個步驟:- 步驟1:建立一個列表“ICustomer”的集合。 隱藏,複製Code

private List<icustomer> customers = new List<icustomer>();</icustomer></icustomer>

步驟2:在建構函式中載入型別的客戶類像鉛和客戶。 隱藏,複製Code

public Factory()
        {
            customers.Add(new Lead());
            customers.Add(new Customer());
        }

步驟3:建立方法看看通過索引列表,返回型別的客戶。因為多型性的具體客戶類會自動型別(一個通用的介面。 隱藏,複製Code

public ICustomer Create(int CustomerType)
        {
            return customers[CustomerType];
        }

下面是更改的工廠類的完整程式碼。 隱藏&,複製Code

public class Factory
{
        private List<icustomer> customers = new List<icustomer>();
        public Factory()
        {
            customers.Add(new Lead());
            customers.Add(new Customer());
        }
        public ICustomer Create(int CustomerType)
        {
            return customers[CustomerType];
        }
}
</icustomer></icustomer>

注意:——把最大的約束模式,具體類應該在繼承層次結構和具有相同的簽名。多型和繼承是一個強制性的特性把模式存在。 思維過程9:-在多型如果可以換成動態多型集合。 模式1把模式:如果你有多型性的優勢,你會看到大量的IF條件,有很好的機會,你可以用一個簡單的替換,如果條件查詢集合。這種模式行為範疇。 國際奧委會認為,DI實現 國際奧委會是一個思想或者說我可以說實體的原則無關的工作應該搬出去的地方。再次讀到完整形式:控制反轉或者我們可以非常具體的說UNWANTEDcontrol其他實體的反演。 如果你看到在上面的場景中,我們移動或我將說我們倒“客戶”的不必要的責任物件建立UI的“工廠”類。 現在國際奧委會原則可以通過多種方式來實現,依賴注入,代表等等。 為了實現這一思維過程我們使用了“工廠”類。如果你看到從工廠類的角度來看我們注入一個物件的UI。所以UI需要注入的工廠類的物件。迪是一個注入依賴物件的過程從一個單獨的實體來實現解耦。 所有的家庭:- SOC, SRP,國際奧委會和DI 如果你看到密切SOC, SRP和奧委會幾乎是同義詞和這些原則可以實現通過使用DI,事件,代表,建構函式注入,服務定位器等。所以對我來說SOC, SRP和奧委會看起來都同義詞。 我鼓勵你看這個視訊解釋了國際奧委會和DI幾乎。 第八步:提高效能的工廠類 在上面的建築工廠類將執行很差如果我們有很多具體的物件 明天如果我們一次又一次地建立工廠例項將導致大量的記憶體消耗。 所以如果我們能有一個與所有具體工廠類的例項物件載入一次,真的會提高效能。這一例項可以用於滿足所有客戶的需求例項。 為了單一例項複製我們需要做以下:- 宣告為靜態的類。宣告的型別列表將被儲存為靜態的。最後建立函式也應該定義靜態,這樣它可以訪問靜態變數。 隱藏,複製Code

public static class Factory
    {
        private static List<icustomer> customers = new List<icustomer>();
        static Factory()
        {
            customers.Add(new Lead());
            customers.Add(new Customer());
        }
        public static ICustomer Create(int CustomerType)
        {
            return customers[CustomerType];
        }
    }
</icustomer></icustomer>

工廠在客戶端呼叫程式碼變得簡單得多了。 隱藏,複製Code

icust = Factory.Create(cmbCustomerType.SelectedIndex);

模式2簡單工廠模式:通過集中物件建立和返回一個通用介面參考,有助於減少變化時變化應用於應用程式。這瀑布在建立類別。 這種模式不應被混淆與四人幫的工廠模式。工廠模式是簡單工廠模式的基礎。 步驟9:-延遲載入的工廠 還其他偉大的事情我們可以做這裡的工廠是按需載入物件。如果你看到現在的物件載入不管你希望他們。我們只是載入即時,換句話說,當我們想要的物件我們載入它們。 所以延遲載入轉換上面的工廠是一個兩步過程:- 步驟1:使物件集合型別空。不載入它們。 隱藏,複製Code

private static List<icustomer> customers = null;</icustomer>

步驟2:建立函式將首先檢查物件是否為空然後載入它,否則只是集合中查詢。 隱藏,複製Code

public static ICustomer Create(int CustomerType)
        {
            if (customers == null)
            {
                LoadCustomers();
            }
            return customers[CustomerType];
        }

下面是延遲載入的完整程式碼。 隱藏,複製Code

public static class Factory
{
        private static List<icustomer> customers = null;

        private static void LoadCustomers()
        {
            customers = new List<icustomer>();
            customers.Add(new Lead());
            customers.Add(new Customer());
        }
        public static ICustomer Create(int CustomerType)
        {
            if (customers == null)
            {
                LoadCustomers();
            }
            return customers[CustomerType];
        }
}
</icustomer></icustomer>

模式3延遲載入:這是我們載入物件建立型設計模式,只有當我們需要它。延遲載入的反面是立即載入。 家庭作業:自動化使用懶字延遲載入 懶惰的設計模式可以自動化,使簡單的通過使用c#懶惰的關鍵字。我將作為你們的家庭作業。看到下面的youtube視訊理解c#延遲載入概念,然後嘗試您的自定義程式碼替換為c#懶惰的關鍵字。 下面是使用c#編寫的程式碼懶惰的關鍵字。 隱藏,複製Code

public static class Factory
    {
        private static Lazy<list<icustomer>> customers = null;
        public Factory()
        {
            customers = new Lazy<list<icustomer>>(() => LoadCustomers());
        }
        private  List<icustomer> LoadCustomers()
        {
            List<icustomer> custs = new List<icustomer>();
            custs.Add(new Lead());
            custs.Add(new Customer());
            return custs;
        }
        public static ICustomer Create(int CustomerType)
        {
            return customers.Value[CustomerType];
        }
    }
</icustomer></icustomer></icustomer></list<icustomer></list<icustomer>

第十步:實現克隆(原型模式) 現在上面的工廠模式類有一個缺陷,你能猜出這是什麼嗎?。 隱藏,複製Code

icust = Factory.Create(0);

現在為什麼會返回相同的例項,因為工廠模式是指向相同的例項的集合。這是災難性的,因為工廠的目的是建立新例項,而不是返回相同的例項。 所以我們需要某種機制,而不是返回相同的物件應該返回一個克隆的物件,一個由VAL副本。這就是原型模式圖片。 所以第一步是定義一個“ICustomer”介面中的“克隆”方法。 隱藏,複製Code

public interface ICustomer
{
         string CustomerName { get; set; }
         string PhoneNumber { get; set; }
         decimal BillAmount { get; set; }
         DateTime BillDate { get; set; }
         string Address { get; set; }
         void Validate();
         ICustomer Clone(); // Added an extra method clone
}

為了建立一個. net物件的“克隆”我們有現成的“MemberwiseClone”功能。基類的客戶我們有相同的實現。這種方法的任何其他型別的客戶類是繼承也將克隆物件的能力。 隱藏,複製Code

public class CustomerBase : ICustomer
{
// Other codes removed for readability       
public ICustomer Clone()
{
            return (ICustomer) this.MemberwiseClone();
}
}

現在工廠的“建立”功能將呼叫克隆方法後,從集合中查詢。所以同一個引用的物件不會被髮送,這將是一個新的物件的副本。 隱藏,複製Code

public static class Factory
{
// Other codes are removed for readability purpose
public static ICustomer Create(int CustomerType)
{
return customers.Value[CustomerType].Clone();
}
}

模式4原型模式:這是一個建立型設計模式,我們建立一個新的克隆/一個物件的例項。 步驟11:-自動化簡單工廠使用統一 一個好的開發人員總是狩獵如何由現成的自動化設計模式框架。例如上面的簡單工廠類是偉大的但現在想一想如果我們需要支援其他物件型別,如訂單,記錄器等等。所以寫工廠對於每個其中之一,建立多型集合,然後在上面查測試所有這些事情本身是一項艱鉅的任務。 完成簡單的工廠和多型收集查詢可以使用一些自動化/取代了DI框架統一,ninject, MEF等等。 我能理解一些人喊出“迪是什麼?”。屏住呼吸很快我們將討論。現在讓我們專注於如何簡單的工廠可以自動使用DI框架。現在,我們將選擇統一應用程式塊。 所以第一步是得到統一使用NUGET應用程式塊在你的工廠類。如果你是NUGET你可以看到這個視訊,NUGET基本面解釋道。 所以第一步是讓持有統一名稱空間的應用程式塊。 隱藏,複製Code

using Microsoft.Practices.Unity;

在統一或任何DI框架容器的概念。這些容器集合。“RegisterType”和“ResolveType”方法有助於分別新增和得到物件從容器中收集。 隱藏,複製Code

static  IUnityContainer cont = null;
        static Factory()
        {
            cont = new UnityContainer();
            cont.RegisterType<icustomer,lead="">("0");
            cont.RegisterType<icustomer,customer="">("1");
        }
        public static ICustomer Create(int CustomerType)
        {
            return cont.Resolve<icustomer>(CustomerType.ToString());
        }
</icustomer></icustomer,></icustomer,>

下面的圖片顯示瞭如何手動工廠模式程式碼對映到自動統一容器的程式碼。 步驟12:-抽象類定義的一半 如果你還記得“CustomerBase”類這是一半定義類。它定義了所有屬性但後來驗證方法定義的孩子具體類。現在想一想如果有人建立了這一半的物件定義類,可以什麼後果?。 會發生什麼如果他呼叫下面空的“驗證”方法?。 是的,你猜對的混亂。 隱藏,複製Code

public class CustomerBase : ICustomer
{
        public string CustomerName { get; set; }
        public string PhoneNumber { get; set; }
        public decimal BillAmount { get; set; }
        public DateTime BillDate { get; set; }
        public string Address { get; set; }
        public void Validate()
	  {
		// To be defined by the child classes
  }
}

所以解決辦法是避免混亂不允許客戶端建立物件的類定義的一半即creatingan“抽象類”。 隱藏,複製Code

public abstract class CustomerBase : ICustomer
{
        public string CustomerName { get; set; }
        public string PhoneNumber { get; set; }
        public decimal BillAmount { get; set; }
        public DateTime BillDate { get; set; }
        public string Address { get; set; }
        public abstract void Validate();
}

現在如果客戶機試圖建立抽象類的物件,他將與以下錯誤丟擲,這有助於我們防止混淆使用一半的類定義。 步驟13:-通用的工廠 如果你看到工廠類與“客戶”的繫結型別。換句話說,如果我們想下班打卡“供應商”型別,我們需要一個更“創造”的方法如以下程式碼所示。如果我們有很多業務物件這樣我們會得到很多的“創造”的方法。 隱藏,複製Code

public static class Factory
{
public static ICustomer Create(int CustomerType)
{
return cont.Resolve<icustomer>(CustomerType.ToString());
}
public static Supplier Create(int Supplier)
{
return cont.Resolve<isupplier>(Supplier.ToString());
}
}
</isupplier></icustomer>

與其繫結單個型別的“工廠”如何成為一個“通用的”類。 如果你是“仿製藥”我建議你通過這個youtube c#泛型視訊解釋了細節的方式“仿製藥”的概念。並且如果你從學校認為“一般”和“通用”集合一樣你應該看到上面的視訊刪除,誤解。 通用幫助你解耦的邏輯資料型別。這裡的邏輯是“物件建立”,但將這種邏輯只與“客戶”會使體系結構剛性。所以如何使它成為泛型型別“AnyType”如以下程式碼所示。 隱藏,複製Code

public static class Factory<anytype>
{
static IUnityContainer container = null;
public static AnyType Create(string Type)
{
if (container == null)
            {
                container = new UnityContainer();
                container.RegisterType<icustomer,lead="">("Lead");
                container.RegisterType<icustomer,customer="">("Customer");
            }
return container.Resolve<anytype>(Type.ToString());
}
}
</anytype></icustomer,></icustomer,></anytype>

注意:——我已經改變的關鍵從數字“0”和“1”到“領導”和“客戶”,使其更具可讀性。 所以現在當客戶想要建立“客戶”物件他需要呼叫如下所示。 隱藏,複製Code

ICustomer Icust =  Factory<icustomer>.Create("Customer");</icustomer>

步驟14:-策略模式進行驗證 如果你讀要求3號它說驗證“客戶”是不同的,不同的“領導”。“客戶”“領導”的所有欄位是強制性的,只足夠多的姓名和電話號碼。 為了達到相同的我們已經建立了一個虛擬“驗證”方法,該方法分別與新規則覆蓋新類。 隱藏,收縮,複製Code

public class Customer : CustomerBase
    {
public override void Validate()
        {
if (CustomerName.Length == 0)
            {
throw new Exception("Customer Name is required");
            }
if (PhoneNumber.Length == 0)
            {
throw new Exception("Phone number is required");
            }
if (BillAmount == 0)
            {
throw new Exception("Bill Amount is required");
            }
if (BillDate >= DateTime.Now)
            {
throw new Exception("Bill date  is not proper");
            }
        }
    }

public class Lead : CustomerBase
    {
public override void Validate()
        {
if (CustomerName.Length == 0)
            {
throw new Exception("Customer Name is required");
            }
if (PhoneNumber.Length == 0)
            {
throw new Exception("Phone number is required");
            }
        }
    }

但如果你讀的要求又進一步說,這有可能增加新的驗證,我們預計系統靈活或我將r皮革、皮革製品說動態實現相同的。 但當我們使用繼承其靜態與動態。第二個“客戶”類和“鉛”類與驗證演算法/策略是緊耦合的。所以如果我們想achievedynamic靈活性我們需要刪除這個驗證邏輯實體和其他地方。 此刻的實體類與驗證演算法。簡而言之: 我們不是SRP之後。我們沒有做SOC所以我們需要實現國際奧委會,這意味著我們需要將演算法的邏輯從實體類,其他類。 現在為了實現解耦之間的“實體”和“驗證邏輯”我們需要確保這兩個政黨通過一個通用介面而不是直接對話的具體類。 我們已經有一個通用介面“客戶”以同樣的方式讓我們建立一個通用介面驗證演算法,我們將術語“IValidationStratergy”這個介面。我們還要注意介面通用,這樣我們可以使用這個介面明天等其他型別的“供應商”,“賬戶”等。 隱藏,複製Code

public interface IValidationStratergy<anytype>
{
void Validate(AnyType obj);
}
</anytype>

現在我們可以進一步實現上面的介面和建立不同的validationlogics。例如下面的驗證檢查 隱藏,複製Code

public class CustomerAllValidation  : IValidationStratergy<icustomer>
    {

public void Validate(ICustomer obj)
        {
if (obj.CustomerName.Length == 0)
            {
throw new Exception("Customer Name is required");
            }
if (obj.PhoneNumber.Length == 0)
            {
throw new Exception("Phone number is required");
            }
if (obj.BillAmount == 0)
            {
throw new Exception("Bill Amount is required");
            }
if (obj.BillDate >= DateTime.Now)
            {
throw new Exception("Bill date  is not proper");
            }
        }
    }
</icustomer>

隱藏,複製Code

public class LeadValidation : IValidationStratergy<icustomer>
    {
public void Validate(ICustomer obj)
        {
if (obj.CustomerName.Length == 0)
            {
throw new Exception("Customer Name is required");
            }
if (obj.PhoneNumber.Length == 0)
            {
throw new Exception("Phone number is required");
            }
        }
    }
</icustomer>

現在基類將內部一般驗證介面。現在,“客戶”和“領導”類不知道他會執行什麼樣的驗證策略。 隱藏,複製Code

public abstract class CustomerBase : BoBase, ICustomer
{
// Code removed for simplification
private IValidationStratergy<icustomer> _ValidationType = null;
public CustomerBase(IValidationStratergy<icustomer> _Validate)
{
            _ValidationType = _Validate;
}
public IValidationStratergy<icustomer> ValidationType
{
get
            {
return _ValidationType;
            }
set
            {
                _ValidationType = value;
            }
        }
}
}
</icustomer></icustomer></icustomer>

現在在工廠類,我們可以建立任何實體和注入任何驗證。你可以看到我們已經建立了一個客戶類和injectedthe所有驗證類物件。以同樣的方式我們已經建立了一個領導類和注射導致驗證物件。 隱藏,複製Code

container.RegisterType<icustomer,customer="">("Customer", new InjectionConstructor(newCustomerAllValidation()));

container.RegisterType<icustomer,lead="">("Lead", new InjectionConstructor(new LeadValidation()));
</icustomer,></icustomer,>

下面是工廠的完整程式碼。 隱藏,複製Code

public static class Factory<anytype>
{
static IUnityContainer container = null;

public static AnyType Create(string Type)
        {
if (container == null)
            {
                container = new UnityContainer();
                container.RegisterType<icustomer,customer="">("Customer", 
                                new InjectionConstructor(newCustomerAllValidation()));
                container.RegisterType<icustomer,lead="">("Lead", 
                                    new InjectionConstructor(new LeadValidation()));

            }
return container.Resolve<anytype>(Type.ToString());
        }

    }
</anytype></icustomer,></icustomer,></anytype>

模式5策略模式:這是一個行為設計模式有助於在執行時選擇演算法。 消費和生活 如果你還記得我們已經有了一個UI所以我剛剛消耗的更新UI。 下面是按鈕驗證事件的程式碼。 隱藏,複製Code

// Create customer or lead type depending on the value of combo box
icust = Factory<icustomer>.Create(cmbCustomerType.Text);

// Set all values
icust.CustomerName = txtCustomerName.Text;
icust.Address = txtAddress.Text;
icust.PhoneNumber = txtPhoneNumber.Text;
icust.BillDate = Convert.ToDateTime(txtBillingDate.Text);
icust.BillAmount = Convert.ToDecimal(txtBillingAmount.Text);


// Call validate method
icust.Validate();
</icustomer>

在接下來的部分是什麼? 在接下來的部分,我們將涵蓋以下五個模式:- 建立DAL層使用ADO。淨和分離他們使用儲存庫模式,UOW和介面卡模式。在ADO使用模板模式。NET程式碼重用命令和連線物件。使用Facade模式簡化UI程式碼。 下面是一個很好的設計模式youtube視訊一步一步這解釋瞭如何使用設計模式在c#專案。 本文轉載於:http://www.diyabc.com/frontweb/news2167.html