Effective C# 学习笔记(二十一)为类型定义有限的职责
2011-07-13 16:04
399 查看
将类型或类型的方法对外暴露得越少,你将会获得更多的可扩展性,更容易修改其实现,将会减少更多的单元测试。如.net framework 中的对于枚举集合类型的实现方式,就是用嵌套类的形式来实现的,如下代码所示:List<T>类型封装了Enumerator<T>类型的行为,对外只保留了应暴露的方法。
// For illustration, not complete source
public class List<T> : IEnumerable<T>
{
private class Enumerator<T> : IEnumerator<T>
{
// Contains specific implementation of
// MoveNext(), Reset(), and Current.
public Enumerator(List<T> storage)
{
// elided
}
}
public IEnumerator<T> GetEnumerator()
{
return new Enumerator<T>(this);
}
// other List members.
}
其次,可以使用接口来定义类型行为,对外暴露接口,少暴露类型。
例如电话号码验证的类型,其代码如下:
public class PhoneValidator
{
public bool ValidateNumber(PhoneNumber ph)
{
// perform validation.
// Check for valid area code, exchange.
return true;
}
}
这里定义了一个电话验证类,其有一个方法ValidateNumber来验证电话号码的合法性。但随着需求的变化,该方法的验证规则就会产生不同,如美国的电话号码验证规则和中国的就不一样,这是你可能需要在 ValidatorNumber方法中添加参数,在方法体中添加逻辑判断,以进行应对。但是这样的修改对方法是破坏性的,每添加一种验证方式就要修改一次该方法,增加了维护的难度,这时若能保持原有验证逻辑,又不破坏原有代码,只做新算法的添加才是合理的思路,所以我们会把PhoneValidator抽象为一个接口,其行为定义为接口的方法,这样就可以保证基本的逻辑封装,有可以保证新增的实现不影响过去实现的代码。
代码如下:
public interface IPhoneValidator
{
bool ValidateNumber(PhoneNumber ph);
}
//美国电话号码验证器
internal class USPhoneValidator : IPhoneValidator
{
public bool ValidateNumber(PhoneNumber ph)
{
// perform validation.
// Check for valid area code, exchange.
return true;
}
}
//国际电话号码验证器
internal class InternationalPhoneValidator : IPhoneValidator
{
public bool ValidateNumber(PhoneNumber ph)
{
// perform validation.
// Check international code.
// Check specific phone number rules.
return true;
}
}
//注意上面的电话号码验证器的类都用了internal关键字进行修饰,也就是说这些类只在程序集内部可见,对外不可见,对外可见的只有IPhoneValidator接口
// For illustration, not complete source
public class List<T> : IEnumerable<T>
{
private class Enumerator<T> : IEnumerator<T>
{
// Contains specific implementation of
// MoveNext(), Reset(), and Current.
public Enumerator(List<T> storage)
{
// elided
}
}
public IEnumerator<T> GetEnumerator()
{
return new Enumerator<T>(this);
}
// other List members.
}
其次,可以使用接口来定义类型行为,对外暴露接口,少暴露类型。
例如电话号码验证的类型,其代码如下:
public class PhoneValidator
{
public bool ValidateNumber(PhoneNumber ph)
{
// perform validation.
// Check for valid area code, exchange.
return true;
}
}
这里定义了一个电话验证类,其有一个方法ValidateNumber来验证电话号码的合法性。但随着需求的变化,该方法的验证规则就会产生不同,如美国的电话号码验证规则和中国的就不一样,这是你可能需要在 ValidatorNumber方法中添加参数,在方法体中添加逻辑判断,以进行应对。但是这样的修改对方法是破坏性的,每添加一种验证方式就要修改一次该方法,增加了维护的难度,这时若能保持原有验证逻辑,又不破坏原有代码,只做新算法的添加才是合理的思路,所以我们会把PhoneValidator抽象为一个接口,其行为定义为接口的方法,这样就可以保证基本的逻辑封装,有可以保证新增的实现不影响过去实现的代码。
代码如下:
public interface IPhoneValidator
{
bool ValidateNumber(PhoneNumber ph);
}
//美国电话号码验证器
internal class USPhoneValidator : IPhoneValidator
{
public bool ValidateNumber(PhoneNumber ph)
{
// perform validation.
// Check for valid area code, exchange.
return true;
}
}
//国际电话号码验证器
internal class InternationalPhoneValidator : IPhoneValidator
{
public bool ValidateNumber(PhoneNumber ph)
{
// perform validation.
// Check international code.
// Check specific phone number rules.
return true;
}
}
//注意上面的电话号码验证器的类都用了internal关键字进行修饰,也就是说这些类只在程序集内部可见,对外不可见,对外可见的只有IPhoneValidator接口
相关文章推荐
- ARM学习笔记(五)--ARM编译器支持的数据类型及预定义宏
- Effective C# 学习笔记(四十)使用Dynamic处理匿名类型参数
- 数据结构学习笔记——二叉树的类型定义
- Effective C# 学习笔记(三)在类型转换上多使用 as 和 is
- (原创)c#学习笔记10--定义类成员02--类成员的其他议题03--嵌套的类型定义
- Effective C# 学习笔记(九) 在你的API中避免使用类型转换运算
- HTML&CSS基础学习笔记4-定义文档类型
- MySQL学习笔记(5)之数据定义类型
- Effective C# 学习笔记(二十)不可变的原子值类型的好处
- C++ primer 模版学习笔记-在模板定义内部指定类型
- c++ Premier 学习笔记(unit2 变量和基本类型 -声明与定义
- Objective-C学习笔记(二十一)——函数的返回值与參数类型
- Effecticve学习笔记_条款46:需要类型转换时请为模板定义非成员函数
- C/C++学习笔记25:用typedef定义类型
- Effective C# 学习笔记(三十九) 使用Dynamic处理范型参数的运行时类型
- Effective C# 学习笔记(二十二)多用接口定义实现,少用继承
- Objective-C学习笔记(二十一)——函数的返回值与参数类型
- Lua学习笔记四之用C为Lua定义类型(UserData)
- HTML学习笔记1.3-定义文档类型
- Go语言学习笔记 --- 常量、变量、批量定义与声明、数据类型、类型别名、类型转换