笔者近来发觉一件很有趣的事情,当我对工厂模式中Factory生成工厂类下的switch或者if---else进行解耦的时候,结果就会出现插件式机制的影子。当对解耦方法进一步深入探索的时候,发觉工厂模式跟插件式应用框架很相似。到底这种相似程度如何呢?我们就来一起探讨一下吧。在开始前,我们先得理清思路。在整个工厂模式实现的时候,我们需要有个基接口。在这里,最重要的就是基接口的类型选择,我们到底是选择接口还是选择抽象类呢?
以下是比较定义接口与抽象类适应环境及优缺点(摘自MSDN):
1、接口定义实施者必须提供的一组成员的签名。接口不能提供成员的实现细节。例如,ICollection 接口定义与使用集合相关的成员。实现该接口的每个类都必须提供这些成员的实现细节。类可以实现多个接口。
2、类定义每个成员的成员签名和实现细节。Abstract(在 Visual Basic 中为 MustInherit)类的行为在某方面与接口或普通类相同,即可以定义成员,可以提供实现细节,但并不要求一定这样做。如果抽象类不提供实现细节,从该抽象类继承的具体类就需要提供实现。
3、虽然抽象类和接口都支持将协定与实现分离开来,但接口不能指定以后版本中的新成员,而抽象类可以根据需要添加成员以支持更多功能。
4、优先考虑定义类,而不是接口。在库的以后版本中,可以安全地向类添加新成员;而对于接口,则只有修改现有代码才能添加成员。
5、如果需要提供多态层次结构的值类型,则应定义接口。值类型必须从 ValueType 继承,并且只能从 ValueType 继承,因此值类型不能使用类来分离协定和实现。这种情况下,如果值类型要求多态行为,则必须使用接口。
6、请考虑定义接口来达到类似于多重继承的效果。如果一个类型必须实现多个协定,或者协定适用于多种类型,请使用接口。例如,IDisposable 是由许多不同情况下使用的类型实现的。如果要求从基类继承的类可处置,会使类层次结构很不灵活。MemoryStream 等应从其父类继承基于流的协定的类,不可能还是可处置的。
7、有关设计指南的更多信息,请参见 Krzysztof Cwalina 和 Brad Abrams 编著、Addison-Wesley 于 2005 年出版的“Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries”(《框架设计指南:可重用 .NET 库的约定、术语和模式》即《.NET设计规范》)。
此文中,笔者采用接口作为基接口进行实现。即IPublisher接口。
工厂模式中的工厂,其实就是生产实例的一个类。比如此文的例子中为PublisherFactory类。工厂模式,实际上就是定义一个基接口,然后定义其他的类继承于该接口,并实现该接口。然后用一个工厂类封装实例化过程。本文通过定义IPublisher作为基接口,通过TsinghuaUniversityPress和ChinaMachinePress继承该接口并实现该接口。然后再用一个PublisherFactory类工厂进行实例化过程的封装。
代码如下:
/// <summary>
/// 所有出版社的基接口
/// </summary>
public interface IPublisher
{
/// <summary>
/// Publish方法
/// </summary>
void Publish();
}
/// <summary>
/// 清华大学出版社
/// </summary>
public class TsinghuaUniversityPress : IPublisher
{
#region IPublisher 成员
/// <summary>
/// 实现Publish方法
/// </summary>
public void Publish()
{