最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關于.NET Framework中的設計模式--應用策略模式為List排序

 更新時間:2013年04月12日 09:00:56   作者:  
本篇文章,小編將為大家介紹關于.NET Framework中的設計模式--應用策略模式為List排序,有需要的朋友可以參考一下
簡單類型排序

編程時遇到排序在平常不過,使用.Net最常見的就是對泛型List<T>進行排序,如果T是簡單數(shù)據類型排序那么很簡單

復制代碼 代碼如下:

public List<int> SortSimpleList(List<int> list)
{
list.Sort();
return list;
}

同樣對string等簡單類型List<T>排序均如此,如果我們要排的對象復雜了怎么辦,我們知道List<T> sort()最后是用快速排序實現(xiàn),快速排序也好,什么排序都需要知道list中item之間的比較結果,如果是簡單的int類型,直接判斷即可,對實現(xiàn)了IComparable接口的對象,可以調用其CompareTo()實現(xiàn)item比較大小,下面是一個快速排序的寫法

復制代碼 代碼如下:

void Sort<T>(T[] array, int left, int right, IComparer_sly<T> comparer) where T : IComparable
{
if (left < right)
{
T middle = array[(left + right) / 2];
int i = left - 1;
int j = right + 1;
while (true)
{
while (array[++i].CompareTo(middle) < 0) ;

while (array[--j].CompareTo(middle) > 0) ;

if (i >= j)
break;

T temp = array[i];
array[i] = array[j];
array[j] = temp;
}

Sort(array, left, i - 1, comparer);
Sort(array, j + 1, right, comparer);
}
}

問題

對于前兩種情況固然可以實現(xiàn)排序,但是我們不可能要求所有待排序的對象都實現(xiàn)IComparable接口,就算能夠保證每個對象都實現(xiàn)IComparable接口,如果想實現(xiàn)對象內多個字段排序,比如Student對象,有時候想按照姓名排序,有時候是成績,有時候是年齡,這怎么破

按照面向對象的思想,要把變化獨立出來,封裝變化,對于我們排序List<T>時變化的其實就是怎么比較兩個對象的大小的算法,如果我們可以把這個算法拿出來,排序就簡單了很多,無論什么排序,算法都是由的,我們要封裝的部分是怎樣比較兩個item的大小的算法,為了實現(xiàn)拓展性我們要遵循面向對象設計的另外一個重要原則,針對接口編程,而不是針對實現(xiàn)編程。

編寫通用的List<T>排序方法

首先定義一個接口,里面有一個比較item大小的方法,在排序的時候作為參數(shù)傳入,當然是傳入它的實現(xiàn)類,有了這個想法,我們可以自己寫個List<T>的排序方法

復制代碼 代碼如下:

public interface mparer_sly<T>{
int Compare(T x, T y);
}

然后為了測試,我們?yōu)長ist<T>加一個包裝,寫一個自己的Sort方法,內部也用快速排序實現(xiàn)。一直困惑我們的變化部分——比較大小算法,我們把它封轉起來,作為參數(shù)傳入

復制代碼 代碼如下:

using System;
using System.Collections.Generic;

namespace Test.Stategy
{public class ListTest<T>
{
public List<T> list = new List<T>();
public void Sort(IComparer_sly<T> comparer)
{
T[] array = list.ToArray();
int left = 0;
int right = array.Length - 1;
QuickSort(array, left, right, comparer);
list = new List<T>(array);
}

private void QuickSort<S>(S[] array, int left, int right, IComparer_sly<S> comparer)
{
if (left < right)
{
S middle = array[(left + right) / 2];
int i = left - 1;
int j = right + 1;
while (true)
{
while (comparer.Compare(array[++i], middle) < 0) ;

while (comparer.Compare(array[--j], middle) > 0) ;

if (i >= j)
break;

S temp = array[i];
array[i] = array[j];
array[j] = temp;
}

QuickSort(array, left, i - 1, comparer);
QuickSort(array, j + 1, right, comparer);
}
}
}
}

比如現(xiàn)在我們有個Student 的實體

復制代碼 代碼如下:

public class Student
{
public Student(int id, string name)
{
this.ID = id;
this.Name = name;
}
public int ID { get; set; }
public string Name { get; set; }
}

如果想對這個實體組成的List<T>進行排序,我們只需一個實現(xiàn) IComparer_sly<Student>的類 StudentComparer,并在內部實現(xiàn)其比較大小方法——Compare(),同時我們可以添加遞增還是遞減排序的控制

復制代碼 代碼如下:

class StudentComparer : IComparer_sly<Student>
{
private string expression;
private bool isAscending;
public StudentComparer(string expression, bool isAscending)
{
this.expression = expression;
this.isAscending = isAscending;
}

public int Compare(Student x, Student y)
{
object v1 = GetValue(x), v2 = GetValue(y);
if (v1 is string || v2 is string)
{
string s1 = ((v1 == null) ? "" : v1.ToString().Trim());
string s2 = ((v2 == null) ? "" : v2.ToString().Trim());
if (s1.Length == 0 && s2.Length == 0)
return 0;
else if (s2.Length == 0)
return -1;
else if (s1.Length == 0)
return 1;
}

// 這里就偷懶調用系統(tǒng)方法,不自己實現(xiàn)了,其實就是比較兩個任意相投類型數(shù)據大小,自己實現(xiàn)比較麻煩
if (!isAscending)
return Comparer.Default.Compare(v2, v1);
return Comparer.Default.Compare(v1, v2);
}

private object GetValue(Student stu)
{
object v = null;
switch (expression)
{
case "id":
v = stu.ID;
break;
case "name":
v = stu.Name;
break;
default:
v = null;
break;
}
return v;
}
}

測試一下好不好使

復制代碼 代碼如下:

static void Main(string[] args)
{
ListTest<Student> test = new ListTest<Student>();
for (int i = 0; i < 10; i++)
{
Student stu = new Student(i,string.Format("N_"+(9-i)));
test.list.Add(stu);
}
Console.WriteLine("元數(shù)據");
for (int i = 0; i < test.list.Count;i++ )
{
Console.WriteLine(string.Format("ID:{0} , Name:{1}", test.list[i].ID, test.list[i].Name));
}

Console.WriteLine("Name 遞增");
test.Sort(new StudentComparer("name", true));
for (int i = 0; i < test.list.Count; i++)
{
Console.WriteLine(string.Format("ID:{0} , Name:{1}", test.list[i].ID, test.list[i].Name));
}
}

看看效果

Capture

.NET List的sort如何為我們排序

用ILSpy反編譯可以看到在調用List<T>的sort()方法時內部調用的時 this.Sort(0, this.Count, null); 然后往里面扒,經過一系列異常處理后會調用 Array.Sort<T>(this._items, index, count, comparer); this._items是把List內容轉換成數(shù)組,同樣再經歷一些列異常處理,調用方法 ArraySortHelper<T>.Default.Sort(array, index, length, comparer); 再往里就和我們上面寫的方法大同小異了,只不過微軟加了很多異常處理和算法優(yōu)化。

策略模式

看清楚了上面這個例子我們就可以進入正題,說說我們的策略模式了。策略模式定義了一系列的算法,并將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立于使用它的客戶而獨立變化。(原文:The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.)

5366d0160924ab189a9f061935fae6cd7b890b16

這個模式涉及到三個角色:

環(huán)境(Context)角色:持有一個Strategy類的引用。抽象策略(Strategy)角色:這是一個抽象角色,通常由一個接口或抽象類實現(xiàn)。此角色給出所有的具體策略類所需的接口。具體策略(ConcreteStrategy)角色:包裝了相關的算法或行為。

相信大家可以分方便的把我們上面例子中的類對應上策略模式的角色,IComparer接口是我們的抽象策略角色, ListTest<T> 類持有抽象策略的引用是環(huán)境(在Sort方法中,其實可以把接口定義為類的屬性,在構造函數(shù)中賦值,不過不適合此場景,畢竟并不是所有List都需要排序,不能強制其接受一個可能會用不到的接口,當然對每個實例都需要用某個策略的場景是合適的),毫無疑問我們實現(xiàn)IComparer抽象策略的類就是具體策略。

使用場景

策略模式很容易理解,不過能夠用它很好的理解封裝變化和針對接口編程者兩個面向對象設計原則,我們來看看什么時候我們會用策略模式

1、 多個類只區(qū)別在表現(xiàn)行為不同,可以使用Strategy模式,在運行時動態(tài)選擇具體要執(zhí)行的行為。

2、 需要在不同情況下使用不同的策略(算法),這些策略有統(tǒng)一接口。

3、 對客戶隱藏具體策略(算法)的實現(xiàn)細節(jié),彼此完全獨立。

策略模式的優(yōu)勢和不足

優(yōu)點:

1、 提供了一種替代繼承的方法,而且既保持了繼承的優(yōu)點(代碼重用)還比繼承更靈活(算法獨立,可以任意擴展)。

2、 使用組合,避免程序中使用多重條件轉移語句,使系統(tǒng)更靈活,并易于擴展。

3、 遵守大部分GRASP原則和常用設計原則,高內聚、低偶合。

缺點:

1、 因為每個具體策略類都會產生一個新類,所以會增加系統(tǒng)需要維護的類的數(shù)量。

相關文章

  • .NET性能優(yōu)化之為結構體數(shù)組使用StructLinq的問題解析

    .NET性能優(yōu)化之為結構體數(shù)組使用StructLinq的問題解析

    這篇文章主要介紹了.NET性能優(yōu)化為結構體數(shù)組使用StructLinq,本系列的主要目的是告訴大家在遇到性能問題時,有哪些方案可以去優(yōu)化;并不是要求大家一開始就使用這些方案來提升性能,需要的朋友可以參考下
    2022-05-05
  • ASP.NET實現(xiàn)根據URL生成網頁縮略圖的方法

    ASP.NET實現(xiàn)根據URL生成網頁縮略圖的方法

    這篇文章主要介紹了ASP.NET實現(xiàn)根據URL生成網頁縮略圖的方法,結合實例較為詳細的分析了asp.net生成網頁縮略圖的詳細實現(xiàn)技巧與相關注意事項,需要的朋友可以參考下
    2015-11-11
  • 詳解如何在ASP.NET Core中編寫高效的控制器

    詳解如何在ASP.NET Core中編寫高效的控制器

    這篇文章主要介紹了詳解如何在ASP.NET Core中編寫高效的控制器,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • .NetCore獲取Json和Xml格式的配置信息

    .NetCore獲取Json和Xml格式的配置信息

    本篇將和大家分享的是如何獲取Json和Xml格式的配置信息,主要介紹的是Configuration擴展方法的使用,對.netcore 獲取json和xml格式的配置信息的相關知識,感興趣的朋友一起看看吧
    2017-09-09
  • 剖析Asp.Net路由系統(tǒng)實現(xiàn)原理

    剖析Asp.Net路由系統(tǒng)實現(xiàn)原理

    本篇文章主要介紹了剖析Asp.Net路由系統(tǒng)實現(xiàn)原理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • webapi中如何使用依賴注入

    webapi中如何使用依賴注入

    本篇將要和大家分享的是webapi中如何使用依賴注入,依賴注入這個東西在接口中常用,實際工作中也用的比較頻繁,因此這里分享兩種在api中依賴注入的方式Ninject和Unity。下面跟著小編一起來看下吧
    2017-02-02
  • ASP.NET網站導航及導航控件如何使用

    ASP.NET網站導航及導航控件如何使用

    這篇文章主要介紹了ASP.NET網站導航及導航控件如何使用,需要的朋友可以參考下
    2015-09-09
  • MVC4制作網站教程第三章 修改用戶組操作3.3

    MVC4制作網站教程第三章 修改用戶組操作3.3

    這篇文章主要為大家詳細介紹了MVC4制作網站教程,修改用戶組功能的實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • .NET示波器控件的實例代碼分析

    .NET示波器控件的實例代碼分析

    本篇文章是對.NET示波器控件進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • WPF項目在設計界面調用后臺代碼

    WPF項目在設計界面調用后臺代碼

    這篇文章介紹了WPF項目在設計界面調用后臺代碼的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04

最新評論

勐海县| 石首市| 海原县| 通道| 眉山市| 黄山市| 彭阳县| 武宣县| 凤庆县| 大足县| 绥芬河市| 巧家县| 左云县| 阿城市| 防城港市| 保亭| 榆社县| 汉寿县| 祁阳县| 洛南县| 惠水县| 苍山县| 梧州市| 深圳市| 讷河市| 垫江县| 体育| 友谊县| 社旗县| 嫩江县| 浦江县| 遂溪县| 德江县| 林西县| 财经| 和林格尔县| 塔河县| 龙游县| 营山县| 乌苏市| 绥化市|