Effective C# Item33:限制类型的可见性

    并不是所有人都需要看到所有的类型,因此我们创建的每一个类型也没有必要设置为public,我们应该为每个类型提供最低的可见性,只要能够达到目的就可以了。

    Visual Studio中创建新的类型时,提供的默认可见性是internal,在程序集内是可见的。如果我们将类型声明为public,那么任何使用这个程序集的代码都可以访问这个类型,这样在今后的维护过程中,很可能会添加不必要的重复工作,因为类型的可见性越低,在以后更新时的修改工作量就越低,访问某块代码的地方越少,更改这块代码后所需要做的改动也就越少。

    我们应该仅仅暴露哪些需要暴露的功能,对于其他类型,我们可以使用不同的方式,降低它们的可见性,例如将类型设置为internal或者private,注意可见性为private的类型也是可以实现接口的,我们还可以将这些类设置为内部类。

    来看下面的代码变化过程,首先是第一版。

1 public class PhoneValidator
2 {
3 public bool ValidateNumber( PhoneNumber ph )
4 {
5 // perform validation.
6 // Check for valid area code, exchange.
7   return true;
8 }
9 }

    上述代码提供了验证电话号码的功能,用户在使用时,直接实例化PhoneValidator对象,然后调用对象的ValidateNumber方法进行验证,这里的PhoneValidator类型是public的。

    随着时间的推进,我们的验证方式可能会变得比较丰富,这时,就会产生第二版代码。

代码
1 public interface IPhoneValidator
2 {
3 bool ValidateNumber( PhoneNumber ph );
4 }
5
6
7 internal class USPhoneValidator : IPhoneValidator
8 {
9 public bool ValidateNumber( PhoneNumber ph )
10 {
11 // perform validation.
12 // Check for valid area code, exchange.
13 return true;
14 }
15 }
16
17
18 internal class InternationalPhoneValidator : IPhoneValidator
19 {
20 public bool ValidateNumber( PhoneNumber ph )
21 {
22 // perform validation.
23 // Check international code.
24 // Check specific phone number rules.
25 return true;
26 }
27 }
28
    上述代码中定义了一个名为IPhoneValidator的接口,接口的类型是public,然后定义了两个实现了这个接口的类型,分别是USPhoneValidator和InternationalPhoneValidator,这两个类型都是internal的。这时用户在使用时,需要声明一个IPhoneValidator类型的实例,然后调用实例的ValidateNumber方法。注意:这里用户不能够直接实例对象了,这个过程需要放置在IPhoneValidator类型所在的程序集中,可以使用工厂模式进行实例化。

    上面的示例中,体现的软件设计原则:1)面向接口编程,可以使得程序更加灵活;2)命令模式或者模板模式,如果是直接实现接口,那么就是命令模式,如果是采用集成抽象基类的方式,将共通的逻辑放置在基类中,那就是模板模式了。

 

    我们通过公有方式暴露给外界的类和接口应该成为我们的合同:我们必须一致使用下去,程序对外接口越混乱,我们未来的方向就越受限制,我们向外暴露的公有类型越少,将来扩展和更改实现所拥有的选择就越多。

posted @ 2010-01-23 15:23  李潘  阅读(408)  评论(0编辑  收藏  举报