如何将数据传递给使用工厂方法创建的对象

发布于 2024-10-28 05:05:58 字数 671 浏览 1 评论 0原文

我正在通过工厂方法模式创建一系列对象。或多或少像这样:

class CMyFactory  
{
public:
    virtual CMyObject* MakeObject(ObjectType type);
}


CMyObject* CMyFactory::MakeObject(ObjectType type)
{
    CMyObject* newObject = NULL;
    switch (type)
    {
    case type1:
        newObject = new CType1Object;
        break;
    case type2:
        newObject = new CType2Object;
        break;

    // Other cases here
    }
    return newObject;
}

现在,假设我想将一些数据传递给创建的具体对象。该数据会根据我想要创建的对象的类型而有所不同。

有没有一种干净的方法可以做到这一点?

我想我可以在创建对象后传递数据,但这不太适合工厂。工厂方法的思想是将对象创建的逻辑仅放在一处。因此,如果我稍后必须处理对象类型相关的类,那么与直接创建我想要的类型的对象没有太大区别。

关于如何解决这个问题有什么想法吗?也许工厂方法模式不是我需要的?

I'm creating a series of objects through a Factory Method pattern. More or less like so:

class CMyFactory  
{
public:
    virtual CMyObject* MakeObject(ObjectType type);
}


CMyObject* CMyFactory::MakeObject(ObjectType type)
{
    CMyObject* newObject = NULL;
    switch (type)
    {
    case type1:
        newObject = new CType1Object;
        break;
    case type2:
        newObject = new CType2Object;
        break;

    // Other cases here
    }
    return newObject;
}

And now, suppose I want to pass some data to the concrete object created. That data would be different depending on the type of object that I want to create.

Is there a clean way of doing so?

I guess I could pass the data after creating the object, but that would not fit well with a Factory. The idea of the factory method is to put the logic of object creation in one place only. So if I have to deal with object type-dependant classes later, there's not much difference with creating the object directly of the type I want.

Any ideas on how to solve this? Maybe the Factory Method pattern is not what I need?

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

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

发布评论

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

评论(4

柏林苍穹下 2024-11-04 05:05:58

您可以做的一件事是将它传递给构造函数,如下所示:

class CMyFactory  
{
public:
    virtual CMyObject* MakeObject(ObjectType type, ParamType param);
}


CMyObject* CMyFactory::MakeObject(ObjectType type, ParamType param)
{
    CMyObject* newObject = NULL;
    switch (type)
    {
    case type1:
        newObject = new CType1Object(param);
        break;
    case type2:
        newObject = new CType2Object(param);
        break;

    // Other cases here
    }
    return newObject;
}

您可以根据参数类型重载 MakeObject,如下所示:

class CMyFactory  
{
public:
    virtual CMyObject* MakeObject(ObjectType type, ParamType param);
    virtual CMyObject* MakeObject(ObjectType type, OtherParamType param);
}

CMyObject* CMyFactory::MakeObject(ObjectType type, ParamType param)
{
    CMyObject* newObject = NULL;
    switch (type)
    {
    case type1:
        newObject = new CType1Object(param);
        break;
    case type2:
        newObject = new CType2Object(param);
        break;

    // Other cases here
    }
    return newObject;
}


CMyObject* CMyFactory::MakeObject(ObjectType type, OtherParamType param)
{
    CMyObject* newObject = NULL;
    switch (type)
    {
    case type3:
        newObject = new CType3Object(param);
        break;
    case type4:
        newObject = new CType4Object(param);
        break;

    // Other cases here
    }
    return newObject;
}

这种方法的缺点是工厂的用户需要知道它需要什么样的参数传递要创建的对象类型,但这对于这种方法来说可能是不可避免的。

我想我可以在创建对象后传递数据,但这不太适合工厂。工厂方法的思想是将对象创建的逻辑仅放在一处。因此,如果我稍后必须处理对象类型相关的类,那么与直接创建我想要的类型的对象没有太大区别。

我同意:您不需要在创建后将数据传递给对象。这相当于两步创建,有点违背了目的。

不过,使用工厂方法不仅可以隐藏对象的构造方式:它还可以隐藏所创建对象的实际类型。一个典型的例子是 WidgetFactory,它将创建各种小部件,但始终返回一个 Widget* ,允许您的代码在处理创建的小部件时利用多态性 -并允许库实现者在后台更改实现而不破坏任何客户端代码

One thing you could do is pass it to the constructor, like so:

class CMyFactory  
{
public:
    virtual CMyObject* MakeObject(ObjectType type, ParamType param);
}


CMyObject* CMyFactory::MakeObject(ObjectType type, ParamType param)
{
    CMyObject* newObject = NULL;
    switch (type)
    {
    case type1:
        newObject = new CType1Object(param);
        break;
    case type2:
        newObject = new CType2Object(param);
        break;

    // Other cases here
    }
    return newObject;
}

You can overload MakeObject according to the parameter type, like this:

class CMyFactory  
{
public:
    virtual CMyObject* MakeObject(ObjectType type, ParamType param);
    virtual CMyObject* MakeObject(ObjectType type, OtherParamType param);
}

CMyObject* CMyFactory::MakeObject(ObjectType type, ParamType param)
{
    CMyObject* newObject = NULL;
    switch (type)
    {
    case type1:
        newObject = new CType1Object(param);
        break;
    case type2:
        newObject = new CType2Object(param);
        break;

    // Other cases here
    }
    return newObject;
}


CMyObject* CMyFactory::MakeObject(ObjectType type, OtherParamType param)
{
    CMyObject* newObject = NULL;
    switch (type)
    {
    case type3:
        newObject = new CType3Object(param);
        break;
    case type4:
        newObject = new CType4Object(param);
        break;

    // Other cases here
    }
    return newObject;
}

Such an approach has the disadvantage that the user of your factory needs to know what kind of parameter it needs to pass for which type of object to be created, but that is probably inevitable with this approach anyway.

I guess I could pass the data after creating the object, but that wouldn't fit well with a Factory. The idea of the factory method is to put the logic of object creation in one place only. So if I have to deal with object type-dependant classes later, there's not much difference with creating the object directly of the type I want.

I agree: you shouldn't need to pass the data to the object after creation. That would amount to a two-step creation which kinda defeats the purpose.

Using a factory method doesn't just hide the way the object is constructed, though: it can also hide the actual type of the object created. A classic example is a WidgetFactory, which will create all kinds of widgets but will always return a Widget* allowing your code to take advantage of polymorphism in dealing with the widget created - and allowing the library implementor to change the implementation behind the scenes without breaking any client code

内心荒芜 2024-11-04 05:05:58

我不确定我是否正确理解了这个问题。您说您有参数传递给工厂方法,这些参数取决于要创建的类型。如果您足够了解创建正确的参数集(并且知道要传递什么 ObjectType),那么为什么还要有一个工厂,为什么不直接创建对象呢?工厂的想法是隐藏类型,但在这里你(隐式地)暴露了类型。

I'm not sure I understand the question correctly. You say you have parameters to pass to the factory method that depend on the type to be created. If you know enough to create the correct set of parameters, (and if ou know what ObjectType to pass), then why have a factory at all, why not just create the objects directly? The idea of a factory is to hide the type, but here you are (implicitly) exposing the type.

恍梦境° 2024-11-04 05:05:58

数据完全不同吗?或者物体完全不同?

例如,是否都是交易,但一种是现金,一种是支票,一种是信用卡?在这种情况下,数据中会有一些共同点(金额、日期等)和一些不同的数据(例如卡号)?

在这种情况下,您可以创建一个基类(例如 CTransaction)并继承 CCreditTransaction 等。然后您可以让您的 MakeObject 也采用 CTransaction 对象。

如果我们谈论 CType1Object 是一个事务,CType2Object 是库存系统中的一个项目,而 CType3Object 是一些小部件,那么我认为您不需要调整您的实现。

您的工厂可能类似于 MakeTransaction(...) ,并且有一个单独的 MakeWidget(...) 工厂和一个单独的 MakeInventoryItem(...) 工厂等

Is the data completely different? Or are the objects completely different?

For example, are they all transactions, but one is cash and one is a check and one is a credit card? In which case there would be some commonality in data (amount, date etc) and some that is distinct (card number, for example)?

In this case, you could create a base class (e.g. CTransaction) and have inheritance for CCreditTransaction etc. You could then have your MakeObject take a CTransaction object as well.

If we're talking about CType1Object is a Transaction and CType2Object is an item from an inventory system and CType3Object is some widget then I don't think you'll need to adjust your implementation.

Your factory could be something like MakeTransaction(...) and have a separate factory for MakeWidget(...) and a separate factory for MakeInventoryItem(...) etc

轻许诺言 2024-11-04 05:05:58

在反序列化的情况下,这非常简单:在串行流中,有一些令牌(枚举类型),工厂可以从中决定要创建哪个对象。然后可以将串行流传递给虚拟 deserialize() 函数中的对象。毕竟,对象最了解流中包含的数据格式。

否则,可能会使用双重调度机制:您想要创建一些对象,因此数据应该兼容。然而,C++ 中不支持双重调度,因此实现起来相当麻烦(也有依赖)。

In case of deserializing, this is pretty straightforward: in the serial stream, there is some token (enum type) from which the factory can decide which object to create. Then the serial stream can be passed to the object in a virtual deserialize() function. After all the object knows best what format data in the stream contains for him.

Otherwise, a double dispatch mechanism might be used: you want to create some object, so the data should be compatible. However, double dispatch is not supported in C++, so it is quite a hassle (also with dependecies) to implement.

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