DEV Community

菜皮日记
菜皮日记

Posted on

行为型设计模式-模板方法 Template Method

简介

父类抽象类定义大的处理流程,部分细节做成抽象方法,留给子类去实现。

如Java的JUnit中, setUp tearDown方法都是留给具体的测试用例来写,Servlet中service处理了一个请求的大部分工作,留下doGet和doPost给业务自定义处理。

另外callback一般分两种方式:同步回调、异步回调,其中同步回调类似于模板方法模式,异步回调类似于观察者模式。

模板方法要基于继承,而回调更类似组合,

角色

  • 抽象模板类

    定义大的处理流程,留出部分方法给具体类实现

  • 具体模板类

    实现具体的处理逻辑

类图

如图,ConcreteClass实现了一些具体逻辑

类图

代码


abstract class AbstractClass
{
    final public function templateMethod(): void
    {
        $this->baseOperation1();
        $this->requiredOperations1();
        $this->baseOperation2();
        $this->hook1();
        $this->requiredOperation2();
        $this->baseOperation3();
        $this->hook2();
    }

    protected function baseOperation1(): void
    {
        echo "AbstractClass says: I am doing the bulk of the work\n";
    }

    protected function baseOperation2(): void
    {
        echo "AbstractClass says: But I let subclasses override some operations\n";
    }

    protected function baseOperation3(): void
    {
        echo "AbstractClass says: But I am doing the bulk of the work anyway\n";
    }

    abstract protected function requiredOperations1(): void;

    abstract protected function requiredOperation2(): void;

    protected function hook1(): void { }

    protected function hook2(): void { }
}

class ConcreteClass1 extends AbstractClass
{
    protected function requiredOperations1(): void
    {
        echo "ConcreteClass1 says: Implemented Operation1\n";
    }

    protected function requiredOperation2(): void
    {
        echo "ConcreteClass1 says: Implemented Operation2\n";
    }
}

class ConcreteClass2 extends AbstractClass
{
    protected function requiredOperations1(): void
    {
        echo "ConcreteClass2 says: Implemented Operation1\n";
    }

    protected function requiredOperation2(): void
    {
        echo "ConcreteClass2 says: Implemented Operation2\n";
    }

    protected function hook1(): void
    {
        echo "ConcreteClass2 says: Overridden Hook1\n";
    }
}

function clientCode(AbstractClass $class)
{
    $class->templateMethod();
}

echo "Same client code can work with different subclasses:\n";
clientCode(new ConcreteClass1());

echo "Same client code can work with different subclasses:\n";
clientCode(new ConcreteClass2());
Enter fullscreen mode Exit fullscreen mode

output:

Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass1 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass1 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass2 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass2 says: Overridden Hook1
ConcreteClass2 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
Enter fullscreen mode Exit fullscreen mode

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay