程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 基礎才是重中之重~這時應該用泛型方法了,之重

基礎才是重中之重~這時應該用泛型方法了,之重

編輯:C#入門知識

基礎才是重中之重~這時應該用泛型方法了,之重


回到目錄

泛型方法:是一個抽象的概念,將批量具有共性的操作進行抽象,使用泛型類型來表示這個方法,實現這些類型的方法具有相同的邏輯,而唯一不同的是,它們的類型,即類型在泛型方法裡是個變量,這話感覺是用肺說出來的,呵呵!

今天在做開發時,遇到了這個問題,最後重構了自己的代碼,重構後,使用了泛型方法,感覺代碼美麗多了

沒用泛型方法前

      /// <summary>
        /// 更新老師與學生的關系
        /// </summary>
        /// <param name="list">要插入的關系列表</param>
        /// <param name="isAll">是否為全部,如果全部,不需要向關系表插入</param>
        /// <param name="teacherId">當前老師ID</param>
        /// <param name="type">類型:0視頻,1作業,3文檔</param>
        public void AddUser_Source_R(List<User_Source_R> list, bool isAll, int teacherId, int objId, int objType)
        {

            switch (objType)
            {
                case 0:
                    var respository1 = LoadRepository<Classroom_Info>();
                    var entity1 = LoadRepository<Classroom_Info>().Find(objId);
                    if (isAll)
                    {
                        entity1.AccessStatus = 0;
                        respository1.Update(entity1);
                    }
                    else
                    {
                        entity1.AccessStatus = 1;
                        respository1.Update(entity1);
                        LoadRepository<User_Source_R>().Insert(list);
                    }
                    break;
                case 1:
                    var respository2 = LoadRepository<Courseware_Info>();
                    var entity2 = LoadRepository<Courseware_Info>().Find(objId);
                    if (isAll)
                    {
                        entity2.AccessStatus = 0;
                        respository2.Update(entity2);
                    }
                    else
                    {
                        entity2.AccessStatus = 1;
                        respository2.Update(entity2);
                        LoadRepository<User_Source_R>().Insert(list);
                    }
                    break;
                case 2:
                    var respository3 = LoadRepository<Task_Info>();
                    var entity3 = LoadRepository<Task_Info>().Find(objId);
                    if (isAll)
                    {
                        entity3.AccessStatus = 0;
                        respository3.Update(entity3);
                    }
                    else
                    {
                        entity3.AccessStatus = 1;
                        respository3.Update(entity3);
                        LoadRepository<User_Source_R>().Insert(list);
                    }
                    break;
                case 3:
                    var respository4 = LoadRepository<Substance_Info>();
                    var entity4 = LoadRepository<Substance_Info>().Find(objId);
                    if (isAll)
                    {
                        entity4.AccessStatus = 0;
                        respository4.Update(entity4);
                    }
                    else
                    {
                        entity4.AccessStatus = 1;
                        respository4.Update(entity4);
                        LoadRepository<User_Source_R>().Insert(list);
                    }
                    break;
                default:
                    throw new ArgumentException();
            }


        }

用了泛型方法後

        /// <summary>
        /// 更新老師與學生的關系
        /// </summary>
        /// <param name="list">要插入的關系列表</param>
        /// <param name="isAll">是否為全部,如果全部,不需要向關系表插入</param>
        /// <param name="teacherId">當前老師ID</param>
        /// <param name="type">>資源類型0課程,1視頻,2作業,3文檔</param>
        public void AddUser_Source_R(
            List<User_Source_R> list,
            bool isAll,
            int objId,
            int objType)
        {
            switch (objType)
            {
                case 0:
                    UpdateSource_R<Classroom_Info>(list, isAll, objId);
                    break;
                case 1:
                    UpdateSource_R<Courseware_Info>(list, isAll, objId);
                    break;
                case 2:
                    UpdateSource_R<Task_Info>(list, isAll, objId);
                    break;
                case 3:
                    UpdateSource_R<Substance_Info>(list, isAll, objId);
                    break;
                default:
                    throw new ArgumentException();
            }


        }

        /// <summary>
        /// 泛型方法來干這邏輯相同,只是類型不同的事情
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="list"></param>
        /// <param name="isAll"></param>
        /// <param name="teacherId"></param>
        /// <param name="objId"></param>
        /// <param name="objType"></param>
        void UpdateSource_R<TEntity>(
            List<User_Source_R> list,
            bool isAll,
            int objId)
            where TEntity : class, IAccess
        {
            var entity = LoadRepository<TEntity>().Find(objId);
            if (isAll)
            {
                entity.AccessStatus = 0;
                LoadRepository<TEntity>().Update(entity);
            }
            else
            {
                entity.AccessStatus = 1;
                LoadRepository<TEntity>().Update(entity);
                LoadRepository<User_Source_R>().Insert(list);
            }
        }

我們可以看是,泛型方法把不變的邏輯抽象在一起,這樣,有利於代碼的擴展和維護,這才是面向對象的代碼!

回到目錄


【Java基礎語法】怎在使用靜態方法的時指定其泛型?萬分感謝

舉個例子:
public void f(int i, char ch, String s){}
這個方法中有三個參數,分別為int類型的i,char類型的ch,String類型的s。這三個參數的類型都已經指定了,如果實際參數類型和對應參數類型不一致,編譯器會出現錯誤。
如何才能做到可以任意指定參數的類型呢?這個時候可以使用泛型方法。舉個例子:
public <A, B, C> void f(A a, B b, C c){}
這個就是所謂的泛型方法,當向方法中傳遞參數後,編譯器會自動推斷出參數的類型,如:
f(1, "hello", 123.123);
第一個參數類型為Integer,第二個為String,第三個為Double(自動包裝機制讓基本類型自動包裝成對應的包裝類)。
泛型方法的特征就是方法前面有對尖括號<>,尖括號裡面的就是類型參數,也就是說類型是個變量,要由實際的參數推斷得來。
Java中的方法就是這樣獲取泛型能力的,還有其他方式。但是static方法比較特殊,如果要使得static方法具有反省能力就必須要使用到上面的方法。
希望能解決你的問題。
 

麻煩給我詳細介紹下JAVA中用了泛型的好處,是不是用了泛型就可以不用NEW去創建對象了?

1. 泛型的卻很有用, 如果跟反射可以配合用好, 普通企業應用得代碼量可以減少非常多.
2. python之類type inference語言比java更適合做這種template抽象

舉個例子: 企業程序大部分程序是實體信息管理得, 真正涉及交易清算得只有極小一部分
對於所有得實體管理, 基本上都是增,刪, 改, 查看, 查找等等幾個功能
我現在用了幾個框架, 經典結合方式:webwork+spring+hibernate, 分析如下:

hibernate O/R Mapping沒什麼花頭, 為每個實體管理都要寫一個映射類, 一般跟實體得數目差不多, 有時候為了避免關聯, 建幾個視圖映射會多點. But, 這個能用hibernate自己寫得工具生成, 維護一個java類文件, 以及裡面得meta description.
或者自己寫個程序生成( 給定數據源,, 輸出java類文件, 以及hbm .xml文件 ), 這個只需要維護sql語句就興了, 我通常這麼做.

1. 不用泛型, 不用反射
spring層要寫5個service(假設一個實體對應一個service), 分別實現讀實體, 加實體, 刪實體, 根據條件查找實體List這些功能.

要寫5個不同得實體類得Action, 然後Action裡面實現校驗, 增加, 修改, 刪除, 列表得功能, 每一個類要實現得功能同樣也類似.

這些都沒多少重構實質性得體現, 好處不明顯, 可以提取得公共代碼非常少.

2. 不用泛型, 用反射
在 1 得基礎之上, 可以重構提取出一個公共service, 將分散在5個service得公共代碼kill掉. 多出一個根據實體類參數操作得公共類, 但是類得數量增加一個.

同樣Action也可以提出一個baseaction來

重構消去了一部分代碼, 每個service得代碼還是存在重復代碼, 但是這個還可以通過反射合成一個service, 不過掉用者要用反射調用

對於action因為需要配置, 除非webwork支持類型得注入, 否則, 不好消去.
如果webwork spring 支持實體類型得注入, 那麼到此可以結束, 只寫一套邏輯, 代碼也沒有重復, 由於精力有限, 沒有去深入研究spring AOP跟webwork 得inteceptor機制, 不知道支持不支持.

3.用泛型, 用反射
在1得基礎上引入泛型, 寫一個泛型service, 寫一個泛型webwork action , 也沒有研究過xwork中泛型對象是怎麼配置產生得, 如果支持配置, 只需要寫一個action即可, 如果不支持, 需要為每個實體類寫一個webwork action

同樣頁面也是這個樣子

但是, java得泛型用了一把, 不說對很多東西支持得很差, 光寫法上來看, 跟C++ template一致, 仍然是一大堆得<>, 讓初學者吐血, 變成高手炫耀得奇技淫巧. 比起python之類動態類型安全語言type inference機制相差太遠, java泛型還有很長得路要走, 不過靜態語言走到type inference上來得話, 編譯類型檢查得好處就沒了, 所以java這方面永遠不可能~~~
通過上面考慮, 我覺得python更適合web管理程序, 對於很多entity management得程序完全可以寫出一個服務所有, 僅僅是O?Rmapping就沒辦法省. 不知道python有沒有類似java得反射, 如果有得話......余下全文>>
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved