Don't just know the strategy mode + simple factory, try a more fragrant strategy mode + abstract factory!

 

My related blog post 

Detailed explanation of three factory modes

Rebate website www.cpa5.cn

 

Strategy mode

In GOF's "Design Patterns: The Foundation of Reusable Object-Oriented Software", the strategy pattern says this:

Define a series of algorithms, encapsulate them one by one, and make them interchangeable. This mode allows the algorithm to change independently of the customers who use it.

 

In order to adapt to different needs, the strategy model only encapsulates the change points. This change point is the algorithm to achieve different needs, such as overtime wages, different overtime situations, and different methods of calculating overtime wages.

We cannot hard-code the algorithm for calculating wages in the program, but can change it freely.

This is the strategy mode.

 

 

 

 

Experiment 1 Strategy Mode + Simple Factory

Code

#include <iostream>
using namespace std;

// Define the strategy type
typedef enum StrategyType
{
    StrategyA,
    StrategyB,
    StrategyC
}STRATEGYTYPE;

// The abstract strategy
class Strategy
{
public:
    virtual void AlgorithmInterface(int x, int y) = 0;
    virtual ~Strategy() = 0; 
};

Strategy::~Strategy()
{}

class ConcreteStrategyA : public Strategy
{
public:
    void AlgorithmInterface(int x, int y)
    {
        cout << "I am from ConcreteStrategyA: result=X+Y, = " << x+y << endl;
    }

    ~ConcreteStrategyA(){
        cout << "~ConcreteStrategyA()." << endl;
    }
};

class ConcreteStrategyB : public Strategy
{
public:
    void AlgorithmInterface(int x, int y)
    {
        cout << "I am from ConcreteStrategyB: result=X*Y, = " << x*y << endl;
    }

    ~ConcreteStrategyB(){
        cout << "~ConcreteStrategyB()." << endl;
    }
};

class ConcreteStrategyC : public Strategy
{
public:
    void AlgorithmInterface(int x, int y)
    {
        cout << "I am from ConcreteStrategyC: result=X-Y, = " << x-y << endl;
    }

    ~ConcreteStrategyC(){
        cout << "~ConcreteStrategyC()." << endl;
    }
};

// 用户类 : 使用算法的用户
class Context
{
public:
    // 该构造函数内使用简单工厂模式
    Context(STRATEGYTYPE strategyType)
    {
        switch (strategyType)
        {
        case StrategyA:
            pStrategy = new ConcreteStrategyA;
            break;

        case StrategyB:
            pStrategy = new ConcreteStrategyB;
            break;

        case StrategyC:
            pStrategy = new ConcreteStrategyC;
            break;

        default:
            break;
        }
    }

    ~Context()
    {
        if (pStrategy) 
            delete pStrategy;
    }

    void ContextInterface(int x, int y) // 定义一个接口来让Stategy访问用户的数据
    {
        if (pStrategy)
            pStrategy->AlgorithmInterface(x, y);
    }

private:
    Strategy *pStrategy; // 维护一个对Stategy对象的引用或指针
    int a;               // 私有数据,这是用户数据,该用户是独立于算法的用户,用户不需要了解算法内部的数据结构
    int b;
};

int main()
{
    Context *pContext = new Context(StrategyA);
    pContext->ContextInterface(100, 6);

    if (pContext) 
        delete pContext;
}

The above example is a strategy pattern, we can also see a little shadow of the simple factory pattern.

The vast majority of Baidu's visits are examples of this kind. Is this code perfect? Look at the essentials of GoF:

If we need to add new algorithms, we need to modify the constructor of the Context class and add new algorithms in it. This obviously does not meet the essence of GoF's use of extension and subclassing.

So it leads me to the following strategy pattern + abstract factory solution.

 

 

Experiment 2 Strategy Mode + Abstract Factory

Code

#include <iostream>
using namespace std;


// The abstract strategy
class Strategy
{
public:
    virtual void AlgorithmInterface(int x, int y) = 0;
    virtual ~Strategy() = 0; 
};

Strategy::~Strategy()
{}

class ConcreteStrategyA : public Strategy
{
public:
    void AlgorithmInterface(int x, int y)
    {
        cout << "I am from ConcreteStrategyA: result=X+Y, = " << x+y << endl;
    }

    ~ConcreteStrategyA(){
        cout << "~ConcreteStrategyA().析够" << endl;
    }
};

class ConcreteStrategyB : public Strategy
{
public:
    void AlgorithmInterface(int x, int y)
    {
        cout << "I am from ConcreteStrategyB: result=X*Y, = " << x*y << endl;
    }

    ~ConcreteStrategyB(){
        cout << "~ConcreteStrategyB().析够" << endl;
    }
};

class ConcreteStrategyC : public Strategy
{
public:
    void AlgorithmInterface(int x, int y)
    {
        cout << "I am from ConcreteStrategyC: result=X-Y, = " << x-y << endl;
    }

    ~ConcreteStrategyC(){
        cout << "~ConcreteStrategyC().析够" << endl;
    }
};

// 用户类 : 使用算法的用户
class Context
{
public:
    Context(Strategy* paraStrategy)
    {
        pStrategy = paraStrategy;
    }

    ~Context()
    {
        // 这里不需要析够pStrategy, pStrategy对应对象的析够会在delete pAbstractStrategyFactory时进行。
        // 即,销毁具体某个策略工厂对象时会负责析够具体的策略对象。所以这里就不需要了。
    }

    void ContextInterface(int x, int y) // 定义一个接口来让Stategy访问用户的数据
    {
        if (pStrategy)
            pStrategy->AlgorithmInterface(x, y);
    }

private:
    Strategy *pStrategy; // 维护一个对Stategy对象的引用或指针
    int a;               // 私有数据,这是用户数据,该用户是独立于算法的用户,用户不需要了解算法内部的数据结构
    int b;
};



// 点评该类: 一条产品线下的产品,通常存在共性,
// 也就是说,维护一个对产品的抽象类通常是需要的,而不是必须的。   

class AbstractStrategyFactory   // 抽象工厂这里可以实现多个纯虚方法
{
public:
    virtual Strategy* createStrategy(string Strategy)=0;
    virtual ~AbstractStrategyFactory(){}
};
  
class StrategyA_Factory:public AbstractStrategyFactory
{
Strategy *pStrategy;
public:
    StrategyA_Factory():pStrategy(NULL)
    {}
    Strategy* createStrategy(string Strategy)
    {
        if(Strategy == "StrategyA"){
            pStrategy = new ConcreteStrategyA();
            return pStrategy;
        }
        return NULL;
    }
    ~StrategyA_Factory()
    {
        cout << "~StrategyA_Factory(). 析够" << endl;
        if(pStrategy)
            delete pStrategy;
    }
};

class StrategyB_Factory:public AbstractStrategyFactory
{
Strategy *pStrategy;
public:
    StrategyB_Factory():pStrategy(NULL)
    {}
    Strategy* createStrategy(string Strategy)
    {
        if(Strategy == "StrategyB"){
            pStrategy = new ConcreteStrategyB();
            return pStrategy;
        }
        return NULL;
    }
    ~StrategyB_Factory()
    {
        if(pStrategy)
            delete pStrategy;
    }
};

class StrategyC_Factory:public AbstractStrategyFactory
{
Strategy *pStrategy;
public:
    StrategyC_Factory():pStrategy(NULL)
    {}
    Strategy* createStrategy(string Strategy)
    {
        if(Strategy == "StrategyC"){
            pStrategy = new ConcreteStrategyC();
            return pStrategy;
        }
        return NULL;
    }
    ~StrategyC_Factory()
    {
         if(pStrategy)
            delete pStrategy;       
    }
};

int main(int argc, char *argv[])
{
    AbstractStrategyFactory* pAbstractStrategyFactory;  // 创建抽象工厂指针
 
    pAbstractStrategyFactory = new StrategyA_Factory();       // 创建策略A的工厂
    Strategy* pStrategy = pAbstractStrategyFactory->createStrategy("StrategyA");  //使用策略A工厂来生产出策略A
    if(pStrategy == NULL)
    {
        cout << "pStrategy is NULL" << endl;
    }
    else
    {
    // 供用户来使用策略A : 用户使用策略A 和 策略A的实现,是松耦合的。
    Context *pContext = new Context(pStrategy);
    pContext->ContextInterface(100, 6);

    delete pAbstractStrategyFactory;

    if (pContext) 
        delete pContext;
    }

    return 0;
  
}

Compile and run:

 

At this point, if you want to add an algorithm, then I think you can use an extended and subclassed solution instead of modifying the existing code like the previous example in this blog post.

To put it plainly, if you want to add an algorithm, you only need to add the relevant code of the new algorithm on the basis of the existing code, instead of modifying the internal implementation of some functions that have been written.

Of course, such a design will lead to a larger amount of code, so everything needs to be weighed, and the one that suits you is the best.

 

 

 

.

Guess you like

Origin blog.csdn.net/nidongla/article/details/114937454