【问题标题】:Template method pattern: changing the algorithm's architecture模板方法模式:改变算法的架构
【发布时间】:2019-03-06 17:41:54
【问题描述】:

我在我的项目中使用模板方法模式,如下所示

class Template
{
public:
void algorithm();
{
    A();
    B();
}
private:
virtual void A()=0;
virtual void B()=0;
}

我有一些子类以不同的方式实现方法 AB
但现在我需要一个新类 Template2 来实现稍微不同的算法。

class Template2
{
public:
void algorithm();
{
    A();
    B();
    C();
}
private:
virtual void A()=0;
virtual void B()=0;
void C()
{
    //some stuff
    A();
    //some stuff
    B();
}
}

C 在所有子类中都是相同的,所以我没有将其设为虚拟。
现在我基于 Template2 创建了一个新的继承层次结构,但这似乎很愚蠢,因为我必须将每个子类的代码复制并粘贴到这个新层次结构中。
有没有更优雅的方式呢?

编辑
对不起,我没有说清楚。
现在我有两个继承层次结构。
1.一个抽象类Template和一些子类A1,A2,A3,A4...
2.一个抽象类Template2和一些子类B1,B2,B3,B4...
这很好用,但我想知道是否有办法以某种方式合并这两个层次结构,因为 A1 和 B1 具有相同的代码,只是它们分别来自 Template 和 Template2。
解决方案是否是模板方法模式与我无关
bcperth 和 Spotted 的答案都对我有用 :)
非常感谢。

【问题讨论】:

    标签: oop design-patterns ooad


    【解决方案1】:

    我同意 Spotted 的观点,但您是否考虑过为您的 template 课程添加额外的算法?它仍然是具有多种算法的模板模式。你得到一个更胖的类,但没有代码重复。下面是一个插图。

    #include <iostream>
    
    using namespace std;
    
    class Template
    {
    public:
        void algorithm1()
        {
            A();
            B();
        }
    
        void algorithm2()
        {
            A();
            B();
            C();
        }
    
    private: void C()
        {
        cout << endl << "start C() ";
        A();
        cout << "middle C() ";
        B();
        cout << "end C()" << endl;
        }
    
    private:
        virtual void A() = 0;
        virtual void B() = 0;
    };
    
    class real :public Template {
    
        void A() { cout << "A(1)  "; }
        void B() { cout << "B(1) "; }
    };
    
    int main()
    {
        real Real;
        cout << "algorithm1" <<endl;
        Real.algorithm1();
        cout << endl;
        cout << endl << "algorithm2 << endl";
        Real.algorithm2();
    
        return 0;
    }
    

    【讨论】:

    • 事实上,这里提出的Template 类(其中包含两种算法)可能是最好的方法。
    • 这真的很有帮助,我想我会用它。
    • 好的,太好了!您可以通过单击我的回复左上角上下箭头下方的勾号来关闭问题。这根本不是强制性的 - 但对统计数据有好处:-)
    【解决方案2】:

    首先,请原谅我糟糕的 C++ 语法。

    我建议你将A()B()Template 解耦,以便在Template2 中更轻松地重用它们

    class Strategy
    {
        public:
        virtual void A()=0;
        virtual void B()=0;
    }
    

    那么在TemplateTemplate2之间有一个共同的祖先:

    class AbstractTemplate
    {
        public:
        virtual void algorithm()=0;
    }
    

    最后将TemplateTemplate2 实现为“最终”类(=不需要子类)。

    class Template : AbstractTemplate
    {
        public:
        Template(Strategy strategy)
        {
            this.strategy = strategy;
        }
        void algorithm()
        {
            strategy.A();
            strategy.B();
        }
        private:
        Strategy strategy;
    }
    
    class Template2 : AbstractTemplate
    {
        public:
        Template2(Strategy strategy)
        {
            this.strategy = strategy;
        }
        void algorithm()
        {
            strategy.A();
            strategy.B();
            C();
        }
        private:
        Strategy strategy;
        void C()
        {
            //some stuff
            strategy.A();
            //some stuff
            strategy.B();
        }
    }
    

    TemplateTemplate2 之间的重叠很小(考虑到您不需要子类,我认为没关系)。

    【讨论】:

    • 我想您只是将他的模板模式更改为策略模式!并不是说这很糟糕,但 OP 可能正在研究模板。那些XY情况之一? :-)
    • @bcperth 首先,是的,由于缺乏来自 OP 的上下文,这可能是 XY 情况。但是,我认为我的解决方案增加了“仅使用”模板模式的价值:它避免了类的扩散。仅使用模板,您可能需要 N^2 个类(N * Template + N * Template2)。使用策略,复杂度降低到 N + 2 (N * strategy + 1 * Template + 1 * Template2)。但正如你所说,如果 OP 的目的是研究模板模式或 XY 情况,这一切都无关紧要,也无济于事。
    • 对不起,我的问题没有说清楚,这正是我想要的答案,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 1970-01-01
    • 1970-01-01
    • 2019-08-23
    相关资源
    最近更新 更多