1 使用RCW和CCW來訪問
是否可以在 .NET 框架程序中使用 COM 對象?
是。您現(xiàn)在部署的任何 COM 組件都可以在托管代碼中使用。通常情況下,所需的調(diào)整是完全自動進(jìn)行的。
特別是,可以使用運行時可調(diào)用包裝 (RCW) 從 .NET 框架訪問 COM 組件。此包裝將 COM 組件提供的 COM 接口轉(zhuǎn)換為與 .NET 框架兼容的接口。對于 OLE 自動化接口,RCW 可以從類型庫中自動生成;對于非 OLE 自動化接口,開發(fā)人員可以編寫自定義 RCW,手動將 COM 接口提供的類型映射為與 .NET 框架兼容的類型。
是否可以在 COM 程序中使用 .NET 框架組件?
是。您現(xiàn)在創(chuàng)建的托管類型都可以通過 COM 訪問。通常情況下,所需的配置是完全自動進(jìn)行的。托管開發(fā)環(huán)境的某些新特性不能在 COM 中訪問。例如,不能在 COM 中使用靜態(tài)方法和參數(shù)化構(gòu)造函數(shù)。一般,提前確定給定類型所針對的用戶是一種較好的辦法。如果類型需要在 COM 中使用,您將被限制在使用 COM 可訪問的特性。
默認(rèn)情況下,托管類型可能是可見的,也可能是不可見的,這由用于編寫托管類型的語言決定。
特別是,可以使用 COM 可調(diào)用包裝 (CCW) 從 COM 訪問 .NET 框架組件。這與 RCW(請參閱上一個問題)相似,但它們的方向相反。同樣,如果 .NET 框架開發(fā)工具不能自動生成包裝,或者如果自動方式不是您所需要的,則可以開發(fā)自定義的 CCW。
使用ildasm 和ilasm反編譯之后,去掉publickey 和.permissionset linkcheck
就可以正常引用了.
聽說VS有自帶的簡單的混淆器咋個啟用方法呀?
這個方法很容易破
用ildasm反編譯后把頭部的強(qiáng)名稱刪掉再用ilasm編譯回去就能用了
方法不錯,值得鼓勵。MS的ReportingService里面就是這么干的,盡管可以用ILDasm來破解掉單個Assembly,但是當(dāng)整個系統(tǒng)都采用這個策略的時候,全部破解很費精力。
re: 指針高級-- 夢在天涯 2006-07-12 12:02
恩,是有警告,說不能返回局部指針,也就是棧上的指針
re: 指針高級-- 夢在天涯 2006-07-07 13:18
直接編譯:需要
#include <stdio.h>
#include <tchar.h>
re: Net 常用工具(free) 夢在天涯 2006-07-04 09:01
re: 非常簡單的石頭,剪刀,布程序 夢在天涯 2006-06-26 14:19
謝謝樓上的!
re: 非常簡單的石頭,剪刀,布程序 夢在天涯 2006-06-24 15:35
死循環(huán)????為什么不執(zhí)行循環(huán)里的輸入語句cin >> a;和cin >> b;???
re: 非常簡單的石頭,剪刀,布程序 夢在天涯 2006-06-24 14:39
輸入字符或字符串的時候會.................
re: 性能測試類 夢在天涯 2006-06-16 14:26
GetTickCount()和GetCurrentTime()都只精確到55ms(1個tick就是55ms)。如果要精確到毫秒,應(yīng)該使用timeGetTime函數(shù)或QueryPerformanceCounter函數(shù)。
雖然timeGetTime返回值的單位是1ms,但實際上它的精度只有10ms左右。
如果想提高精度,可以使用QueryPerformanceCounter和QueryPerformanceFrequency。這兩個函數(shù)不是在每個系統(tǒng)中都支持。對于支持它們的系統(tǒng)中,可以獲得低于1ms的精度。Windows 內(nèi)部有一個精度非常高的定時器, 精度在微秒級, 但不同的系統(tǒng)這個定時器的頻率不同, 這個頻率與硬件和操作系統(tǒng)都可能有關(guān)。利用 API 函數(shù) QueryPerformanceFrequency 可以得到這個定時器的頻率。利用 API 函數(shù) QueryPerformanceCounter 可以得到定時器的當(dāng)前值。根據(jù)要延時的時間和定時器的頻率, 可以算出要延時的時間定時器經(jīng)過的周期數(shù)。在循環(huán)里用 QueryPerformanceCounter 不停的讀出定時器值, 一直到經(jīng)過了指定周期數(shù)再結(jié)束循環(huán), 就達(dá)到了高精度延時的目的。
re: 單元測試小技巧 夢在天涯 2006-06-16 11:53
vista開發(fā)社區(qū): http://devreadiness.org/default.aspx
紋理類
在托管的 Direct3D 中,與紋理相關(guān)的類從抽象類 Resource 繼承,并且在極大程度上在與紋理相關(guān)的非托管接口上建立層。托管的 Direct3D 有三個紋理類:Texture、CubeTexture 和 VolumeTexture。Texture 類表示可映射到基元上的圖像,用于呈現(xiàn)或用于凹凸貼圖、法線貼圖或其他效果。紋理的基本函數(shù)用于將一對紋理坐標(biāo)映射到某個值(通常是顏色值),但是可以通過其他方式進(jìn)行解釋。紋理坐標(biāo)通常是頂點數(shù)據(jù)的一部分。紋理坐標(biāo)到顏色或其他值的映射是在呈現(xiàn)管線的像素處理階段完成的。Direct3D 允許一次最多使用八個紋理。CubeTexture 類是用于立方體環(huán)境貼圖的特殊種類的紋理,立方體環(huán)境貼圖這種技術(shù)允許環(huán)境(如室內(nèi)或外景)由反光物體反射出來,這是通過以下方法來實現(xiàn)的:使用紋理來為立方體周圍的六個面各定義一個圖像,并由所呈現(xiàn)的物體來反射。VolumeTexture 類表示存在于三維矩形空間中的顏色或其他值。同樣,它將紋理坐標(biāo)的三元組映射到顏色或其他值。這些類最重要的方面是,它們都支持一組用于鎖定和取消鎖定紋理的重載方法。
經(jīng)常用于加載和保存紋理的類是 TextureLoader。TextureLoader 類包含用來從文件或流加載紋理、立方體紋理或體積紋理的方法。TextureLoader 類的其他用法包括填充和篩選紋理以及計算法線貼圖。用來創(chuàng)建紋理的有用的 helper 方法由 GraphicsUtility 類提供:文件的 GraphicsUtility.CreateTexture 方法只是查找指定紋理的路徑,然后調(diào)用 TextureLoader.FromFile 方法以加載它。以下代碼說明了 GraphicsUtility 類的用法:
Texture texture = GraphicsUtility.CreateTexture(device,"banana.bmp");
設(shè)備類
托管的 Direct3D 提供了基于類的設(shè)備抽象,該抽象是通過使用非托管的 IDirect3DDevice9 接口實現(xiàn)的。編寫 Direct3D 托管代碼的程序員使用 Device 類的方法來訪問其他 Direct3D 對象,以便設(shè)置各種圖形狀態(tài)并呈現(xiàn)幾何形狀。為了執(zhí)行這些函數(shù),Device 類提供了許多屬性、方法和事件。圖 2 列出了 Device 類最重要的方法,這些方法由 3D 應(yīng)用程序調(diào)用。
談到對象激活,一種觀點認(rèn)為,非托管的 Direct3D 之所以使用工廠方法,只是因為 COM 不支持新運算符。COM 的標(biāo)準(zhǔn)激活模式是基于工廠的構(gòu)造。CoCreateInstance 函數(shù)模仿 COM 的新運算符,但它只是一個在內(nèi)部使用 COM 工廠的包裝。使用工廠(相對于新運算符)的另一個原理就是,在使用新運算符時,需要將對象的特定實現(xiàn)綁定到客戶端的代碼中;因此,如果大量使用新運算符,可能會導(dǎo)致版本控制問題。工廠方法通常用于將代碼的客戶端或用戶與代碼的創(chuàng)建者去耦。非托管的 COM IDirect3DDevice9 接口提供 14 種顯式工廠方法,以便創(chuàng)建在使用 Direct3D 時需要的對象(如像素和頂點 Shader 以及頂點和索引緩沖區(qū))。
目前,托管的 Direct3D 在很大程度上依賴于使用新運算符來構(gòu)造類。盡管 Device 托管類只提供三種工廠方法,但是,一個值得注意的有趣現(xiàn)象是,非托管的 IDirect3DDevice9 工廠方法和由 Device 類公開的公共屬性之間存在一對一關(guān)聯(lián)。以下代碼行說明了由 Device 托管類公開的三種工廠方法,每種方法都使用多個參數(shù):
public Surface CreateRenderTarget(...);
public Surface CreateDepthStencilSurface(...);
public Surface CreateOffscreenPlainSurface(...);
在托管的 Direct3D 中大量使用方法重載。下面的代碼示例說明了非托管的 Device.ColorFill 方法及其托管的重載包裝:
typedef DWORD D3DCOLOR;
// Methods from the unmanaged IDirect3DDevice9 interface.
HRESULT ColorFill(IDirect3DSurface9 *pSurface, CONST RECT *pRect,
D3DCOLOR color);
// Methods from the managed Device class.
public void ColorFill(Surface surface, Rectangle rect, Color color);
public void ColorFill(Surface surface, Rectangle rect, int color);
與傳統(tǒng)的圖形系統(tǒng)一樣,非托管的 Direct3D 需要將顏色值作為 32 位整數(shù)值在內(nèi)部傳遞。另一方面,Microsoft .NET Framework 顯式提供用來處理 ARGB 顏色值的 System.Drawing.Color 類,其中包含幾種用來在不同表示形式之間進(jìn)行轉(zhuǎn)換的方法。為方便那些已習(xí)慣于使用整數(shù)值來表示顏色的程序員,托管的 Direct3D 在需要顏色參數(shù)時使用這兩種表示形式來提供方法重載。
非托管的 IDirect3DDevice9 接口既公開只讀屬性,又公開讀寫屬性,這兩種屬性都可以帶參數(shù),也可以不帶參數(shù)。在最新版本的 .NET Framework 中,屬性不帶參數(shù)。因此,在將非托管的 Direct3D 映射到托管的 Direct3D 時,不使用參數(shù)的屬性可以很好地映射到 C# 屬性,而使用參數(shù)的 Direct3D 非托管屬性只作為 Get 和 Set 方法公開。圖 3 列出了 Device 類的一些最重要的屬性。
最后,Direct3D Device 托管類提供了五個用來與設(shè)備進(jìn)行交互的顯式事件。基于 Direct3D 的應(yīng)用程序可以通過以下方法來將事件作為 Device 的來源:啟動應(yīng)用程序、調(diào)整窗口的大小、從窗口模式更改到全屏模式或者退出應(yīng)用程序。一個有趣的發(fā)現(xiàn)是由 Direct3D 使用的基于 .NET 委托的事件模式。對于 Device 類的每個事件聲明,提供了添加、刪除和引發(fā)方法,以及用來存儲事件處理程序的私有實例變量。在 C# 中,客戶端事件注冊和注銷的語法形式分別是通過 += 和 -= 運算符來提供的(請參閱圖 4)。
圖形狀態(tài)類
如前所述,非托管代碼的圖形狀態(tài)是通過 IDirect3DDevice9 接口的方法來配置的。例如,在非托管代碼中,變換狀態(tài)可通過 GetTransform 和 SetTransform 方法直接訪問,這兩種方法都使用 D3DTRANSFORMTYPE 類型的枚舉值。
// From unmanaged IDirect3DDevice9 interface:
HRESULT GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX *pMatrix);
HRESULT SetTransform(D3DTRANSFORMSTATETYPE State,
CONST D3DMATRIX *pMatrix);
托管的 Direct3D 為非托管層提供一些抽象,這會使客戶端代碼變得更簡潔。下面顯示的 Device 類說明了一組只讀屬性:
public class Device : MarshalByRefObject, IDisposable
{
// Additional properties, methods and events.
public Transforms Transform { get; }
public RenderStates RenderState { get; }
public SamplerStates SamplerState { get; }
public TextureStates TextureState { get; }
}
這些屬性返回 Transforms、RenderStates、SamplerStates 和 TextureStates 類的實例。這些實例隨后用于配置托管 Direct3D 的圖形狀態(tài)。例如,Device 類不直接公開使用枚舉值的 Transform 屬性。Device 托管類提供可返回 Transforms 對象的屬性。Transforms 對象隨后公開一組可用來訪問當(dāng)前世界、視圖和投影矩陣的屬性,這些屬性本身是 TransformType 托管枚舉的元素。
RenderStates 類提供了大量的屬性來配置為光柵化階段選擇的特定算法。下面的客戶端代碼顯示了如何設(shè)置 Direct3D 托管管線的狀態(tài)。
// cull, spec, dither states.
device.RenderState.CullMode = Cull.None;
device.RenderState.SpecularEnable = false;
device.RenderState.DitherEnable = false;
// Filter states.
device.SamplerState[0].MagFilter = TextureFilter.Linear;
device.SamplerState[0].MinFilter = TextureFilter.Linear;
請注意,使用索引器來訪問取樣器狀態(tài)的多紋理層疊所在的階段。
取樣器狀態(tài)指定用于特定階段的篩選、平鋪和紋理尋址模式,這些模式可通過 Sampler 類的屬性來公開。篩選功能用于指定如何將圖像映射到特定的 Direct3D 基元。根據(jù)圖像(紋理)的大小以及它需要映射到的屏上基元的大小,可能需要放大或縮小圖像。Direct3D 提供了三種篩選方法:MipFilter、MinFilter 和 MagFilter,每種方法都具有可由 TextureFilter 枚舉配置的模式。平鋪功能用于將一組單個的紋理匯集成單個紋理并減少切換紋理的需要。平鋪功能是通過 Sampler 類的一組屬性獲得支持的。最后,紋理尋址模式通過 TextureAddress 枚舉的元素為 [0,1] 邊界外部的紋理坐標(biāo)定義操作:
public class SamplerStates
{
private Sampler[] m_lpTex;
private bool pureDevice;
public Sampler get_SamplerState(int index);
internal SamplerStates(Device dev, bool pure);
public Sampler this[int index] { get; }
}
TextureStates 和 SamplerStates 類提供只讀索引器,該索引器可返回特定階段的 TextureState 實例。TextureState 類定義的屬性可獲得或指定特定紋理階段狀態(tài)的元素。諸如 ColorArgumentn 或 AlphaArgumentn(其中 n 可以是 0、1 或 2)屬性可以是 TextureArgument 枚舉的元素,而 ColorOperation 或 AlphaOperation 可以屬于 TextureOperation 枚舉,如下所示:
// color = tex mod diffuse.
device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
device.TextureState[0].ColorOperation = TextureOperation.Modulate;
device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;
// alpha = select texture alpha.
device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
device.TextureState[0].AlphaOperation = TextureOperation.SelectArg1;
device.TextureState[0].AlphaArgument1 = TextureArgument.Diffuse;
與幾何形狀相關(guān)的類
Direct3D 中的幾何形狀被定義為頂點定義的數(shù)組。不同的圖形算法需要存儲在每個頂點的不同信息,了解這一點很重要。這些頂點組分需要由應(yīng)用程序進(jìn)行聲明,具體情況取決于程序員希望實現(xiàn)的效果。例如,如果程序員希望將紋理映射到 Direct3D 將呈現(xiàn)的幾何形狀,則程序員必須進(jìn)行如下聲明:在每個頂點,都將有 tu 和 tv 值(紋理坐標(biāo))。托管的 Direct3D 提供了兩種頂點定義機(jī)制:VertexFormats 和 VertexDeclarations。使用這些機(jī)制,可以在每個頂點定義其他數(shù)據(jù),如顏色、混合權(quán)重、紋理坐標(biāo)或應(yīng)用程序定義的任何用法。作為一種方便的方法,為經(jīng)常使用的頂點格式定義提供了 CustomVertex helper 類。CustomVertex 類提供 11 種不同的頂點定義,這些定義經(jīng)常用于 Direct3D 應(yīng)用程序中。
在托管的 Direct3D 中,應(yīng)用程序用來定義其頂點布局的頂點格式由 Device 類的讀和寫 VertexFormat 屬性來訪問。VertexFormat 屬性訪問 VertexFormats 枚舉的元素,并且只需通過以下方法來實現(xiàn):針對 IDirect3DDevice9 接口使用 GetFVF 和 SetFVF 方法,調(diào)用內(nèi)部的非托管 Direct3D Device COM 對象。托管的 VertexFormats 枚舉映射到在 d3dtypes.h 中定義的 VertexFormat 常量位,如下所示:
public struct Vertex
{
public Vector3 position;
public float tu, tv;
public static readonly VertexFormats Format =
VertexFormats.Position | VertexFormats.Texture1;
};
// From a typical managed Direct3D applications Render() method.
device.VertexFormat = Vertex.Format;
在使用可編程的管線時,需要自定義的頂點聲明。與使用靈活的頂點格式定義的頂點緩沖區(qū)不同,自定義頂點聲明可以通過使用多個流來定義,從而可節(jié)省帶寬:
VertexElement[] declaration = new VertexElement[]
{
new VertexElement(
0, // short stream
0, // short offset
DeclarationType.Float2, // DeclarationType declType
DeclarationMethod.Default, // DeclarationMethod declMethod
DeclarationUsage.Position, // DeclarationUsage declUsage
0 // byte usageIndex
),
VertexElement.VertexDeclarationEnd
};
VertexDeclaration declaration = new VertexDeclaration(device,
declaration);
托管 Direct3D 中的幾何形狀通常是通過處理 VertexBuffer.Created 事件來創(chuàng)建的。圖 5 顯示了從 SDK 中的 Tutorial2 示例提取的簡單三角形形狀,并說明了預(yù)定義的自定義頂點 (CustomVertex.TransformedColored) 的用法。
托管的 D3DX 庫
托管的 D3DX 實用工具庫具有用來處理網(wǎng)格、紋理、Shader、效果、文本和動畫的類。但是,與非托管的 D3DX 庫不同的是,它沒有數(shù)學(xué)類,如矩陣、矢量和四元組類。在托管 DirectX 中,數(shù)學(xué)類是 DirectX 庫的一部分。
用來處理網(wǎng)格的類包括 Mesh、SimplificationMesh、ProgressiveMesh、SkinMesh 和 PatchMesh。Mesh 和 ProgressiveMesh 從 BaseMesh 類繼承。BaseMesh 管理內(nèi)存(包括頂點和索引緩沖區(qū))中的網(wǎng)格表示形式,并提供用來呈現(xiàn)網(wǎng)格的 DrawSubset 方法。其他方法包括用來復(fù)制網(wǎng)格的 Clone 方法,以及用來計算頂點法線并獲取相鄰項信息的方法。
Mesh 類使用可將網(wǎng)格保存到 .X 文件(標(biāo)準(zhǔn)的 DirectX 文件類型)或二進(jìn)制流中并從中加載網(wǎng)格的方法來擴(kuò)展 BaseMesh。還提供了用來生成表示以下圖形的網(wǎng)格的方法:n 邊形、圓柱、球形、圓環(huán)、給定字體的 3D 文本或者甚至是茶壺。用戶可以網(wǎng)格化網(wǎng)格以獲得更光滑的對象(通過將每個三角形解釋為 N-patch),簡化網(wǎng)格(通過減少三角形的數(shù)量)、優(yōu)化網(wǎng)格(通過對三角形重新排序,以便利用硬件中的頂點緩存并提高性能)或者執(zhí)行與網(wǎng)格的光交叉。
SimplificationMesh 對象是從 Mesh 構(gòu)造的,它具有可減少表面(三角形)或頂點數(shù)量的方法,從而可產(chǎn)生比初始網(wǎng)格簡單但是質(zhì)量更低的網(wǎng)格形式。ProgressiveMesh 對象是從 Mesh 構(gòu)造的。它允許實時簡化網(wǎng)格,以便在網(wǎng)格對象和照相機(jī)之間的距離增大時,最小化所呈現(xiàn)三角形的數(shù)量。SkinMesh 類(由主干制作動畫的網(wǎng)格)提供的方法可用來從 .X 文件數(shù)據(jù)對象加載外觀網(wǎng)格。包含了用來公開基礎(chǔ)網(wǎng)格和外觀的信息(如每根骨頭對結(jié)構(gòu)的影響)的屬性。
PatchMesh 類表示更高階的表面,如 N-Patch、Triangle Patch 或 Rectangle Patch 表面。PatchMesh 包括用來執(zhí)行如下操作的方法:從 Mesh 對象創(chuàng)建 N-Patch 網(wǎng)格、從 .X 文件加載 PatchMesh、網(wǎng)格化 PatchMesh 等。用來處理紋理的類主要包括:前面介紹的 TextureLoader 類、RenderToEnvironmentMap 類和 RenderToSurface 類。RenderToEnvironmentMap 和 RenderToSurface 類用來在運行時創(chuàng)建立方體環(huán)境貼圖和紋理。如果在運行時呈現(xiàn)到紋理中,則允許您獲得特殊效果,如讓類似于鏡面的物體反射布景中的其他物體,或者制造雙窗格呈現(xiàn)效果。用來處理文本的類主要包括 Font 類,F(xiàn)ont 類可以從 System.Drawing.Font 對象實例化,并且具有可以在支持 Direct3D 的設(shè)備上呈現(xiàn)文本的方法。用來處理動畫的類由 KeyFrameInterpolator 類組成,KeyFrameInterpolator 類具有用來以內(nèi)插值替換對象的縮放、旋轉(zhuǎn)和/或平移的方法。內(nèi)插值替換是通過使用一組 3D 矢量(用來縮放和平移)和四元組項(用于旋轉(zhuǎn))來執(zhí)行的。
都有這個device.SetStreamSource(0, vertexBuffer, 0);
她的作用?可以不要嗎?
用處: 在c++中用基類指針的數(shù)組,在c#中用arraylist都可以 來表示一個帶有分支的樹結(jié)構(gòu)
用戶感覺不到他在處理結(jié)合還是一個單體> 這就是此模式的用處所在
小弟最近在CSDN上找的C#面試題目,自己做了一下把題目和答案附上來,希望對大家有用。如有錯誤的地方還望大家指教!
1、C#中 property 與 attribute的區(qū)別,他們各有什么用處,這種機(jī)制的好處在哪里?
property和attribute漢語都稱之為屬性。不過property是指類向外提供的數(shù)據(jù)區(qū)域。而attribute則是描述對象在編譯時或運行時屬性的。這兩者是有本質(zhì)區(qū)別的。
2、講一講你理解的web service,在dot net framework中,怎么很好的結(jié)合xml?(講概念就行了)
從表面上看,Web Service就是一個應(yīng)用程序,它向外界暴露出一個能夠通過Web進(jìn)行調(diào)用的API。這就是說,你能夠用編程的方法通過Web調(diào)用來實現(xiàn)某個功能的應(yīng)用程序。從深層次上看,Web Service是一種新的Web應(yīng)用程序分支,它們是自包含、自描述、模塊化的應(yīng)用,可以在網(wǎng)絡(luò)(通常為Web)中被描述、發(fā)布、查找以及通過Web來調(diào)用。可擴(kuò)展的標(biāo)記語言XML是Web Service平臺中表示數(shù)據(jù)的基本格式。除了易于建立和易于分析外,XML主要的優(yōu)點在于它既與平臺無關(guān),又與廠商無關(guān)。XML是由萬維網(wǎng)協(xié)會(W3C)創(chuàng)建,W3C制定的XML SchemaXSD定義了一套標(biāo)準(zhǔn)的數(shù)據(jù)類型,并給出了一種語言來擴(kuò)展這套數(shù)據(jù)類型。Web Service平臺是用XSD來作為數(shù)據(jù)類型系統(tǒng)的。當(dāng)你用某種語言如VB.NET或C#來構(gòu)造一個Web Service時,為了符合Web Service標(biāo)準(zhǔn),所有你使用的數(shù)據(jù)類型都必須被轉(zhuǎn)換為XSD類型。如想讓它使用在不同平臺和不同軟件的不同組織間傳遞,還需要用某種東西將它包裝起來。這種東西就是一種協(xié)議,如 SOAP。
3. C#, Java 和 c++的特點,有什么相同的地方,不同的地方,C#分別從c++和java中吸取了他們那些優(yōu)點?
C#看起來與Java有著驚人的相似;它包括了諸如單一繼承,界面,與Java幾乎同樣的語法,和編譯成中間代碼再運行的 過程.但是C#與Java有著明顯的不同,它借鑒了Delphi的一個特點,與COM(組件對象模型)是直接集成。
微軟c#語言定義主 要是從C和C++繼承而來的,而且語言中的許多元素也反映了這一點.C#在設(shè)計者從C++繼承的可選選項方面比Java要廣泛一些(比如說 structs),它還增加了自己新的特點(比方說源代碼版本定義).
C#從Java繼承而來的特點
類:在C#中類的申明與Java很相似。特點看起來與Java相比沒有變化.布爾運算:條件表達(dá)式的結(jié)果是布爾數(shù)據(jù)類型,布爾數(shù)據(jù)類型是這種語言中獨立的一種數(shù)據(jù)類型.從布爾類型到其他類型沒有 直接的轉(zhuǎn)換過程.布爾常量true和false是C#中的關(guān)鍵字.錯誤處理:如Java中那樣,通過拋出和捕捉異常對象來管理錯誤處理過程.內(nèi)存管理:由 底層.NET框架進(jìn)行自動內(nèi)存垃圾回收.
C#從C和C++繼承的特點
編譯:程序直接編譯成標(biāo)準(zhǔn)的二進(jìn)制可執(zhí)行形式.
結(jié)構(gòu)體:一個C#的結(jié)構(gòu)體與C++的結(jié)構(gòu)體是相似的,因為它能夠包含數(shù)據(jù)申明和方法.但是,不象C++,C#結(jié)構(gòu)體與類是不同的而且不支持繼承.但是,與Java相同的是,一個結(jié)構(gòu)體可以實現(xiàn)界面.
預(yù)編譯:C#中存在預(yù)編譯指令支持條件編譯,警告,錯誤報告和編譯行控制. #error
C#獨有的特點
中間代碼:微軟在用戶選擇何時MSIL應(yīng)該編譯成機(jī)器碼的時候是留了很大的余地.微軟公司很小心的聲稱MSIL不是解釋性的,而是被編譯成了機(jī)器碼.它也明 白許多--如果不是大多數(shù)的話--程序員認(rèn)為Java程序要不可避免的比C編寫的任何東西都要慢.而這種實現(xiàn)方式?jīng)Q定了基于MSIL的程序(指的是用 C#,Visual Basic,"Managed C++"--C++的一個符合CLS的版本--等語言編寫的程序)將在性能上超過"解釋性的"Java代碼.當(dāng)然,這一點還需要得到事實證明,因為C#和 其他生成MSIL的編譯器還沒有發(fā)布.但是Java JIT編譯器的普遍存在使得Java和C#在性能上相對相同.象"C#是編譯語言而Java是解釋性的,"之類的聲明只是商業(yè)技巧.Java的中間代碼和 MSIL都是中間的匯編形式的語言,它們在運行時或其它的時候被編譯成機(jī)器代碼.
命名空間中的申明:當(dāng)你創(chuàng)建一個程序的時候,你在一個命名空間里創(chuàng)建了一個或多個類.同在這個命名空間里(在類的外面)你還有可能聲明界面,枚舉類型和結(jié)構(gòu)體.必須使用using關(guān)鍵字來引用其他命名空間的內(nèi)容.
基本的數(shù)據(jù)類型:C#擁有比C,C++或者Java更廣泛的數(shù)據(jù)類型.這些類型是bool, byte, ubyte, short, ushort, int, uint, long, ulong, float, double,和decimal.象Java一樣,所有這些類型都有一個固定的大小.又象C和C++一樣,每個數(shù)據(jù)類型都有有符號和無符號兩種類型.與 Java相同的是,一個字符變量包含的是一個16位的Unicode字符.C#新的數(shù)據(jù)類型是decimal數(shù)據(jù)類型,對于貨幣數(shù)據(jù),它能存放28位10 進(jìn)制數(shù)字.
兩個基本類:一個名叫object的類是所有其他類的基類.而一個名叫string的類也象object一樣是這個語言的一部分.作為語言的一部分存在意味著編譯器有可能使用它--無論何時你在程序中寫入一句帶引號的字符串,編譯器會創(chuàng)建一個string對象來保存它.
參數(shù)傳遞:方法可以被聲明接受可變數(shù)目的參數(shù).缺省的參數(shù)傳遞方法是對基本數(shù)據(jù)類型進(jìn)行值傳遞.ref關(guān)鍵字可以用來強(qiáng)迫一個變量通過引用傳遞,這使得一個變量可以接受一個返回值.out關(guān)鍵字也能聲明引用傳遞過程,與ref不同的地方是,它指明這個參數(shù)并不需要初始值.
與COM 的集成:C#對Windows程序最大的賣點可能就是它與COM的無縫集成了,COM就是微軟的Win32組件技術(shù).實際上,最終有可能在任何.NET語 言里編寫COM客戶和服務(wù)器端.C#編寫的類可以子類化一個以存在的COM組件;生成的類也能被作為一個COM組件使用,然后又能使用,比方說, JScript語言子類化它從而得到第三個COM組件.這種現(xiàn)象的結(jié)果是導(dǎo)致了一個運行環(huán)境的產(chǎn)生,在這個環(huán)境里的組件是網(wǎng)絡(luò)服務(wù),可用用任何.NET語 言子類化.
索引下標(biāo):一個索引與屬性除了不使用屬性名來引用類成員而是用一個方括號中的數(shù)字來匿名引用(就象用數(shù)組下標(biāo)一樣)以外是相似的.
代理和反饋:一個代理對象包括了訪問一個特定對象的特定方法所需的信息.只要把它當(dāng)成一個聰明的方法指針就行了.代理對象可以被移動到另一個地方,然后可以 通過訪問它來對已存在的方法進(jìn)行類型安全的調(diào)用.一個反饋方法是代理的特例.event關(guān)鍵字用在將在事件發(fā)生的時候被當(dāng)成代理調(diào)用的方法聲明中.
Managed DirectX是對DirectX大部分功能的托管封裝,可以用任何支持.NET的語言開發(fā)。MDX只對DirectX做了非常低層次的封裝,因此保持了用COM接口DirectX開發(fā)時的大部分原貌。MDX的性能是不用擔(dān)心的,因為它還是象COM DirectX一樣提供對硬件層次的訪問,大部分功能都是在你的顯卡/網(wǎng)卡/聲卡上起作用的,托管部分只是它的接口。事實證明MDX在DirectX Graphics中的性能與COM接口的DirectX不相上下。既然MDX的開發(fā)方式、API和性能都與COM接口的DirectX差不多,那為什么要用MDX呢?我自己對這個問題的回答是:
1、托管代碼的對象模型更好。MDX基于類庫的組織結(jié)構(gòu),比用COM接口的處理方式更方便。
2、用MDX,一般不用操心資源釋放的問題。很大一部分資源釋放的操作,都被封裝好了。
3、與更多現(xiàn)代技術(shù)結(jié)合得更好。我們可以讓DirectX程序使用XML、WebService和智能客戶端等技術(shù)。
Direct3D程序最基本的流程是:創(chuàng)建Windows窗口、創(chuàng)建設(shè)備、處理消息循環(huán)、物體圖形顯示、退出和清理。在MDX的世界里,窗口創(chuàng)建和處理消息循環(huán)我們交給Windows Forms模型來做,剩下最主要的任務(wù)就是創(chuàng)建設(shè)備和物體圖形顯示。Direct3D設(shè)備是Direct3D開發(fā)最基本的入口,它定義了Direct3D所有的繪圖組件,大部分的操作都需要從Direct3D設(shè)備開始。創(chuàng)建設(shè)備需要設(shè)定幾個參數(shù),包括顯卡序號、設(shè)備類型、所屬窗口、3D運算方式等。除了這些信息外,還需要一個PresentParameters類型的參數(shù),其中定義了Direct3D設(shè)備所需的相關(guān)信息。下面代碼中的InitializeDirect3D函數(shù)完整的演示了創(chuàng)建設(shè)備的步驟
設(shè)備類型:Direct3D支持3種設(shè)備,其中HAL和REF最為重要。HAL通過硬件進(jìn)行光柵化、坐標(biāo)變換和光照處理等,速度最快。REF則是用軟件實現(xiàn)相關(guān)的操作,僅用于硬件不支持某種操作的情況。DeviceType枚舉定義了設(shè)備類型可能的選項。
3D運算方式包括一些選項,如HardwareVertexProcessing,PureHardwareVertexProcessing等,用于指定頂點運算由硬件執(zhí)行還是軟件執(zhí)行等。
PresentParameters還包括一些設(shè)置,如后臺緩沖區(qū)的高度、寬度和像素格式,以及從后臺緩沖區(qū)復(fù)制到前臺緩存屏幕顯示的方式等等。如果Direct3D采用窗口方式運行,像素格式必須查詢當(dāng)前的顯示模式獲得。
Direct3D設(shè)備創(chuàng)建成功以后,就可以進(jìn)入圖形顯示階段。在下面的代碼中以Render()函數(shù)的形式出現(xiàn)。在繪制圖形前,需要調(diào)用Device::Clear()函數(shù)重制ViewPort的顏色緩沖區(qū)。ViewPort就是3D形狀投射到平面顯示器上供我們看到的那個區(qū)域。Clear函數(shù)的Flag參數(shù)指定了對顏色緩沖區(qū)、深度緩沖區(qū)還是模板緩沖區(qū)進(jìn)行初始化。因為我用ATI顯卡,所以我選擇了將顏色緩沖區(qū)初始化為紅色:)。接下來是調(diào)用BeginScene()函數(shù)和EndScene()函數(shù)。實際的繪圖中,所有渲染的代碼都必須放在BeginScene函數(shù)和EndScene函數(shù)之間,否則就會出錯。最后調(diào)用Present()函數(shù),將后臺緩沖區(qū)中的數(shù)據(jù)復(fù)制到前臺緩沖區(qū),我們就能看見圖形了。
IT公司類
包括思科、英特爾、IBM、惠普、ACER、索尼、Oracle、聯(lián)想、長城、同方、方正、洪恩、微軟、漢王、神州數(shù)碼、京東方、維爾軟件、普天、奇碼數(shù)字信息有限公司、廣東北電、威盛、高通、揚智、友立資訊、BISC、GOOGLE、SUN、騰訊公司、百度等
通訊/運營類
中國電信、中國移動、中國聯(lián)通、中國網(wǎng)通、中國鐵通、華為、中興、大唐、UT斯達(dá)康、上海貝爾阿爾卡特、摩托羅拉、諾基亞、愛立信、西門子、朗訊、香港電信、東信、北京信威通信、飛利浦、NEC
電子電氣類
意法半導(dǎo)體、Avant! 微電子、凹凸電子、松下電器、美的集團(tuán)、創(chuàng)維集團(tuán)、廈新、TCL、北京松下彩色顯像管有限公司、中星微電子、美國國家儀器有限公司(NI)、士蘭微電子、世芯電子股份有限公司、奧的斯(otis)、青島海信集團(tuán)技術(shù)中心
金融/投資
中國工商銀行、中國建設(shè)銀行、中國銀行、中國農(nóng)業(yè)銀行、中國招商銀行、中國國際金融有限公司(CICC)、Hongkong Bank、中軟融鑫、高盛(GS)、博世(BOSCH)、寶潔(Procter&Gamble)、沃爾瑪
http://www.net3721.com/bbs/forumdisplay.php?fid=43
但是 .net 2.0 中不支持用delegate() 來sort().
re: XML Comments in C# 夢在天涯 2006-04-30 16:25
很好用的啊,但是好像沒有最新的支持.net 2.0的啊!
re: IT高薪必讀 夢在天涯 2006-04-26 09:02
轉(zhuǎn)的!
在什么情況下應(yīng)當(dāng)使用訪問者模式
有意思的是,在很多情況下不使用設(shè)計模式反而會得到一個較好的設(shè)計。換言之,每一個設(shè)計模式都有其不應(yīng)當(dāng)使用的情況。訪問者模式也有其不應(yīng)當(dāng)使用的情況,讓我們
先看一看訪問者模式不應(yīng)當(dāng)在什么情況下使用。
傾斜的可擴(kuò)展性
訪問者模式僅應(yīng)當(dāng)在被訪問的類結(jié)構(gòu)非常穩(wěn)定的情況下使用。換言之,系統(tǒng)很少出現(xiàn)需要加入新節(jié)點的情況。如果出現(xiàn)需要加入新節(jié)點的情況,那么就必須在每一個訪問對象里加入一個對應(yīng)于這個新節(jié)點的訪問操作,而這是對一個系統(tǒng)的大規(guī)模修改,因而是違背"開一閉"原則的。
訪問者模式允許在節(jié)點中加入新的方法,相應(yīng)的僅僅需要在一個新的訪問者類中加入此方法,而不需要在每一個訪問者類中都加入此方法。
顯然,訪問者模式提供了傾斜的可擴(kuò)展性設(shè)計:方法集合的可擴(kuò)展性和類集合的不可擴(kuò)展性。換言之,如果系統(tǒng)的數(shù)據(jù)結(jié)構(gòu)是頻繁變化的,則不適合使用訪問者模式。
"開一閉"原則和對變化的封裝
面向?qū)ο蟮脑O(shè)計原則中最重要的便是所謂的"開一閉"原則。一個軟件系統(tǒng)的設(shè)計應(yīng)當(dāng)盡量做到對擴(kuò)展開放,對修改關(guān)閉。達(dá)到這個原則的途徑就是遵循"對變化的封裝"的原則。這個原則講的是在進(jìn)行軟件系統(tǒng)的設(shè)計時,應(yīng)當(dāng)設(shè)法找出一個軟件系統(tǒng)中會變化的部分,將之封裝起來。
很多系統(tǒng)可以按照算法和數(shù)據(jù)結(jié)構(gòu)分開,也就是說一些對象含有算法,而另一些對象含有數(shù)據(jù),接受算法的操作。如果這樣的系統(tǒng)有比較穩(wěn)定的數(shù)據(jù)結(jié)構(gòu),又有易于變化的算法的話,使用訪問者模式就是比較合適的,因為訪問者模式使得算法操作的增加變得容易。
反過來,如果這樣一個系統(tǒng)的數(shù)據(jù)結(jié)構(gòu)對象易于變化,經(jīng)常要有新的數(shù)據(jù)對象增加進(jìn)來的話,就不適合使用訪問者模式。因為在訪問者模式中增加新的節(jié)點很困難,要涉及到在抽象訪問者和所有的具體訪問者中增加新的方法。
六、 使用訪問者模式的優(yōu)點和缺點
訪問者模式有如下的優(yōu)點:
訪問者模式使得增加新的操作變得很容易。如果一些操作依賴于一個復(fù)雜的結(jié)構(gòu)對象的話,那么一般而言,增加新的操作會很復(fù)雜。而使用訪問者模式,增加新的操作就意味著增加一個新的訪問者類,因此,變得很容易。
訪問者模式將有關(guān)的行為集中到一個訪問者對象中,而不是分散到一個個的節(jié)點類中。
訪問者模式可以跨過幾個類的等級結(jié)構(gòu)訪問屬于不同的等級結(jié)構(gòu)的成員類。迭代子只能訪問屬于同一個類型等級結(jié)構(gòu)的成員對象,而不能訪問屬于不同等級結(jié)構(gòu)的對象。訪問者模式可以做到這一點。
積累狀態(tài)。每一個單獨的訪問者對象都集中了相關(guān)的行為,從而也就可以在訪問的過程中將執(zhí)行操作的狀態(tài)積累在自己內(nèi)部,而不是分散到很多的節(jié)點對象中。這是有益于系統(tǒng)維護(hù)的優(yōu)點。
訪問者模式有如下的缺點:
增加新的節(jié)點類變得很困難。每增加一個新的節(jié)點都意味著要在抽象訪問者角色中增加一個新的抽象操作,并在每一個具體訪問者類中增加相應(yīng)的具體操作。
破壞封裝。訪問者模式要求訪問者對象訪問并調(diào)用每一個節(jié)點對象的操作,這隱含了一個對所有節(jié)點對象的要求:它們必須暴露一些自己的操作和內(nèi)部狀態(tài)。不然,訪問者的訪問就變得沒有意義。由于訪問者對象自己會積累訪問操作所需的狀態(tài),從而使這些狀態(tài)不再存儲在節(jié)點對象中,這也是破壞封裝的。
訪問者模式的目的是封裝一些施加于某種數(shù)據(jù)結(jié)構(gòu)元素之上的操作。一旦這些操作需要修改的話,接受這個操作的數(shù)據(jù)結(jié)構(gòu)則可以保持不變。
問題提出
System.Collection命名空間下提供了大量集合操作對象。但大多數(shù)情況下處理的都是同類對象的聚集。換言之,在聚集上采取的操作都是一些針對同類型對象的同類操作。但是如果針對一個保存有不同類型對象的聚集采取某種操作該怎么辦呢?
粗看上去,這似乎不是什么難題。可是如果需要針對一個包含不同類型元素的聚集采取某種操作,而操作的細(xì)節(jié)根據(jù)元素的類型不同而有所不同時,就會出現(xiàn)必須對元素類型做類型判斷的條件轉(zhuǎn)移語句。這個時候,使用訪問者模式就是一個值得考慮的解決方案。
訪問者模式
訪問者模式適用于數(shù)據(jù)結(jié)構(gòu)相對未定的系統(tǒng),它把數(shù)據(jù)結(jié)構(gòu)和作用于結(jié)構(gòu)上的操作之間的耦合解脫開,使得操作集合可以相對自由地演化。
數(shù)據(jù)結(jié)構(gòu)的每一個節(jié)點都可以接受一個訪問者的調(diào)用,此節(jié)點向訪問者對象傳入節(jié)點對象,而訪問者對象則反過來執(zhí)行節(jié)點對象的操作。這樣的過程叫做"雙重分派"。節(jié)點調(diào)用訪問者,將它自己傳入,訪問者則將某算法針對此節(jié)點執(zhí)行。
雙重分派意味著施加于節(jié)點之上的操作是基于訪問者和節(jié)點本身的數(shù)據(jù)類型,而不僅僅是其中的一者。
State模式與Strategy模式的區(qū)別時什么啊?,potian大俠幫忙。
首先,兩者的意圖是不同的。策略用來處理算法變化,而狀態(tài)則是透明地處理狀態(tài)變化。
造成混淆的原因可能是兩者好像都能成為繼承的替代。
策略主要處理算法變化的意思是算法可能是要變的,但是這種變化卻是由用戶來決定到底采用何種算法。這些算法之間一般來說沒有狀態(tài)變遷的問題,并且你總是從幾個算法中間選取一個。策略最經(jīng)典的用法是和observe一起組成MVC,其中V通過Observe觀察M,而V通過strategy控制C.
策略使用的另一個最頻繁的地方就是消除大量的Case或if else ,但是條件是這些case中每個條件可以歸納為一個算法,最好它們只需要相同的參數(shù)。當(dāng)然,在strategy中,Context可以提供接口讓strategy,但是我一般不太喜歡這么用,因為這樣可能造成一系列的不必要耦合和開銷。
對這些case,if else使得strategy有了一個policy的別名,還有一個常用的地方叫做validator,譬如在輸入框內(nèi)進(jìn)行檢查時可以把它實現(xiàn)為Validator。有時候,if else的嵌套層次可能很深,這時候策略可能不能用,那么你可能需要更加復(fù)雜或者更加專注的Rule模式。
狀態(tài)模式則有所不同,她實現(xiàn)的一個概念可以叫做動態(tài)繼承,也就是繼承的子類(每一個狀態(tài))可以發(fā)生變化。這些狀態(tài)的變化是一個整體,組成了一個狀態(tài)變化圖。而一般來說,使用該模式的狀態(tài)之間存在著一種線性變化的關(guān)系,也就是一個狀態(tài)變?yōu)榱硪粋€,然后是第三個。客戶代碼并不清楚這些狀態(tài)在何時發(fā)生變化,這樣做的好處是在組成你整個變化過程中某些狀態(tài)之間需要插入一個新的狀態(tài),或者狀態(tài)的順序之間發(fā)生變化,對客戶是不可見。實現(xiàn)模式一方面,修改的也只是相領(lǐng)的狀態(tài)。在處于不同的狀態(tài)時,客戶代碼可以執(zhí)行的方法也是不同的。但它的問題就是必須在Context和所有的狀態(tài)實現(xiàn)所有狀態(tài)可能的方法。
這兩個之間的區(qū)別有時候可能沒有,譬如在面向連結(jié)的TCPConnection例子中,不同的狀態(tài)可能具有不同的方法。但是在我剛剛實現(xiàn)的一個無連結(jié)的P2P底層協(xié)議中,所有狀態(tài)需要處理地就是一個processXML方法,這時候,你可以叫它狀態(tài)或者策略都可以。但由于還是又狀態(tài)變遷的問題,所以我喜歡把它叫做狀態(tài)。
比較簡單了,在net里太多的集合類拉,哈哈,就是那2個interface.
在什么情況下應(yīng)當(dāng)使用命令模式
在下面的情況下應(yīng)當(dāng)考慮使用命令模式:
1、使用命令模式作為"CallBack"在面向?qū)ο笙到y(tǒng)中的替代。"CallBack"講的便是先將一個函數(shù)登記上,然后在以后調(diào)用此函數(shù)。
2、需要在不同的時間指定請求、將請求排隊。一個命令對象和原先的請求發(fā)出者可以有不同的生命期。換言之,原先的請求發(fā)出者可能已經(jīng)不在了,而命令對象本身仍然是活動的。這時命令的接收者可以是在本地,也可以在網(wǎng)絡(luò)的另外一個地址。命令對象可以在串形化之后傳送到另外一臺機(jī)器上去。
3、系統(tǒng)需要支持命令的撤消(undo)。命令對象可以把狀態(tài)存儲起來,等到客戶端需要撤銷命令所產(chǎn)生的效果時,可以調(diào)用undo()方法,把命令所產(chǎn)生的效果撤銷掉。命令對象還可以提供redo()方法,以供客戶端在需要時,再重新實施命令效果。
4、如果一個系統(tǒng)要將系統(tǒng)中所有的數(shù)據(jù)更新到日志里,以便在系統(tǒng)崩潰時,可以根據(jù)日志里讀回所有的數(shù)據(jù)更新命令,重新調(diào)用Execute()方法一條一條執(zhí)行這些命令,從而恢復(fù)系統(tǒng)在崩潰前所做的數(shù)據(jù)更新。
5、一個系統(tǒng)需要支持交易(Transaction)。一個交易結(jié)構(gòu)封裝了一組數(shù)據(jù)更新命令。使用命令模式來實現(xiàn)交易結(jié)構(gòu)可以使系統(tǒng)增加新的交易類型。
八、 使用命令模式的優(yōu)點和缺點
命令允許請求的一方和接收請求的一方能夠獨立演化,從而且有以下的優(yōu)點:
命令模式使新的命令很容易地被加入到系統(tǒng)里。
允許接收請求的一方?jīng)Q定是否要否決(Veto)請求。
能較容易地設(shè)計-個命令隊列。
可以容易地實現(xiàn)對請求的Undo和Redo。
在需要的情況下,可以較容易地將命令記入日志。
命令模式把請求一個操作的對象與知道怎么執(zhí)行一個操作的對象分割開。
命令類與其他任何別的類一樣,可以修改和推廣。
你可以把命令對象聚合在一起,合成為合成命令。比如宏命令便是合成命令的例子。合成命令是合成模式的應(yīng)用。
由于加進(jìn)新的具體命令類不影響其他的類,因此增加新的具體命令類很容易。
命令模式的缺點如下:
使用命令模式會導(dǎo)致某些系統(tǒng)有過多的具體命令類。某些系統(tǒng)可能需要幾十個,幾百個甚至幾千個具體命令類,這會使命令模式在這樣的系統(tǒng)里變得不實際。
職責(zé)鏈(Chain of Responsibility)模式
責(zé)任鏈模式是一種對象的行為模式【GOF95】。在責(zé)任鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發(fā)出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求,這使得系統(tǒng)可以在不影響客戶端的情況下動態(tài)地重新組織鏈和分配責(zé)任。
我想Proxy與Adapter還是有區(qū)別的。因為Proxy中的代理和被代理對象是“同根生”,這樣才可以代理。Adapter中的Adapter與Adaptee不用“同根生”。我把Proxy稱作“票販子的模式”,而Adapter是“倒賣外匯的模式”。票販子販的是票,在販賣的過程中,票沒有變化,只是被代理了。而Adapter模式中,外匯可能由人民幣變做了美元,東西變了(呵呵,換湯不換藥,都是鈔票)。
好像和裝飾(Decorator)模式差不多啊?
到底有什么不同啊?
在什么情況下使用門面模式
為一個復(fù)雜子系統(tǒng)提供一個簡單接口
提高子系統(tǒng)的獨立性
在層次化結(jié)構(gòu)中,可以使用Facade模式定義系統(tǒng)中每一層的入口。
使用裝飾模式的優(yōu)點和缺點
使用裝飾模式主要有以下的優(yōu)點:
裝飾模式與繼承關(guān)系的目的都是要擴(kuò)展對象的功能,但是裝飾模式可以提供比繼承更多的靈活性。
通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設(shè)計師可以創(chuàng)造出很多不同行為的組合。
這種比繼承更加靈活機(jī)動的特性,也同時意味著裝飾模式比繼承更加易于出錯。
使用裝飾模式主要有以下的缺點:
由于使用裝飾模式,可以比使用繼承關(guān)系需要較少數(shù)目的類。使用較少的類,當(dāng)然使設(shè)計比較易于進(jìn)行。但是,在另一方面,使用裝飾模式會產(chǎn)生比使用繼承關(guān)系更多的對象。更多的對象會使得查錯變得困難,特別是這些對象看上去都很相像。
裝飾模式應(yīng)當(dāng)在什么情況下使用
在以下情況下應(yīng)當(dāng)使用裝飾模式:
需要擴(kuò)展一個類的功能,或給一個類增加附加責(zé)任。
需要動態(tài)地給一個對象增加功能,這些功能可以再動態(tài)地撤銷。
需要增加由一些基本功能的排列組合而產(chǎn)生的非常大量的功能,從而使繼承關(guān)系變得不現(xiàn)實。
裝飾(Decorator)模式又名包裝(Wrapper)模式[GOF95]。裝飾模式以對客戶端透明的方式擴(kuò)展對象的功能,是繼承關(guān)系的一個替代方案。
橋梁模式的用意
【GOF95】在提出橋梁模式的時候指出,橋梁模式的用意是"將抽象化(Abstraction)與實現(xiàn)化(Implementation)脫耦,使得二者可以獨立地變化"。這句話有三個關(guān)鍵詞,也就是抽象化、實現(xiàn)化和脫耦。
抽象化
存在于多個實體中的共同的概念性聯(lián)系,就是抽象化。作為一個過程,抽象化就是忽略一些信息,從而把不同的實體當(dāng)做同樣的實體對待【LISKOV94】。
實現(xiàn)化
抽象化給出的具體實現(xiàn),就是實現(xiàn)化。
脫耦
所謂耦合,就是兩個實體的行為的某種強(qiáng)關(guān)聯(lián)。而將它們的強(qiáng)關(guān)聯(lián)去掉,就是耦合的解脫,或稱脫耦。在這里,脫耦是指將抽象化和實現(xiàn)化之間的耦合解脫開,或者說是將它們之間的強(qiáng)關(guān)聯(lián)改換成弱關(guān)聯(lián)。
將兩個角色之間的繼承關(guān)系改為聚合關(guān)系,就是將它們之間的強(qiáng)關(guān)聯(lián)改換成為弱關(guān)聯(lián)。因此,橋梁模式中的所謂脫耦,就是指在一個軟件系統(tǒng)的抽象化和實現(xiàn)化之間使用組合/聚合關(guān)系而不是繼承關(guān)系,從而使兩者可以相對獨立地變化。這就是橋梁模式的用意。
在什么情況下應(yīng)當(dāng)使用橋梁模式
根據(jù)上面的分析,在以下的情況下應(yīng)當(dāng)使用橋梁模式:
如果一個系統(tǒng)需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態(tài)的聯(lián)系。
設(shè)計要求實現(xiàn)化角色的任何改變不應(yīng)當(dāng)影響客戶端,或者說實現(xiàn)化角色的改變對客戶端是完全透明的。
一個構(gòu)件有多于一個的抽象化角色和實現(xiàn)化角色,系統(tǒng)需要它們之間進(jìn)行動態(tài)耦合。
雖然在系統(tǒng)中使用繼承是沒有問題的,但是由于抽象化角色和具體化角色需要獨立變化,設(shè)計要求需要獨立管理這兩者。
Adapter模式在實現(xiàn)時有以下這些值得注意的地方:
1、 目標(biāo)接口可以省略,模式發(fā)生退化。但這種做法看似平庸而并不平庸,它可以使Adaptee不必實現(xiàn)不需要的方法(可以參考Default Adapter模式)。其表現(xiàn)形式就是父類實現(xiàn)缺省方法,而子類只需實現(xiàn)自己獨特的方法。這有些像模板(Template)模式。
2、 適配器類可以是抽象類。
3、 帶參數(shù)的適配器模式。使用這種辦法,適配器類可以根據(jù)參數(shù)返還一個合適的實例給客戶端。
在以下各種情況下使用適配器模式:
1、 系統(tǒng)需要使用現(xiàn)有的類,而此類的接口不符合系統(tǒng)的需要。
2、 想要建立一個可以重復(fù)使用的類,用于與一些彼此之間沒有太大關(guān)聯(lián)的一些類,包括一些可能在將來引進(jìn)的類一起工作。這些源類不一定有很復(fù)雜的接口。
3、 (對對象適配器而言)在設(shè)計里,需要改變多個已有子類的接口,如果使用類的適配器模式,就要針對每一個子類做一個適配器,而這不太實際。
原型模式的用意是:通過給出一個原型對象來指明所要創(chuàng)建的對象類型,然后用復(fù)制這個原型對象的辦法創(chuàng)建出更多的同類型對象。
Prototype模式的優(yōu)點與缺點
Prototype模式的優(yōu)點包括
1、Prototype模式允許動態(tài)增加或減少產(chǎn)品類。由于創(chuàng)建產(chǎn)品類實例的方法是產(chǎn)批類內(nèi)部具有的,因此增加新產(chǎn)品對整個結(jié)構(gòu)沒有影響。
2、Prototype模式提供了簡化的創(chuàng)建結(jié)構(gòu)。工廠方法模式常常需要有一個與產(chǎn)品類等級結(jié)構(gòu)相同的等級結(jié)構(gòu),而Prototype模式就不需要這樣。
3、Portotype模式具有給一個應(yīng)用軟件動態(tài)加載新功能的能力。由于Prototype的獨立性較高,可以很容易動態(tài)加載新功能而不影響老系統(tǒng)。
4、產(chǎn)品類不需要非得有任何事先確定的等級結(jié)構(gòu),因為Prototype模式適用于任何的等級結(jié)構(gòu)。
Prototype模式的缺點:
Prototype模式的最主要缺點就是每一個類必須配備一個克隆方法。而且這個克隆方法需要對類的功能進(jìn)行通盤考慮,這對全新的類來說不是很難,但對已有的類進(jìn)行改造時,不一定是件容易的事