一不变应万变的多态---.net 多态理解

来源:互联网 发布:幼儿园手指数算法视频 编辑:程序博客网 时间:2024/04/27 22:05
— 将Word、PDF、TXT、JPG、AVI等业务实体抽象为对象,并在每个相应的对象内部来处理本对象类型的文件打开工作,这样各个类型之间的交互操作就被分离出来,这样很好地体现了职责单一原则的目标。
— 将各个对象的属性和行为相分离,将文件打开这一行为封装为接口,再由其他类来实现这一接口,有利于系统的扩展同时减少了类与类的依赖。
图1-12  万能加载器系统设计
— 将相似的类抽象出公共基类,在基类中实现具有共性的特征,并由子类继承父类的特征,例如Word、PDF、TXT的基类可以抽象为DocLoader;而JPG和GIF的基类可以抽象为ImageLoader,这种实现体现的是面向对象的开放封闭原则:对扩展开放,对修改关闭。如果有新的类型需要扩展,则只需继承合适的基类成员,实现新类型的特征代码即可。
— 实现可柔性扩展的接口机制,能够更加简单的实现增加新的文件类型加载程序,也能够很好的扩展打开文件之外的其他操作,例如删除、重命名等修改操作。
— 实现在不需要调整原系统,或者很少调整原系统的情况下,进行功能扩展和优化,甚至是无需编译的插件式系统。
下面是具体的实现,首先是通用的接口定义:
interface IFileOpen
{
    void Open();
}
接着定义所有文件类型的公共基类,因为公共的文件基类是不可以实例化的,在此处理为抽象类实现会更好,详细为:
abstract class Files: IFileOpen
{
    private FileType fileType = FileType.doc;
    public FileType FileType
    {
        get { return fileType; }
    }
    public abstract void Open();
}
基类Files实现了IFileOpen接口,不过在此仍然定义方法为抽象方法。除了文件打开抽象方法,还可以实现其他的通用文件处理操作,例如文件删除Delete、文件重命名ReName和获取文件路径等。有了文件类型的公共基类,是时候实现其派生类了。经过一定的分析和设计,小王没有马上提供具体的资料类型类,而是对派生类型做了归档,初步实现文件类型、图片类型和媒体类型三个大类,将具体的文件类型进一步做了抽象:
    abstract class DocFile: Files
    {
        public int GetPageCount()
        {
            //计算文档页数
        }
    }
    abstract class ImageFile : Files
    {
        public void ZoomIn()
        {
            //放大比例
        }
        public void ZoomOut()
        {
            //缩小比例
        }
}
终于是实现具体资料类的时候了,在此以Word类型为例来说明具体的实现:
class WORDFile : DocFile
{
    public override void Open()
    {
        Console.WriteLine("Open the WORD file.");
    }
}
其他类型的实现类似于此,不同之处在于不同的类型有不同Open实现规则,以应对不同资料的打开操作。
小王根据架构的设计,同时提供了一个资料管理类来进行资料的统一管理:
class LoadManager
{
    private IList<Files> files = new List<Files>();
    public IList<Files> Files
    {
        get { return files; }
    }
    public void LoadFiles(Files file)
    {
        files.Add(file);
    }
    //打开所有资料
    public void OpenAllFiles()
    {
        foreach(IFileOpen file in files)
        {
            file.Open();
        }
    }
    //打开单个资料
    public void OpenFile(IFileOpen file)
    {
        file.Open();
    }
    //获取文件类型
    public FileType GetFileType(string fileName)
    {
        //根据指定路径文件返回文件类型
        FileInfo fi = new FileInfo(fileName);
        return (FileType)Enum.Parse(typeof(FileType), fi.Extension);
    }
}
最后,小王实现了简单的客户端,并根据所需进行文件的加载:
class FileClient
{
    public static void Main()
    {
        //首先启动文件加载器
        LoadManager lm = new LoadManager();
        //添加要处理的文件
        lm.LoadFiles(new WORDFile());
        lm.LoadFiles(new PDFFile());
        lm.LoadFiles(new JPGFile());
        lm.LoadFiles(new AVIFile());
        foreach (Files file in lm.Files)
        {
            if (file is 爷爷选择的)       //伪代码
            {
                lm.OpenFile(file);
            }               
        }
    }
}