2017年1月2日 星期一

設計模式 Simple Factory 簡單工廠模式

情境:
要設計一個連接資料庫的物件,提供 MSSQL 與 MYSQL 兩種連線方式
讓使用者使用

 1.首先定一個介面
  1. public interface IDBConnection
  2. {
  3. void GetIDBConnection();
  4. }
  5.  
2.實作 MYSQL 與 MSSQL 資料庫連線方式
  1. public class MSSQL : IDBConnection
  2. {
  3. public void GetDBConnection()
  4. {
  5. Console.WriteLine("MYSQL連線 ");
  6. }
  7. }
  8. public class MYSQL:IDBConnection
  9. {
  10. public void GetDBConnection()
  11. {
  12. Console.WriteLine("MYSQL 連線");
  13. }
  14. }
  15.  
3.實做工廠類別
  1.  
  2. public class ConnectionFactory
  3. {
  4. public static IDDConnection GetConnection(DBType type)
  5. {
  6. IDDConnection db_ = null;
  7. switch (type)
  8. {
  9. case DBType.MySQL:
  10. db_ = new MYSQL();
  11. break;
  12. case DBType.MSSQL:
  13. db_ = new MSSQL();
  14. break;
  15. default:
  16. Console.WriteLine("default type");
  17. break;
  18. }
  19. return db_ ;
  20. }
  21. }
  22.  
  23.  
4.外部使用簡單工廠模式
  1.  
  2. class Program
  3. {
  4. static void Main(string[] args)
  5. {
  6. IDBConnection Connection_ = ConnectionFactory.GetConnection(DBType.MySQL);
  7. Connection.GetDBConnection();
  8. Console.ReadKey();
  9. }
  10. }
  11.  
  12.  

Blogger 顯示好看的程式碼內容(Code Block)

網路上查了一下 Code Block 發現 Google Code Prettify 看起來蠻順眼的, 就在這邊記錄一下設定的過程,留下筆記以便於日後查詢。

點選「版面配置」
在中間的位置點擊「新增小工具」

點擊「HTML/JavaScript」


























填入標題 Google Code Prettify

填入內容

選一個順眼的程式碼格式
Color themes for Google Code Prettify

使用方式如下














linenums 是顯示行號
language-cs 是指定 cs 的格式

範例程式碼

C# 二進制字串轉數值

範例:將字串 "1000000000000000000" 轉成 int 數值
  1.  
  2. using System;
  3. using System.Text.RegularExpressions;
  4. namespace BinaryStringToInteger
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. BinaryStringToInteger("1000000000000000000");
  11. Console.ReadKey();
  12. }
  13. static readonly Regex Binary = new Regex("^[01]{1,32}$", RegexOptions.Compiled);
  14. static void BinaryStringToInteger(string s)
  15. {
  16. if (Binary.IsMatch(s))
  17. {
  18. Console.WriteLine(Convert.ToInt32(s, 2));
  19. }
  20. else
  21. {
  22. Console.WriteLine("invalid: " + s);
  23. }
  24. }
  25. }
  26. }
  27.  
  28.  

設計模式 C# 的 Singleton 的泛型


讓人繼承就可已變成 Singleton 獨體



  1. ///
  2. /// 給人繼承成為獨體
  3. ///
  4. /// 要繼承的類別
  5. public class Singleton where T : class, new()
  6. {
  7. protected Singleton()
  8. {
  9. Debug.Assert(null == _instance);
  10. }
  11. private static readonly T _instance = new T();
  12. public static T Instance
  13. {
  14. get
  15. {
  16. return _instance;
  17. }
  18. }
  19. }
  20.  
  21.  

Function Composition

由多個小 function 組合成大 function
  1. var john = new User("John", "Doe");
  2. string EmailTo(User u) => Domain(FullName(u));
  3. var email = EmailTo(john);
  4. Console.WriteLine(email);
  5. // jodo@gmail.com (姓 2 碼 + 名 2 碼 + gmail.com)

EmailFor() 能根據 User 的 姓 與 名 自動產生 email

string EmailTo(User u) => Domain(FullName(u));

EmailTo() 為 Local Function 由 FullName() 與 Domain() 組合出新的 EmailTo()

這就是所謂的 Function Composition

Function Composition 重複使用性高,程式碼必須『由右而左』

一般人『由左至右』的閱讀習慣,改用 Function Pipeline
  1. namespace ConsoleApp
  2. {
  3. public static class Email
  4. {
  5. public static string FullName(this User u) => ShortName(u.FirstName) + CutName(u.LastName);
  6. public static string Domain(this string localPart) => $"{localPart}@gmail.com";
  7. private static string ShortName(string s) => s.Substring(0, 2).ToLower();
  8. }
  9. }

將 Name() 與 Domain() 的第一個參數都改加上 this,變成為 Extension Method
  1. namespace ConsoleApp
  2. {
  3. internal static class Program
  4. {
  5. private static void Main()
  6. {
  7. var email =
  8. new User("John", "Doe")
  9. .FullName()
  10. .Domain();
  11. Console.WriteLine(email);
  12. }
  13. }
  14. }

原本的 EmailTo() Local Function 就不需要了
只要將 User new 後,直接用 FullName() 與 Domain(),維持了『由左至右』的閱讀習慣

只要將第一個參數加上 this 修飾成為 Extenstion Method 後,
就可由 Function Composition 改成 Function Pipeline 風格

Function Composition 與 Function Pipeline 講的是同一件事情,
只是 Function Composition 採用 由右至左,
而 Function Pipeline 符合閱讀習慣,採用 由左至右

Funciton Compostion 與 Function Pipeline 是 FP 關鍵部分,
以前總以為 C# 沒有支援,
因此無法使用 C# 寫 FP,
有了 Extension Method,
C# 就能很輕鬆的實踐 FP

Extension Method

目的:
讓我們在不修改原始程式,為類別增加新函式。

  1. Enumerable.Range(1, 3)
  2. .Select(x => x * 2)
  3. .ToList()
  4. .ForEach(x => Console.WriteLine(x.ToString()));

Enumerable.Range() 產生 1、2、3
Select() 2、4、6
ForEach() 列印在畫面上

因為 List 才有 ForEach()
所以先 ToList()
再 ForEach()

這邊可以利用 Extension Method
幫 IEnumerable 打造一個 ForEach()


  1. namespace ConsoleApp
  2. {
  3. public static class Extensions
  4. {
  5. internal static void ForEacht>(this IEnumerablet source, Actiont action)
  6. {
  7. foreach (T element in source)
  8. action(element);
  9. }
  10. }
  11. }

整理一下
第一、第一個參數 this IEnumerable 特別加了 this 且 class 或 interface
第二、Extension Method 必須都為 static method


  1. Enumerable
  2. .Range(1, 3)
  3. .Select(x => x * 2)
  4. .ForEach(x => Console.WriteLine(x.ToString()));
  1. 用了 Extension Method 後這樣就能拿掉 ToList()
  1.  

設計模式 AdpaterPattern 轉接器模式

情境:
目前已經有讀取資料的類別了
要設計一個讀取資料類別支援 Json 格式

1.目前已經有一個讀取資料的方法了

  1. public class FileReader
  2. {
  3. public string Read(string parameter)
  4. {
  5. string result = string.Empty;
  6. //實作硬碟讀取
  7. return result;
  8. }
  9. }
  10.  
  11.  

2.設計一個讀取資料的介面

  1. public interface IReadData
  2. {
  3. string GetJsonData(string parameter);
  4. }
  5.  
  6.  

3.繼承這個 IReadData 介面
  1. ///
  2. /// 從網路上讀取要的資料
  3. ///
  4. public class WebReader : IReadData
  5. {
  6. public string GetJsonData(string parameter)
  7. {
  8. string result = string.Empty;
  9. //實作網路讀取
  10. return result;
  11. }
  12. }
  13.  
  14.  

4.要讓 FileReader 共享 IReadData 介面 這時候轉接器模式就可以上場了
  1. public class FileAdapter : IReadData
  2. {
  3. public string GetJsonData(string parameter)
  4. {
  5. var reader = new FileReader();
  6. return reader.Read(parameter);
  7. }
  8. }
  9.  
  10.  

總結:
雖然 FileReader 在 FileAdapter 內
但是外部看起來 WebReader 與 FileAdapter 同樣繼承 IReadData 介面

Visual Studio 2017/2019 推薦的擴充功能與更新

參考文章: 覺得 Google 的 Blogger 不太順手?透過 HTML 的 iframe 移花接木 HackMD