为什么模板方法标记为final?

时间:2017-08-14 09:26:55

标签: java design-patterns abstract-class final public-method

在模板方法模式中,有一个标记为final的方法,但我无法理解使用此方法的含义。请帮帮我。换句话说,在PackageA类中,可以根据需要为每个抽象方法实现算法。客户端可以使用自己的订单调用PackageA中的方法。这个public final void performTrip()的功能/意义是什么?非常感谢你。

public abstract class Trip {
    public final void performTrip() {
        doComingTransport();
        doDayA();
        doDayB();
        doDayC();
        doReturningTransport();
    }

    public abstract void doComingTransport();

    public abstract void doDayA();

    public abstract void doDayB();

    public abstract void doDayC();

    public abstract void doReturningTransport();
}

public class PackageA extends Trip {
    @Override
    public void doComingTransport() {
        System.out.println("PKG A" + "coming");
    }

    @Override
    public void doDayA() {
        System.out.println("PKG A" + "A");
    }

    @Override
    public void doDayB() {
        System.out.println("PKG A" + "B");
    }

    @Override
    public void doDayC() {
        System.out.println("PKG A" + "C");
    }

    @Override
    public void doReturningTransport() {
        System.out.println("PKG A" + "Return");
    }

}

6 个答案:

答案 0 :(得分:2)

final个关键字表示Trip的子类无法覆盖performTrip()方法。

在当前上下文中,这意味着允许子类覆盖旅行的各个部分,例如,在A或B日发生的事情,但不是在旅行期间发生的订单(A日总是在B日之前发生)。

答案 1 :(得分:1)

这只是意味着没有其他类扩展抽象类 Trip 可以覆盖performTrip()方法。

如果继承类想要使用它,则必须使用Trip类中编写的类。

因此PackageA不能包含具有相同签名的方法(performTrip()),并且在PackageA中对performTrip()的任何调用都将引用Trip类中记录的方法。

答案 2 :(得分:1)

在模板设计模式中,一种方法是定义序列,或者换句话说,是调用类中其他方法的顺序。在你的例子中

doComingTransport();
doDayA();
doDayB();
doDayC();
doReturningTransport();

在此模板模式中无法更改调用这些方法的顺序。因此,任何扩展此类的类都不应该有机会覆盖“performTrip”方法,因为这定义了调用方法的顺序。但是可以覆盖各个方法并更改功能。这就是为什么方法“performTrip”被声明为final,所以子类不能覆盖

答案 3 :(得分:1)

final关键字阻止其他程序员以技术方式覆盖此方法。

这个接缝必须区别于这个类中的其他方法,必须在子类中被覆盖(实现)。

然而,
我在这里看到的问题是,所有abstract方法都应该具有protected可见性,因为它们旨在提供特定于类型的行为,而这些行为不应该是类公共API的一部分。

此外,final关键字还会阻止为此类(及其后代)创建模拟对象,这使得很难为类构建 UnitTest 对这个类有依赖性。

答案 4 :(得分:1)

模板模式意味着客户端代码将使用PackageA.performTrip()。它可能就像

 Collection<Trip> worldTour;
// add PackageA, PackageB and climbEverest to a worldTour

foreach(Trip currentTrip: worldTour) {
   currentTrip.performTrip();
}

巡演之外的perforimng dayB()经常受到限制,例如它可能是protected

使用final保护performTrip的实现:在DayB()

之后,没有人可以使用dayA()

答案 5 :(得分:1)

使模板方法最终确保我们的实现支持模板设计模式的意图&#34; 在操作中定义算法的骨架,将一些步骤推迟到子类。模板方法允许子类重新定义算法的某些步骤,而无需更改算法的结构。 &#34;如GOF书中所述,Eric Gamma)。本书还解释了其中的后果部分 - &#34; 模板方法指定哪些操作是挂钩(可能被覆盖)以及哪些是抽象操作(必须被覆盖)很重要)...... &#34;

但我不认为使微操作受到保护是设计模式的必要条件。只要不损害模式,class就可以使用公共范围内的那些。

实际上,设计模式永远不会孤立出现,但却出现在手中。因此,对一种模式进行100%公正不应该使其他人不公平地帮助申请。在所有模式处于抽象设计级别而不是实现级别之后。