需要一些帮助来创建一个工厂类来封装对象创建

时间:2010-11-11 15:24:23

标签: c# factory encapsulation

我有一系列类,我觉得需要对创建方法进行一些封装。举个例子:

public abstract class File
{   
    protected File(string fileName)
    {
        Name = fileName;
    }
    string Name {get; set;}
}

public class ImageFile : File
{
    protected ImageFile(string fileName, int width, int Height) :base(fileName)
    {
        Height = height;
        Width = width;  
    }

    int Height {get; set;}
    int Width {get; set;}
}

public class WordFile : File
{
    protected WordFile(string fileName, int wordCount) :base(fileName)
    {
        WordCount = wordCount;
    }

   int WordCount {get; set;}
}

鉴于这个类层次结构,对于我来说,封装每个不同类的创建方法的最佳方法是什么?如果你能提供一些使用工厂类的例子会很有帮助吗?

非常感谢

修改

我想到的一个想法是抽象类中的Factory方法,它返回具体类。 e.g

public abstract class File
    {   
        protected File(string fileName)  
        {
         ....
        } 

        string Name {get; set;}
        public static File Create(string fileName) 
        {
            if(filename.Contains("jpg")
            {
               return new ImageFile(...);
            }
            .... 
        }
    }

但是在这个例子中我不知道如何为每个具体类型传递unqiue参数。即Width,Height,WordCount ......

3 个答案:

答案 0 :(得分:2)

如何为每种文件类型创建不同的工厂?您的File.Create(...)方法可以选择要调用的方法,然后每个工厂都负责读取特定类型的文件,创建生成您想要的File对象所需的数据,然后返回它。

public static File Create(string fileName)
{
    var factory = GetFactory(fileName);
    return factory.CreateFile(fileName);
}

public static IFileFactory GetFactory(string fileName)
{
    if(Path.GetExtension(fileName).toUpperInvariant() == ".JPG")
    {
        return new ImageFileFactory();
    }
    //...
}

public interface IFileFactory
{
    File CreateFile(string fileName);
}
public class ImageFileFactory : IFileFactory
{
    public File CreateFile(string fileName)
    {
        int width = GetWidth(fileName);
        int height = GetHeight(fileName);
        return new ImageFile(fileName, width, height);
    }
}

答案 1 :(得分:0)

我认为你有几个选择:

  1. 定义某种对象(例如Dictionary),其中包含每个不同实例应具有的参数。调用工厂方法的代码将负责正确构造字典(您应该确保键是在每个子类中定义的常量)并将其传入。每个子类的构造函数将是负责验证对象并确保其所需的一切都存在。如果不是,他们应该提供一个提供合理信息的例外。

  2. 如果对象构造不直接需要参数,则可以将它们添加为属性。调用代码将负责设置这些属性,并且子类需要验证在需要属性时已设置的属性。如果他们没有,那么他们应该再提出一个提供合理信息的例外。

  3. 这里你要失去的最重要的事情是这些参数的编译时错误检查 - 如果调用代码没有提供,例如,WordFile类的单词计数参数,则不会有编译错误。

答案 2 :(得分:0)

看起来您正在尝试创建具有与其构造函数不同的参数的类的对象。工厂模式无法帮助您解决这个问题。它确实有助于解决这样一个事实:根据文件名,它将创建一个合适的对象。要为它们传递不同的参数,您必须在创建对象后执行此操作。

一种解决方案可能是传递一个列表或参数数组,您的工厂可以确定要创建的对象类型,然后使用参数列表或数组创建所需的对象。 例如

List<int> param = new List<int>();
param.Add(200);   //So add as many parameters as you want
//The factory will simply pass those to the objects it is creating
//And then pass this pass this param to your File.Create() method
File.Create(param);

此处使用工厂的唯一好处是您的代码将独立于您实现的各种文件类型类的特定实现。否则,我建议不要使用此模式,只需直接创建对象,因为您已经知道要创建什么。