上节我们讲到数据对象创建的管理,那么如何管理数据访问类的对象创建呢?先从为什么需要设计模式的原理说起吧
为了更好的理解设计思想,我尽可能的用实例来演示推进。但随着需求的增加,程序将越来越复杂。此时就有修改设计的必要,重构和设计模式就可以派上用场了。最后当设计渐趋完美后,你会发现,即使需求不断增加,你也可以神清气闲,不用为代码设计而烦恼了。
Code
using System;
using System.Collections.Generic;
using System.Text;
/*场景摸拟:
小明:听说导演要重拍天龙八部,你去吗?
小华:我哪有这个条件啊,不过毕竟我是学影视导演方向的,如果我能做导演就好了。
小明:去你的,就你那水平,不过,说真的,如果让你做导演,你会怎么做?
小华说:我会先招男主角,比如:乔峰和段誉。看看我是如何招的?
*/
namespace ConsoleApplication3
{
//我们定义了两个类乔峰和段誉,并且要求他们都会打,所以我们定了strike方法
class Qiaofeng : Nanzhujiao
{
public override void strike()
{
Console.Write("this is qiaofeng's action");
Console.Read();
}
}
class Duanyu : Nanzhujiao
{
public override void strike()
{
Console.Write("this is qiaofeng's action");
Console.Read();
}
}
//现在乔峰和段誉都具有打这个方法,为什么我们不能把它们提出来单独的做成一个类呢?于是我们可以这样,因为是抽像类,所以不能实便化
public abstract class Nanzhujiao
{
public abstract void strike();
}
//现在我要指派乔峰上场了,如何区分到底是谁上场呢?
class daoyan
{
static void test(Nanzhujiao nan)
{
nan.strike();
}
}
//此时导演如果决定起用虚猪,那么我们仅需要编写虚猪类即可,其它的可不动。
//现在三个男主角我们已经全部起用了,现在导演要招女演员了,怎么办?难道我们还让王语嫣去继承男演员吗?当然不行,那么我们这样做:
//我们定义了两个类王语嫣和穆姐姐
class Wangyuyan : luzhujiao
{
public override void strike()
{
Console.Write("this is Wangyuyan's action");
Console.Read();
}
}
class Mujiejie : luzhujiao
{
public override void strike()
{
Console.Write("this is Mujiejie's action");
Console.Read();
}
}
//现在王语嫣和穆姐姐都具有打这个方法
public abstract class luzhujiao
{
public abstract void strike();
}
//现在导演觉得太烦了,既要管男演员,又要管女演员,太累了,于是导演定义了一个标准:要都会打就行了。
//因为接口这个利器你还没有用上(虽然你也可以用抽象类,但在C#里只支持类的单继承)
public interface Inormal
{
void strike();
}
//不管是男演员还是女演员都要照标准做,于是:
我们修改上面的两个抽象类,让它们实现上面的Inormal,如下:
Code
public abstract class Nanzhujiao : Inormal
{
public abstract void strike();
}
public abstract class luzhujiao : Inormal
{
public abstract void strike();
}
通过上面的分析,我们现在可以让导演来指派该谁上场了:如下:
Code
//于是,导演就可以用下面的方法来指派人了
public class daoyan
{
public static void test(Inormal nan)
{
nan.strike();
}
}
//我们可以得出这样一个结论:在调用类对象的属性和方法时,尽量避免将具体类对象作为传递参数,而应传递其抽象对象,
//更好地是传递接口,将实际的调用和具体对象完全剥离开,这样可以提高代码的灵活性。
Code
//下面来看看我们如何去调用
class Program
{
static void Main(string[] args)
{
Inormal nan1=null;
string arg = "wangyuyan";//此处可以根据下拉框选择来选定
switch (arg)
{
case "Qiaofeng":
nan1 = new Qiaofeng();
break;
case "Duanyu":
nan1 = new Duanyu();
break;
case "wangyuyan":
nan1 = new Wangyuyan();
break;
}
daoyan.test(nan1);
}
}
这些讨厌的switch语句又出现了,有没方法把这些烦烦的switch消掉呢。我们来努力一下,该是让工厂模式来生产对象的时候了:
Code
public interface IcreateFactory
{
Inormal CreateObject();
}
public class qiaofengCreate : IcreateFactory
{
public Inormal CreateObject()
{
return new Qiaofeng();
}
}
public class wangyuyianCreate : IcreateFactory
{
public Inormal CreateObject()
{
return new Wangyuyan();
}
}
这样,由工厂模式直接创造出对象,比如:乔峰,段誉,王语嫣等,下面就可以这样调用了:
IcreateFactory i = new qiaofengCreate();
i.CreateObject().strike();
通过以上方法我们部分的消除了switch语句,因为总是要用条件去判断到底该实例化哪个类。幸运的是,.net给我们提供了一种非常好的机制来消除这种现象,这就是利用类名反射,我们来看一下如何做:
首先,在web.config文件中添加如下配置:
Code
<appSettings>
<add key="WebDAL" value="Pyllot.EC.Cargo.SqlServerDAL"/>
<!--数据库连接字符串-->
<add key="SiteSqlServer" value="Server=(local);Database=Northwind;uid=sa;pwd=sa;"/>
<add key="SiteMySql" value="Host=localhost;port=3306;UserName=root;Password=mfm;Database=ec_cargo;"/>
</appSettings>
然后动态根据类名反射,从而动态实例化类,如下:
Code
public static Pyllot.EC.Cargo.IDAL.ICategory CreateCategory()
{
string className = ConfigReader.Read("WebDAL") + ".Category";
return (Pyllot.EC.Cargo.IDAL.ICategory)Assembly.Load(ConfigReader.Read("WebDAL")).CreateInstance(className);
}
那么,上面的switch或工厂模式可以统统丢掉了,我们仅需要将以上的.Category改为qiaofeng,wangyuyan等,另外改一下配置文件中的目录即可。
好了,这个系列二分析了面向对象的封装,继承,抽像,接口,工厂模式,下一系列我们将这种思想活用于架构中,敬请期待