【问题标题】:Factory method pattern uses inheritance while the abstract factory pattern uses composition how?工厂方法模式使用继承而抽象工厂模式使用组合如何?
【发布时间】:2018-07-18 05:59:41
【问题描述】:

我正在研究抽象工厂模式与工厂方法模式之间的区别。 我知道工厂方法仅用于创建一种产品,但抽象工厂是关于创建相关或依赖产品的系列。 但是我不清楚工厂方法模式如何使用继承而抽象工厂模式使用组合。

我知道这已经被问过几次了,谁能用下面的代码解释一下继承和组合是如何发生的?

工厂方法代码

class IRose
{
public:
virtual string Color(void)=0;
};

class RedRose: public IRose
{
public:
string Color(void)
{
    return "Red";
}
};

class YellowRose: public IRose
{
public:
string Color(void)
{
    return "Yellow";
}
};

class IFactory
{
public:
virtual IRose* Create(string type)=0; 
//The factory create method in 90% of cases will take a parameter which 
//determines what kind of the object the factory will return.   
};

class Factory: public IFactory
{
public:
IRose* Create(string type)
{
    if ("Red" == type)
        return new RedRose();

    if ("Yellow" == type)
        return new YellowRose();

    return NULL;
}
};

int main()
{
IRose* p = NULL;
IFactory* f = NULL;

f = new Factory();  //You have to create an INSTANCE of the factory

p = f->Create("Red");
cout<<"\nColor is: "<<p->Color()<<"\n";
delete p;
p = f->Create("Yellow");
cout<<"\nColor is: "<<p->Color()<<"\n";
delete p;
return 1;
}

抽象工厂代码。

class IFridge
{
public:
virtual string Run(void) = 0;
};

class FridgeSamsung : public IFridge
{
public:
string Run(void)
{
    return "You are now running Samsung Fridge\n";
}
};

class FridgeWhirlpool : public IFridge
{
public:
string Run(void)
{
    return "You are now running Whirlpool Fridge\n";
}
};

class IWashingMachine
{
public:
virtual string Run(void) = 0;
};

class WashingMachineSamsung : public IWashingMachine
{
public:
string Run(void)
{
    return "You are now running Samsung Washing Machine\n";
}
};

class WashingMachineWhirlpool : public IWashingMachine
{
public:
string Run(void)
{
    return "You are now running Whirlpool Washing Machine\n";
}
};

class IFactory
{
public:
virtual IFridge* GetFridge(void) = 0;
virtual IWashingMachine* GetWashingMachine(void) = 0;
};

class FactorySamsung : public IFactory
{
IFridge* GetFridge(void)
{
    return new FridgeSamsung();
}

IWashingMachine* GetWashingMachine(void)
{
    return new WashingMachineSamsung();
}
};

class FactoryWhirlpool : public IFactory
{
IFridge* GetFridge(void)
{
    return new FridgeWhirlpool();
}

IWashingMachine* GetWashingMachine(void)
{
    return new WashingMachineWhirlpool();
}
};

int main()
{
IFridge* fridge;    //Client just knows about fridge and washingMachine.
IWashingMachine* washingMachine; //and factory. He will write operations which
IFactory* factory; //work on fridges and washingMachines.

factory = new FactorySamsung; 
//This is the only place where the client
//has to make a choice. 

//The rest of the code below will remain same, even 
//if the factory is changed. He can change the factory and the same range
//of products but from a different factory will be returned. No need to 
//change any code.

fridge = factory->GetFridge();
cout << fridge->Run();
washingMachine = factory->GetWashingMachine();
cout << washingMachine->Run();
cout << "\n";

delete factory;
factory = new FactoryWhirlpool;

//See same client code.
fridge = factory->GetFridge();
cout << fridge->Run();
washingMachine = factory->GetWashingMachine();
cout << washingMachine->Run();
cout << "\n";
delete factory;
return 1;
}

【问题讨论】:

  • 第一个代码在我看来不像典型的工厂方法。带有Create(string type) 的工厂类似乎过于复杂且不必要。你从哪里得到的代码?另外,您从哪里读到“工厂方法模式使用继承而抽象工厂模式使用组合”
  • @guillaume31“工厂方法模式使用继承,而抽象工厂模式使用组合”这个话题已经在stackoverflow本身here中讨论过
  • @guillaume31 我从here 获取的代码作为参考如果您觉得这不是正确的方法,请直接使用正确的方法。
  • 我觉得有点做作。如需更清晰的示例,请查看您刚刚链接到的 SO 问题中的 Mark Seemann 示例代码。
  • 好的,您从中获取代码的文章有一个很大的缺陷,因为尽管标题声称,它解释了工厂模式 - 其主要目标是将复杂的创建逻辑从构造函数中提取到一个单独的类 - 而不是 Factory Method 模式本身。

标签: c++ design-patterns factory-pattern abstract-factory


【解决方案1】:

这是经过深思熟虑后的修改回复。

工厂方法:通常createObject()是Creator对象的一个​​方法。

抽象工厂:通常工厂对象是Creator对象的一个​​属性。

现在假设 createObject() 和 Factory Object 属于它们各自的 Creator。

工厂方法:createObject() 可能会在 Creator 的子类中发生变化。这通过通过继承更改 creatObject() 的实现来实现。

抽象工厂:工厂对象也可能在 Creator 的子类中发生变化。然而,这种改变是通过用不同的工厂对象替换一个工厂对象来实现的,即 Creator 对象由 composition 改变。

在您的演示中,creatObject() 和工厂对象是 Creator(s) 的外部对象,因此模糊了组合/继承之间的区别!

Christopher Okhravi 在 YouTube 上有很棒的关于模式的视频。

工厂方法https://www.youtube.com/watch?v=EcFVTgRHJLM&index=4&list=PLrhzvIcii6GNjpARdnO4ueTUAVR9eMBpc

抽象工厂https://www.youtube.com/watch?v=v-GiuMmsXj4&index=5&list=PLrhzvIcii6GNjpARdnO4ueTUAVR9eMBpc

这里要求的是工厂方法的一个版本(这次是 C++!)。 如果您需要任何翻译帮助,请告诉我。

class IRose
{
public:
    virtual const char * Color(void) = 0;
};

class RedRose : public IRose
{
public:
    const char * Color(void)
    {
        return "I am a Red rose";
    }
};

class YellowRose : public IRose
{
public:
    const char * Color(void)
    {
        return "I am a Yellow rose";
    }
};

class RoseGarden
{
protected: class IRose* rose;   // a pointer to the garden's rose

public:
    virtual void createRose() { }  // abstract Factory Method

public: void sayColor() {
        cout << rose->Color() << '\n';
    }
};

class RedRoseGarden : public RoseGarden
{
public:
    void createRose()
    {
        this->rose = new RedRose();   // concrete factory method
    }
};

class YellowRoseGarden : public RoseGarden
{
public:
    void createRose()
    {
        this->rose = new YellowRose();  // concrete factory method
    }
};

int main()
{
    RoseGarden * garden = NULL;

    garden = new YellowRoseGarden;
    garden->createRose();      // correct factory method is chosen via inheritance
    garden->sayColor();
    delete garden;

    garden = new RedRoseGarden;
    garden->createRose();      // correct factory method is chosen via inheritance
    garden->sayColor();
    delete garden;

    return 1;
}

这里还有一个稍微修改过的抽象工厂版本,以更好地展示它的使用方式。刚刚添加了一个房屋对象。请注意,我为我的编译器将所有“字符串”对象更改为 const char*。

// make different types of fridges
class IFridge
{
public:
    virtual const char* Run(void) = 0;
};

class FridgeSamsung : public IFridge
{
public:
    const char* Run(void)
    {
        return "This house has a Samsung Fridge\n";
    }
};

class FridgeWhirlpool : public IFridge
{
public:
    const char* Run(void)
    {
        return "This house has a Whirlpool Fridge\n";
    }
};

// make different types of washing machine 
class IWashingMachine
{
public:
    virtual const char*  Run(void) = 0;
};

class WashingMachineSamsung : public IWashingMachine
{
public:
    const char* Run(void)
    {
        return "This house has a Samsung Washing Machine\n";
    }
};

class WashingMachineWhirlpool : public IWashingMachine
{
public:
    const char* Run(void)
    {
        return "This house has a Whirlpool Washing Machine\n";
    }
};

// make different type of factory
class IFactory
{
public:
    virtual IFridge* GetFridge(void) = 0;
    virtual IWashingMachine* GetWashingMachine(void) = 0;
};

class FactorySamsung : public IFactory
{
    IFridge* GetFridge(void)
    {
        return new FridgeSamsung();
    }

    IWashingMachine* GetWashingMachine(void)
    {
        return new WashingMachineSamsung();
    }
};

class FactoryWhirlpool : public IFactory
{
    IFridge* GetFridge(void)
    {
        return new FridgeWhirlpool();
    }

    IWashingMachine* GetWashingMachine(void)
    {
        return new WashingMachineWhirlpool();
    }
};

// Make a house object that has a fridge and a washing machine
class House
{
private:
    class  IWashingMachine * washingMachine;
    class  IFridge * fridge;

public:
    House(IFactory * houseFactory) {
        washingMachine = houseFactory->GetWashingMachine();
        fridge = houseFactory->GetFridge();
    }
    void showAppliances() {
        cout << washingMachine->Run();
        cout << fridge->Run();
    }
};

int main()
{
    class IFactory * factory;  
    class House * house;       

    // make a samsung house
    factory = new FactorySamsung;
    house = new House(factory);     // passing the factory by injection
    house->showAppliances();        // now we have a Samsung house
    cout << '\n';

    // clean up
    delete house;
    delete factory;

    // make a whirlpool house
    factory = new FactoryWhirlpool;
    house = new House(factory);    // passing the factory by injection
    house->showAppliances();       // now we have a WHilepool house
    cout << '\n';

    // clean up
    delete house;
    delete factory;

    return 1;
} 

【讨论】:

  • 如果可能,请您重新构造上面的工厂方法代码以使用继承
  • 当然 - 我通常在 JS/PHP 中工作,所以需要一些时间来设置。如果你能读懂 PHP,我有一些 PHP 示例可以提供?
  • 抱歉不熟悉 JS/PHP,如果您发现任何 C++ 中指出上述内容的链接,请分享链接。
  • 好吧,我习惯从一种语言跳到另一种语言!我可以轻松地将上面的内容翻译成 C++,但明天会做 :-)
  • 非常感谢,我了解了工厂方法中的继承。如果是抽象工厂方法,真的需要House类吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-03
  • 1970-01-01
  • 2020-10-25
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多