多态
书接上回,继续探究。
颠覆之前的构思。势在必行。
1、Word,pdf,mp3,txt,avi等将这些业务实体抽象为对象,并在每个对象内部来处理该文件的打开,这样各个类型之间的交互操作就被分离出来,这样很好的体现了职责单一的原则。
2、将对象的属性与行为相分离,将文件打开这一行为封装为接口,再有其他类来实现这一接口,利于系统的扩展减少类与类之间的依赖。
将相似的类抽象出公共基类,在基类中实现具有共性的特征,并有子类继承父类的特征。文档的基类可以抽象为DocLoader;图片格式的基类抽象为ImageLoader。这种方式体现了面向对象的开放关闭原则:对扩展开放,对修改关闭。
namespace Polymorphisn
{
/// <summary>
/// 通用接口定义
/// </summary>
internal interface IFileOpen
{
void Open();
}
}
定义所有文件的公共基类
namespace Polymorphisn
{
/// <summary>
/// 所有文件的基类
/// </summary>
abstract class Files : IFileOpen
{
private FileType fileType = FileType.doc;
public FileType FileType { get { return fileType; } }
/// <summary>
/// 抽象方法,除了文件打开抽象方法,还可以实现其他通用文件处理操作。
/// </summary>
public abstract void Open();
//实现了IFileOpen接口
}
}
有了文件类型的公共基类,是时候实现其派生类了
/// Doc文件
abstract class DocFile : Files
{
/// <summary>
/// 计算页数
/// </summary>
/// <returns></returns>
public int GetPageCount() { return 0; }
}
/// 图片文件
abstract class ImageFile : Files
{
public void ZommIn()
{
//放大比例
}
public void ZommOut()
{
//缩小比例
}
}
终于是实现具体资料类的时候了,在此以 Word 类型为例来说明具体的实现:
class WORDFile : DocFile
{
/// <summary>
/// 打开Doc文件
/// </summary>
public override void Open()
{
Console.WriteLine("Open the Word file.");
}
//其他类型的实现类似于此,不同之处在于不同的类型有不同 Open 实现规则,
//以应对不同资料的打开操作
}
class PDFFile : DocFile
{
public override void Open()
{
Console.WriteLine("Open the PDF file.");
}
}
同时提供了一个资料管理类来进行资料的统一管理:
internal class LoadManager
{
private IList<Files> files = new List<Files>();
public IList<Files> Files { get { return files; } }
public void LoadFiles(Files file)
{
files.Add(file);
}
/// <summary>
/// 打开所有文件资料
/// </summary>
public void OpenAllFiles()
{
foreach (var file in files)
{
file.Open();
}
}
/// <summary>
/// 打开单个文件资料
/// </summary>
/// <param name="file"></param>
public void OpenFile (IFileOpen file)
{
file.Open();
}
/// <summary>
/// 获取文件类型
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public FileType GetFileType(string fileName)
{
//根据指定路径返回文件类型
FileInfo fileInfo = new FileInfo(fileName);
return (FileType)Enum.Parse(typeof(FileType), fileName);
}
}
实现简单的客户端,并根据所需进行文件的加载:
public static void Main()
{
//启动文件加载器
LoadManager loadManager = new LoadManager();
loadManager.LoadFiles(new WORDFile());
loadManager.LoadFiles(new BusinessLogicImage());
//...
}
随需而变的业务
新的视频格式出现:MPEG
/// <summary>
/// 视频格式继承Files公用基类
/// </summary>
abstract class MediaFile : Files
{
}
首先是增加处理 MPEG 文件的类型
MPEGFile,并让它继承自 MediaFile,实现具体的 Open 方法即可。
class MPEG : MediaFile
{
public override void Open()
{
Console.WriteLine("Open the MPEG file");
}
}
接着就是添加处理新文件的加载操作,如下:
// 在没有对原系统进行修改的继承上,只需加入简单的类型和操作即可完成原来看似复杂的操作
loadManager.LoadFiles(new MPEG());
事实证明,只要有更合理的设计与架构,在基于面向对象和.NET 框架的基础上,完全可以实现类
似于插件的可扩展系统,并且无需编译即可更新扩展。