日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

设计模式学习笔记六:.NET反射工厂

發(fā)布時(shí)間:2023/12/19 asp.net 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 设计模式学习笔记六:.NET反射工厂 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? 1. 簡(jiǎn)述

????通過前面的學(xué)習(xí),我們以傳統(tǒng)的方式實(shí)現(xiàn)了簡(jiǎn)單工廠,工廠方法和抽象工廠,但是有些場(chǎng)合下如此處理,代碼會(huì)變得冗余并且難以維護(hù)。假設(shè)我們要?jiǎng)?chuàng)建交通工具。可以是汽車,火車,輪船等,其結(jié)構(gòu)如下:


?????我們可以采用簡(jiǎn)單工廠,通過參數(shù)指示創(chuàng)建所需要的對(duì)象類型。如果要增加子類,例如卡車和轎車,則必須增加參數(shù)和相應(yīng)的代碼。如果子類層次過多,則會(huì)是程序變得很難維護(hù)。?
????但我們可以采用工廠方法模式來實(shí)現(xiàn),即定義一個(gè)產(chǎn)生交通工具的接口,然后在子類中實(shí)現(xiàn)創(chuàng)建具體子類。代碼如下:
Code
public?interface?ICreateVehicle
????
{
?????????Vehicle?CreateCehicle();
????}
Code
?public?abstract?class?Vehicle
????
{

????}
Code
????public?class?Car:Vehicle
????
{
????????
public?Car()
????????
{
????????????Console.WriteLine(
"創(chuàng)建了一個(gè)Car");
????????}

????}
Code
????public?class?Boat:Vehicle?
????
{
????????
public?Boat()
????????
{
????????????Console.WriteLine(
"創(chuàng)建了一個(gè)Boat");
????????}

????}
Code
????public?class?CreateCar:ICreateVehicle
????
{
????????
ICreateVehicle?成員#region?ICreateVehicle?成員

????????
public??Vehicle?CreateCehicle()
????????
{
????????????Vehicle?vehicle
=new?Car();
????????????
return?vehicle;
????????}


????????
#endregion

????}
Code
????public?class?CreateBoat:ICreateVehicle
????
{
????????
ICreateVehicle?成員#region?ICreateVehicle?成員

????????
public?Vehicle?CreateCehicle()
????????
{
????????????Vehicle?vehicle?
=?new?Boat();
????????????Console.WriteLine(
"Car");
????????????
return?vehicle;
????????}


????????
#endregion

????}

這就是工廠方法。如果希望增加新的交通工具,不僅需要實(shí)現(xiàn)交通工具接口,還需要實(shí)現(xiàn)生產(chǎn)交通工具的工廠方法。

????顯然我們需要幾十種交通工具,則需要幾十個(gè)具體的工廠。而這些類的區(qū)別僅僅是返回相對(duì)應(yīng)的類的實(shí)例,所以位維護(hù)帶來了很大的麻煩。如果需要在接口中增加一個(gè)帶參數(shù)的方法,則所有的子類都需要修改。
在這種場(chǎng)合下,采用抽象工廠與工廠方法沒有區(qū)別,因?yàn)檫@里并不涉及產(chǎn)品線,抽象工廠并不能解決其中的問題,如果每種交通工具都要有對(duì)應(yīng)的車站,則要使用抽象工廠,但是將會(huì)跟復(fù)雜。

有沒有可能將需要?jiǎng)?chuàng)建類的類型傳遞到工廠方法中,由工廠方法根據(jù)類型返回相應(yīng)的實(shí)例?解決這個(gè)問題的關(guān)鍵是需要?jiǎng)討B(tài)的決定需要?jiǎng)?chuàng)建的類,這不是設(shè)計(jì)模式能解決的問題,屬于軟件平臺(tái)的功能范疇。.NET可以提供反射技術(shù)。

我們先看通過反射技術(shù)實(shí)現(xiàn)的簡(jiǎn)化的工廠,代碼如下:

Code
?public?class?CreateVehicleByType:ICreateVehicle
????
{

????????
ICreateVehicle?成員#region?ICreateVehicle?成員

????????
private?Type?VehicleTYpe;

????????
public?CreateVehicleByType(string?strType)
????????
{
????????????Type?t?
=?Type.GetType(strType);

????????????VehicleTYpe?
=?t;
????????}

????????
public??Vehicle?CreateCehicle()
????????
{
????????????ConstructorInfo??objConstrutor?
=?VehicleTYpe.GetConstructor(System.Type.EmptyTypes);
????????????Vehicle?c?
=?(Vehicle)objConstrutor.Invoke(null);
????????????
return?c;
????????}


????????
#endregion


???????
????}

在使用是,只要在創(chuàng)建時(shí)帶入需要?jiǎng)?chuàng)建的類的類型:

Code
static?void?Main(string[]?args)
????????
{

????????????
string?strType?=?"Car";

????????????Vehicle?v;
????????????ICreateVehicle?f?
=?null;

????????????
if?(strType?==?"Car")
????????????
{
????????????????f?
=?new?CreateVehicleByType("FactoryVehicle.Car");

????????????}

????????????
else?if?(strType?==?"Boat")
????????????
{
????????????????f?
=?new?CreateVehicleByType("Boat");
????????????}

????????????v?
=?f.CreateCehicle();
????????????Console.ReadLine();

????????}


通過反射技術(shù),我們將很多的具體的工廠類簡(jiǎn)化為一個(gè)類,并且新增加類型時(shí)不需要新的工廠類,這樣我們得到簡(jiǎn)化的工廠,可以稱其為“反射工廠”。

2.實(shí)例

???????? 先來看看,大話設(shè)計(jì)模式中的利用反射加抽象工廠的數(shù)據(jù)訪問程序。先來看看反射技術(shù)的基本格式:

Assembly.Load(“程序集名稱”).CreateInstance(“命名空間.類名稱”);

只要在程序頂端寫上using System.Reflection來引用Reflection,就可以采用反射工廠來克服抽象工廠模式的先天不足。下面我們來看通過反射技術(shù)實(shí)現(xiàn)不同數(shù)據(jù)庫的訪問程序.

???????? 先來看結(jié)構(gòu)圖:



?

DataAccess類,用反射技術(shù),取代了抽象工廠中的IFactory,SqlServerFactoryAccessFactory
????
具體代碼:
????

Code
public?class?User
????
{
????????
private?int?_id;
????????
public?int?ID
????????
{
????????????
get?{?return?_id;?}
????????????
set?{?_id?=?value;?}
????????}


????????
private?string?_name;
????????
public?string?Name
????????
{
????????????
get?{?return?_name;?}
????????????
set?{?_name?=?value;?}
????????}

????}


????
public?class?Department
????
{
????????
private?int?_id;
????????
public?int?ID
????????
{
????????????
get?{?return?_id;?}
????????????
set?{?_id?=?value;?}
????????}


????????
private?string?_deptName;
????????
public?string?DeptName
????????
{
????????????
get?{?return?_deptName;?}
????????????
set?{?_deptName?=?value;?}
????????}

????}


????
public?interface?IUser
????
{
????????
void?Insert(User?user);

????????User?GetUser(
int?id);
????}


????
public?class?SqlserverUser?:?IUser
????
{
????????
public?void?Insert(User?user)
????????
{
????????????Console.WriteLine(
"在Sqlserver中給User表增加一條記錄");
????????}


????????
public?User?GetUser(int?id)
????????
{
????????????Console.WriteLine(
"在Sqlserver中根據(jù)ID得到User表一條記錄");
????????????
return?null;
????????}

????}


????
public?class?AccessUser?:?IUser
????
{
????????
public?void?Insert(User?user)
????????
{
????????????Console.WriteLine(
"在Access中給User表增加一條記錄");
????????}


????????
public?User?GetUser(int?id)
????????
{
????????????Console.WriteLine(
"在Access中根據(jù)ID得到User表一條記錄");
????????????
return?null;
????????}

????}


????
public?interface?IDepartment
????
{
????????
void?Insert(Department?department);

????????Department?GetDepartment(
int?id);
????}


????
public?class?SqlserverDepartment?:?IDepartment
????
{
????????
public?void?Insert(Department?department)
????????
{
????????????Console.WriteLine(
"在Sqlserver中給Department表增加一條記錄");
????????}


????????
public?Department?GetDepartment(int?id)
????????
{
????????????Console.WriteLine(
"在Sqlserver中根據(jù)ID得到Department表一條記錄");
????????????
return?null;
????????}

????}


????
public?class?AccessDepartment?:?IDepartment
????
{
????????
public?void?Insert(Department?department)
????????
{
????????????Console.WriteLine(
"在Access中給Department表增加一條記錄");
????????}


????????
public?Department?GetDepartment(int?id)
????????
{
????????????Console.WriteLine(
"在Access中根據(jù)ID得到Department表一條記錄");
????????????
return?null;
????????}

????}


????
public?class?DataAccess
????
{
????????
private?static?readonly?string?AssemblyName?=?"抽象工廠模式";
????????
private?static?readonly?string?db?=?"Sqlserver";
????????
//private?static?readonly?string?db?=?"Access";

????????
public?static?IUser?CreateUser()
????????
{
????????????
string?className?=?AssemblyName?+?"."?+?db?+?"User";
????????????
return?(IUser)Assembly.Load(AssemblyName).CreateInstance(className);
????????}


????????
public?static?IDepartment?CreateDepartment()
????????
{
????????????
string?className?=?AssemblyName?+?"."?+?db?+?"Department";
????????????
return?(IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);
????????}

????}

調(diào)用代碼:

Code
????????????User?user?=?new?User();
????????????Department?dept?
=?new?Department();

????????????IUser?iu?
=?DataAccess.CreateUser();

????????????iu.Insert(user);
????????????iu.GetUser(
1);

????????????IDepartment?id?
=?DataAccess.CreateDepartment();
????????????id.Insert(dept);
????????????id.GetDepartment(
1);

????????????Console.Read();
????????}


????現(xiàn)在我們要增加Oracle數(shù)據(jù)訪問,相關(guān)類的增加是不可避免的,這點(diǎn)是無論我們用什么方法都解決不了的,這是擴(kuò)展,依照開發(fā)-封閉原則,對(duì)于擴(kuò)展,我們開放,但對(duì)與修改我們關(guān)閉。就現(xiàn)在的代碼中,我們要換Oracle很容易,只需將db=”Sqlserver”換成db=”O(jiān)racle”
????
現(xiàn)在我們需要增加Product,只需增加三個(gè)與Product相關(guān)的類,再修改一下DataAccess,在其中增加一個(gè)創(chuàng)建Product的方法就可以了。
????
現(xiàn)在我們要更換數(shù)據(jù)訪問程序是,我們還需要修改程序,重新編譯,我們可以利用配置文件來解決這個(gè)問題,首先要在我們的項(xiàng)目中添加config文件,內(nèi)容如下:

Code
<?xml?version="1.0"?encoding="utf-8"??>
<configuration>
????
<appSettings>
????????
<add?key="DB"?value="Sqlserver"/>
????
</appSettings>
</configuration>


再在項(xiàng)目中引用

System.configuration,并在程序頭增加using System.configuration;, 然后修改DataAccess類的字段db的賦值代碼:
Code
class?DataAccess
????
{
????????
private?static?readonly?string?AssemblyName?=?"抽象工廠模式";
????????
private?static?readonly?string?db?=?ConfigurationManager.AppSettings["DB"];
????????
????????
public?static?IUser?CreateUser()
????????
{
????????????
string?className?=?AssemblyName?+?"."?+?db?+?"User";
????????????
return?(IUser)Assembly.Load(AssemblyName).CreateInstance(className);
????????}


????????
public?static?IDepartment?CreateDepartment()
????????
{
????????????
string?className?=?AssemblyName?+?"."?+?db?+?"Department";
????????????
return?(IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);
????????}

????}


3.總結(jié)

???????? 使用反射工廠的優(yōu)點(diǎn)是極大的減少了工廠類的數(shù)量,降低了代碼的冗余,并且系統(tǒng)更容易擴(kuò)展,增加新類型后,不需要修改工廠類。

???????? 使用反射工廠的代價(jià)是工廠與產(chǎn)品之間的依賴關(guān)系不明顯,由于動(dòng)態(tài)綁定,因此理論上可以用一個(gè)工廠完成很多類型的實(shí)例化,從而使得代碼不容易理解。另外就是增加了測(cè)試難度,因?yàn)閯?chuàng)建是動(dòng)態(tài)完成的。

???????? 采用反射技術(shù)創(chuàng)建的反射工廠可以使系統(tǒng)更靈活,使工廠和產(chǎn)品之間的依賴關(guān)系更小。在.NET的項(xiàng)目中大量的使用了反射工廠取代的傳統(tǒng)的工廠。

總結(jié)

以上是生活随笔為你收集整理的设计模式学习笔记六:.NET反射工厂的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。