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

发布于 2024-10-01 14:42:32 字数 1181 浏览 8 评论 0原文

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

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;}
}

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

非常感谢

编辑

我想到的一个想法是抽象类中的工厂方法,它返回具体类。例如

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(...);
            }
            .... 
        }
    }

,但在这个例子中,我不确定如何为每个具体类型传递独特的参数。即宽度、高度、字数...

I have a family of classes which i feel needs some encapsulation over the creation methods. Take for example:

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;}
}

Given this class hierarchy, what is the best method for me to encapsulate the creation method of each distinct classes? It would be helpful if you can provide some examples of using a factory class?

Many Thanks

Edit

One idea i had i mind was a Factory method in the abstract class which returns the concrete class. 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(...);
            }
            .... 
        }
    }

But in this example im not sure how i can pass the unqiue parameters for each of the concrete types. i.e Width, Height, WordCount...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

羅雙樹 2024-10-08 14:42:32

为每种文件类型创建不同的工厂怎么样?您的 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);
    }
}

How about creating a different factory for each of these file types? Your File.Create(...) method can choose which one to invoke, and then each factory would be responsible for reading a particular type of file, creating the data necessary to generate the File object you want to have, and returning it.

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);
    }
}
此刻的回忆 2024-10-08 14:42:32

我认为您有几个选择:

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

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

这里你将失去的最大的东西是这些参数的编译时错误检查 - 如果调用代码没有提供,例如,WordFile 类的字数统计参数,则不会出现编译器错误。

You've got a couple of options, I think:

  1. Define some sort of object (such as a Dictionary) that contains the parameters that each different instance should have. The code which calls the factory method will be responsible for constructing the Dictionary correctly (you should probably make sure the keys are constants defined in each of the sub-classes) and passing it in. The constructor for each of the sub-classes will be responsible for validating the object and ensuring that everything they need is present. If it isn't, they should throw an exception providing reasonable information.

  2. If the parameters aren't directly needed for object construction, you could add them as properties. The calling code would be responsible for setting these properties, and the subclasses would need to validate the properties have been set when they need the properties. If they haven't, then again they should throw an exception providing reasonable information.

The biggest thing you're going to lose here is compile-time error checking of these parameters - if the calling code isn't providing, for instance, the word count parameter for the WordFile class, there won't be a compiler error.

遗心遗梦遗幸福 2024-10-08 14:42:32

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

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

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);

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

It looks like you are trying to create objects of classes which have different parameters to their constructors. The Factory pattern does not help you solve that. It does help solve the fact that depending on the filename it will create an appropriate object. To pass them different parameters, you will have to do that once the objects are created.

One solution could be to have a list or array of arguments to be passed and your factory could determine the type of object to create and then use the parameter list or array to create the desired object.
For example

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);

The only benefit here of using a factory here is that your code will be independent of the specific implementations of the various File Type classes that you implementing. Otherwise, I would suggest not use to use this pattern and simply create your objects directly as you already know what to create.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文