設計開篇


1 設計模式

   類是我們面向對象編程的承載工具,可以說是面向對象的起點。
   設計模式,這種算面向對象的進化。按照gof設計模式的分類
   設計模式分為:創建型,結構型,行為型。
   其中創建型主要和類的創建有關
   結構性組織擴展類和類之間的關系
   行為型主要擴展的類的訪問
   這三個對應到類上
   創建型模式對應的是構造函數
   結構型對應的是類的屬性
   行為型對應類的方法
   就想我們以前學數學中很多證明題,都源自最基本的定理,面向對象編程也有類似的地方
   設計模式就是類最基本功能的一個進化

 


 

2.依賴注入    

  相信大家對Ioc(依賴注入)肯定不陌生,Ioc主要遵循設計原則中的依賴倒置原則,  

  但是假設我們不要把這個東西提升到設計的高度,只看它的功能就會發現,   Ioc創建類正好就是控制類的構造函數,和設計模式中創建型模式有關,  

  例如創建型模式中單例模式用ioc生命周期管理可以達到同樣的效果,

  這里以Unity為例,Untiy支持child容器。利用child容器,我們可以在運行時提供更多動態創建的內容。

  我們以asp.net mvc為例,我們可以在session初始化的時候根據不同用戶注入不同接口的實現。

  例如我們可以在repository中注入一個默認的規約,當不同用戶登錄   我們可以將用戶對數據的訪問權限形成一個規約,

  注冊到child容器中,然后在controller激活的時候使用當前session的子容器來激活controller。

  在這里使用例子中,Ioc又實現了類似factory,甚至是building模式的功能(這個例子會在后面的文章中給大家展現具體的實現).

 


 

3.抽象的維度  

  多態是代碼的下行  

  抽象是代碼的下行

  如果B繼承自A,C繼承自A,那么A稱之為B,C這個維度的抽象,B,C稱之為A這個維度的變化 A,B,C稱之為一個維度的繼承關系

  傳統的繼承解決的是一個維度的變化,如果我們在這個維度上面引入泛型,並且用where限制泛型的行為 或者屬性,

  那么就可以用諸如interface<T1,T2,T3>這樣,通過組合幾個泛型提供多個維度的變化。 此處用泛型擴展的繼承有點類似於多繼承。

 


 

4.元數據編程(Attribute)

  Attribute在我所使用的元數據編程占有重要位置。

  在asp.net mvc中,ValueProvider,ModuleBinding,Validator,Filter,都使用了元數據編程。

  不談這個大的我們看一個更小的例子。

  最早在winform中使用DateGrid的時候,我們都是在grid設計器中去設置列的屬性,名稱,綁定的字段,等等。

  如果我們引入元數據編程,就可以通過在類的屬性上加上特性來擴展。

  這樣做更便於維護,當你的界面需要修改時,只需要在綁定的類上做修改,修改的地方相對集中,而不用去操作設計器。

 


 

5. 策略工廠

  上面說了很多理論的東西,下面為大家帶來點干貨。
  首先我們分析一個簡單工廠的代碼:

  public interface ITest
      {
          void DoSomething();
      }


      public class Test1: ITest
      {
          public void DoSomething()
          {

          }
      }
      public class Test2: ITest
      {
          public void DoSomething()
          {

          }
      }


      public class Factory
      {
          public static ITest Create(string type)
          {
              if (type == "1")
                  return new Test1();
              if (type == "2")
                  return new Test2();
              throw new NotImplementedException();
          }
      }

 

分析簡單工廠的弊端  

  1,擴展不方便需要改動create的邏輯  

  2,客戶需要知道create的具體邏輯 

  3,創建類型過於單一導致簡單工廠類的泛濫  

  4,無法為對象創建提供靈活性,例如構造函數參數  

  5,無法實現運行時擴展

下面我對簡單工廠做了一些改造

    public  interface IStrategy
    {
    }

    public interface IGenericsFactory<TStrategy>
        where TStrategy : IStrategy
    {

        /// <summary>
        /// 注冊處理策略
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        void Regist(Type type);


        /// <summary>
        /// 獲取處理策略
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        TStrategy GetStrategy(string name);

        /// <summary>
        /// 獲取所有的處理策略
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        List<string> GetStrategys();
    }

    public class GenericsFactory<TStrategy> : IGenericsFactory<TStrategy>
        where TStrategy : IStrategy
    {
        public GenericsFactory()
        {
            if (_strategys == null)
            {
                _strategys = GetType().Assembly
                        .GetTypes()
                        .Where(item => item.GetInterfaces().Contains(typeof(TStrategy)) || item.IsSubclassOf(typeof(TStrategy)))
                        .Where(item => !item.IsAbstract)
                        .ToDictionary(item =>
                        {
                            var desc = item.GetCustomAttribute<DescriptionAttribute>();
                            return desc != null ? desc.Description : string.Empty;
                        }, item => item);
            }
        }

        protected Dictionary<string, Type> _strategys;

        public void Regist(Type type)
        {
            if (type.GetInterfaces().Contains(typeof(TStrategy)) && type.IsSubclassOf(typeof(TStrategy)))
                throw  new TypeLoadException(string.Format("類型不是從{0},繼承",typeof(TStrategy).Name));
            if (_strategys.ContainsKey(MetaDataManager.Attribute.GetDescription(type)))
                return;
            _strategys.Add(MetaDataManager.Attribute.GetDescription(type), type);
        }

        public TStrategy GetStrategy(string name)
        {
            if (!_strategys.ContainsKey(name))
                _strategys.Add(name, typeof(TStrategy));
            return (TStrategy)UnityService.Resolve(_strategys[name]);
        }


        public List<string> GetStrategys()
        {
            return _strategys.Keys.ToList();
        }
    }

 

改造思路
  1,使用將create的類型標記在對應的接口實現上,反射獲取子類的特性,如果新增加一個類型只
       需要增加子類,並且在子類添加特性
  2,將所有可用子類的元素據緩存起來,在工廠構造函數中反射所有子類和子類的特性用字典緩存起來
       並且所有可創建的類型暴露給外部
  3,將構造出來的類型做成泛型,並且提供泛型限制,將可構造類型獨立出一個維度來變化
  4,通過ioc來動態創建類型
  5,通過提供regist來提供運行時擴展

使用的案例:
  1,SSO登陸,前台用戶和后台用戶,存放在不同的數據表,數據結構也可能不一樣
  2,動態數據權限配置,例如,某個角色只能訪問某部分數據 =,>,<等等這些篩選條件的擴展
  3,狀態者模式,狀態可擴展,可以由界面去選擇某種狀態對應那種處理方式,
     將處理方式類型放在數據庫
  4,責任鏈模式中節點的擴展和配置
       通過緩存可以直接所有節點,靈活配置節點來實現流程的功能
  5,裝飾器的擴展
  可以搭配裝飾器模式配置出先用某個裝飾后用某個裝飾、

 


 

總結:

  上面的這些關於程序設計的一些思考,會在后面的文章中分享一些自己在實際項目中的
  具體案例,請關注后續文章。要想一個架構設計能順利推廣,最簡單粗暴的方法就是這個架構能夠幫助程序員少些代碼。
  下一篇文章將分享一個,全棧式編程的設計,主要應用於后台系統的增刪改查,方便程序員更
  快速的處理掉數據的增刪改查這部分通用邏輯

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM