モデル名と分類
templateMethod
行動パターン
意図
スケルトンアルゴリズム操作の定義、言葉の遅れクラスにいくつかのステップ。アルゴリズムのアルゴリズムの特定のステップの構造を再定義するようにTemplateMethod単語クラスが変更されなくてもよいです。
モチベーション
Mavenのソフトウェアでは、我々は多くの段階があるのデフォルトのライフサイクル3つのライフサイクルを、定義した、コンパイル、パッケージ、その上のインストール、および。実装の各段階のためのMavenの関係者は書かれているが、より柔軟なソフトウェアは、他のサードパーティ製のプラグインをサポートしている必要があります。より多くのカスタマイズ機能を達成するために。
Mavenのプロジェクトを覚えて、我々はラベル
我々は、特定のライフサイクルステージにプラグインとのバインドを宣言することができるものの説明。自分自身のためにMavenのパッケージまたはインストールまたは介入コンパイル。
このように:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.2.1</version>
// 任务执行,插件可以执行多个任务
<executions>
<execution>
// 绑定了package阶段,很多插件不需要指定,因为插件的目标在编写时已经定义好默认绑定阶段
<phase>package</phase>
<goals>
// 通过goals配置指定要执行的插件目标
<goal>shade</goal>
</goals>
// 某些插件支持出传入参数,像mvn install -Dmaven.test.skip=true。里面的-D意味着
//后面是参数,真正的参数是maven.test.skip=true,这个也可以使用configuration配置,全局生效。
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>HelloWorld</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
適用性
実際の設計では、我々は手順を定義しますが、異なる実装を可能にします。それとも私たちはデザインが異なる実装の様々なサポートします。
構造
参加者
- 親、通常は抽象クラス--AbstractClass
- 達成するために、クラスの特定のメソッドのサブクラス - サブクラス
連携
- 親クラスは、テンプレートシーケンス処理操作で定義され、及び方法の最終的な設定、動作シーケンスを変更することができないことを意味しています。
- サブクラスは親クラスを継承した後、実際のステップメソッドを書き換えます
- 意思の完璧な実現:そのサブクラスは、いくつかのステップを実装定義する親クラス定義されたアルゴリズムのスケルトン。
効果
前述のように、私たちはより良いスケーラビリティのプログラミング、Mavenのプラグウェイ、春のカスタム拡張などを行うことができます。
コード例
例1:表示モード
https://www.runoob.com/design-pattern/template-pattern.html
// 步骤 1
// 创建一个抽象类,它的模板方法被设置为 final。
// Game.java
public abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
//模板
public final void play(){
//初始化游戏
initialize();
//开始游戏
startPlay();
//结束游戏
endPlay();
}
}
// 步骤 2
// 创建扩展了上述类的实体类。
// Cricket.java
public class Cricket extends Game {
@Override
void endPlay() {
System.out.println("Cricket Game Finished!");
}
@Override
void initialize() {
System.out.println("Cricket Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Cricket Game Started. Enjoy the game!");
}
}
// Football.java
public class Football extends Game {
@Override
void endPlay() {
System.out.println("Football Game Finished!");
}
@Override
void initialize() {
System.out.println("Football Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Football Game Started. Enjoy the game!");
}
}
// 步骤 3
// 使用 Game 的模板方法 play() 来演示游戏的定义方式。
// TemplatePatternDemo.java
public class TemplatePatternDemo {
public static void main(String[] args) {
Game game = new Cricket();
game.play();
System.out.println();
game = new Football();
game.play();
}
}
実施例2:アナログのMavenプラグを実現しました
只实现模板方法,实际操作更加复杂,但是过程大概如此。
在我们使用mvn build时,触发此方法。而其中的各个阶段方法,可以配置自定义插件,也可以使用maven的默认插件。
// maven 的default生命周期的build阶段。
public abstract class AbstractBuild {
public void build(){
initialize();
compile();
test();
packagee();
integrationTest();
deploy();
}
protected abstract void initialize();
protected abstract void compile();
protected abstract void test();
protected abstract void packagee();
protected abstract void integrationTest();
protected abstract void deploy();
}
例3のバネは、カスタムラベル伸長分析を可能に
- 背景:春は、私たちはカスタムラベルを拡張することができ、優れた拡張性を持って、それが春がどのように達成するために、この方法は、基礎となるプロセスを解決することです。
- この方法は、春は解決プロセスを定義し、具体的な達成するために解決し、doParse(...)メソッドを定義して、我々は我々自身のカスタムラベルを解決するために、このメソッドをオーバーライドすることができます。
- このプロセスは再び提案で、特別なテンプレートパターンの点に注意してください。春のソースアプリケーションを読みながら、私が書いたノートです。具体的な解決方法は、彼のモデルを見て...と言うことではありません。
@Override
protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
// 在执行我们自定义的解析器中的方法之前,先执行一些准备工作,也可以叫做预解析,对beanClass、scope、lazyInit等属性的准备
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
String parentName = getParentName(element);
if (parentName != null) {
builder.getRawBeanDefinition().setParentName(parentName);
}
// 这个是自定义解析器中重写的getBeanClass方法
Class<?> beanClass = getBeanClass(element);
if (beanClass != null) {
builder.getRawBeanDefinition().setBeanClass(beanClass);
}
else {
// 如果没有重写getBeanClass方法,就看有没有重写getBeanClassName方法;
String beanClassName = getBeanClassName(element);
if (beanClassName != null) {
builder.getRawBeanDefinition().setBeanClassName(beanClassName);
}
}
builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
BeanDefinition containingBd = parserContext.getContainingBeanDefinition();
if (containingBd != null) {
//如果存在父类,就使用父类的scope属性
// Inner bean definition must receive same scope as containing bean.
builder.setScope(containingBd.getScope());
}
if (parserContext.isDefaultLazyInit()) {
// 延迟懒加载
// Default-lazy-init applies to custom bean definitions as well.
builder.setLazyInit(true);
}
// 这个是我们自己写的解析器啦,还记得模版模式么!就是这个意思,在父类中定义要做的事,而将具体的实现延迟到子类;
// 我们可以自定义很多解析器,每个解析器都有自己的解析规则。只需要复写doParse方法就好了。典型的模版模式
doParse(element, parserContext, builder);
return builder.getBeanDefinition();
}
既知の使用方法
上記
- 達成するためのMavenプラグイン
- 春カスタムラベル決意