先说讲到起茧的依赖反转(DI)原则
此原则用来解耦合,使高层次的模块不依赖于低层次的模块
这是啥意思呢?
啥是高层次,啥是低层次?
所谓高层次说白了就是抽象,在程序里面对应我们定义的接口,抽象类
所谓低层次对应的是继承抽象类,实现接口的类型。
当然高层低层也有软件结构层次的意思,其实这个高层的结构一样对于低层来说是很抽象的东西,可以用一样的理解方式来理解结构层次的依赖。
啥是高层不依赖低层?
举个栗子:
就像领导总是抽象的,你们给我把事情做完,谁做(依赖接口),你怎么做(接口方法)哥哥我不管,我不依赖你的实现,哥只知道你有这能力(接口),那做实际事情的总是我们这些码农呗(实例化出来的对象),也就是低层。
做个具体实现的栗子,销售部和开发部,销售部在卖东西需要据客户需求添加新功能的时候,他们老板总不能直接跟你技术部的码农直接对话吧?肯定是跟你技术部的老大直接交涉。这个就是高层抽象不依赖低层实现,抽象只依赖抽象。当然具体实现也只依赖抽象。
{
void AddNewFunction(ICodeFarmer manager);
}
public class SalesManager : ISalesman
{
public void AddNewFunction(ICodeFarmer manager)
{
manager.AddNewFunction();
}
}
public interface ICodeFarmer
{
void AddNewFunction();
}
如上代码。应该一目了然了。
那么其实标准的说法是:
1. 高层次的模块不应该依赖于低层次的模块,两者都应该依赖于抽象接口。
2.抽象接口不应该依赖于具体实现。而具体实现则应该依赖于抽象接口。
对于第2点,啥玩意呢?其实不用多解释,就是第一点的补充而已,抽象都依赖抽象了,你具体实现敢不依赖抽象?你销售部老板都只能找我技术部老板谈,你销售部小罗罗当然也只能和我技术部老大提问题!
关于依赖注入
我再写一个代码:还是上面的栗子,现在把客户的部分也加上来,全部的代码现在如下:
{
void AddNewFunction(ICodeFarmer manager);
}
public class SalesManager : ISalesman
{
public void AddNewFunction(ICodeFarmer manager)
{
manager.AddNewFunction();
}
}
public interface ICodeFarmer
{
void AddNewFunction();
}
public class CodeFarmerManager : ICodeFarmer
{
public void AddNewFunction()
{
//todo
}
}
public interface IClient
{
void AddNewFunction(ISalesman salesman);
}
public class ShaBClient : IClient
{
private ICodeFarmer CodeFarmerManager;
public ShaBClient()
{
CodeFarmerManager = new CodeFarmerManager();
}
public void AddNewFunction(ISalesman salesman)
{
salesman.AddNewFunction(CodeFarmerManager);
}
}
现在问题来了,我客户照道理说我只需要和你销售部的打交道,但是实际的代码里面为了调用销售部的方法,需要和搞代码的�丝也要有依赖
客户表示很不开心。这就是第2个常见的错误,依赖了不该依赖的对象。我觉得这也是依赖中的一个常见的问题。
好吧,怎么解决这个问题呢?
简单,在SalesManager构造函数里面初始化一个ICodeFarmer类型就行了
现在代码变成:
{
void AddNewFunction();
}
public class SalesManager : ISalesman
{
private ICodeFarmer CodeFarmerManager;
public SalesManager()
{
CodeFarmerManager = new CodeFarmerManager();
}
public void AddNewFunction()
{
CodeFarmerManager.AddNewFunction();
}
}
public interface ICodeFarmer
{
void AddNewFunction();
}
public class CodeFarmerManager : ICodeFarmer
{
public void AddNewFunction()
{
//todo
}
}
public interface IClient
{
void AddNewFunction();
}
public class ShaBClient : IClient
{
public void AddNewFunction()
{
ISalesman salesman = new SalesManager();
salesman.AddNewFunction();
}
}
这样问题貌似解决了,但是!!!!!
突然有一天,技术部的经理表示,哥哥我写代码都没时间,还要整天处理这些和外面打交道的事情,哥哥我不干了。这时公司没办法,只好又招聘了一个人,我们暂且叫技术部助理吧(看这就是千变万化的软件世界)
{
public void AddNewFunction()
{
//todo
}
}
销售部门提需求需要跟这位新同事打交道。但是有时候助理他有些问题不明白还是要和技术经理提需求,这里
public SalesManager()
{
CodeFarmerManager = new XXXXXXXX();
}
就形成了一个变化的东西,但是代码里面你总要给new一个啥东西出来呀,怎么搞??
好吧,现在只能这样:在构造函数中指明需要和啥玩意打交道
{
在很多项目里面,字典管理是必备的项目模块,而这个又是比较通用的功能,因此可以单独做成一个通用字典管理,例如这个模块,可以通过集成的方式,使用在我的《Winform开发框架》、《WCF开发框架》、《混合式开发框架》中,这样可以避免代码的重复维护管理,对企业来说,也可以更好管理核心的代码,实现统一的版本更替。通用的字典管理模块,主要包括了字典类型的管理、字典数据的管理,另外,为了方便,还可以加入批量添加数据的功能,以便更适合实际使用场景,加快字典数据的快速录入。借着这个机会,把我的通用字典管理模块的内容大概介绍一下吧。
1、通用字典管理模块的数据管理
普通的字典模块管理如下所示
其中左边的是字典类型的树列表,可以通过右键菜单进行维护,如下界面所示。
批量插入的字典模块管理如下所示
2、全国省市地区的数据字典管理
在最近的项目中,由于需要使用到全国地区的省份、城市、区县这些新政区划的信息,网上的很多数据脚本都是早期的,因此花了一整天的时间,重新校对了这些省份、城市、地区的数据内容,以及编写一个对全国省市地区的数据字典管理模块,由于这些模块的数据是属于数据字典的范畴,因此把这些新政区划的管理也整合通用字典模块里面,以方便更好的应用。
这些全国的新政区划数据,最权威的数据当然来自国家统计局了(http://www.stats.gov.cn/tjbz/xzqhdm/t20130118_402867249.htm),从里面的数据可以看出,这两三年,全国的省份信息基本没有变化,但是城市、区县的数据变化还是不少,如调整了三亚,增加了三沙市,以及合并一些省份的城市,广州等城市的区县也有所变化等等,因此花了不少精力时间来对这些数据进行整理,希望能够给自己方便使用的同时,也方便需要用到这些省份城市行政区的开发人员。
全国地区的省份、城市、区县这些新政区划的管理界面如下所示
继承我通用字典管理的功能,在城市行政区维护的功能上,也增加了一个批量插入数据的操作,以方便更好的数据增加需要(虽然我们很少调整这些城市行政区数据)。
3、如果使用通用字典模块的行政区划数据
上面的字典管理界面只是提供了方便对数据的维护,在实际项目模块中,我们需要增加对省份、城市、区县地区的联动选择支持,如我在《客户关系管理系统CRM》中,客户数据的编辑界面如下所示。
首先需要在绑定省份的字典数据,如下代码所示。
/// 初始化数据字典
/// </summary>
private void InitDictItem()
{
this.txtProvince.Properties.BeginUpdate();
this.txtProvince.Properties.Items.Clear();
List<ProvinceInfo> provinceList = BLLFactory<Province>.Instance.GetAll();
foreach (ProvinceInfo info in provinceList)
{
this.txtProvince.Properties.Items.Add(new CListItem(info.ProvinceName, info.ID.ToString()));
}
this.txtProvince.Properties.EndUpdate();
.....................
}
然后在省份、城市的下拉列表控件的事件中实现其他行政区划数据的显示即可。
{
CListItem item = this.txtProvince.SelectedItem as CListItem;
if (item != null)
{
string provinceId = item.Value;
this.txtCity.Properties.BeginUpdate();
this.txtCity.Properties.Items.Clear();
List<CityInfo> cityList = BLLFactory<City>.Instance.GetCitysByProvinceID(provinceId);
foreach (CityInfo info in cityList)
{
this.txtCity.Properties.Items.Add(new CListItem(info.CityName, info.ID.ToString()));
}
this.txtCity.Properties.EndUpdate();
}
}
private void txtCity_SelectedIndexChanged(object sender, EventArgs e)
{
CListItem item = this.txtCity.SelectedItem as CListItem;
if (item != null)
{
string cityId = item.Value;
this.txtDistrict.Properties.BeginUpdate();
this.txtDistrict.Properties.Items.Clear();
List<DistrictInfo> districtList = BLLFactory<District>.Instance.GetDistrictByCity(cityId);
foreach (DistrictInfo info in districtList)
{
this.txtDistrict.Properties.Items.Add(new CListItem(info.DistrictName, info.ID.ToString()));
}
this.txtDistrict.Properties.EndUpdate();
}
}
4、行政区划sql数据脚本
全国地区的省份、城市、区县这些新政区划的最新Sql脚本下载地址如下所示,希望对大家有帮助。
http://files.cnblogs.com/wuhuacong/CityDistrict.rar
上面的省市区县的行政区划脚本数据,是我通过花了几乎一天的时间进行整理核对的,数据来源于国家统计局2013最新的行政区划数据,绝对有保证,如果对你有帮助,请顺手推荐一下,让更多的人受益,谢谢支持。
本文链接:http://www.cnblogs.com/wuhuacong/p/3464662.html,转载请注明。
没有评论:
发表评论