デザインパターン プログラミング Java

【TemplateMethodパターン】売上レポートをテキストとHTML形式で出力分けする事例

投稿日:

概要

デザインパターンのTemplateMethodパターンの事例です。
デザインパターンは増補改訂版 Java言語で学ぶデザインパターン入門で学ぶことができますし、Qiitaでも取り上げられています。

ここで紹介するのは、私が自分で適用可能な状況を考えて実装した事例です。
本の写経やブログを読んで終わりではなく、どのような状況でどのように実装できるか?
と自分なりに考えることの重要性は、増補改訂版 Java言語で学ぶデザインパターン入門でも述べられています。

本を読んだり、写経したり、Qiitaを見て真似してみたけど、実際にどうやって使うんだろうか?
という疑問を持っている読者の方に、またオブジェクト指向プログラミングを身に着けたい方の参考になればと思います。

TemplateMethodパターンとは?

説明

ロジックが共通しているが、具体的な処理内容はサブクラスで実装するパターンです。
ロジック部分はスーパークラスで実装されており、ロジック内にある個別の処理内容をサブクラス固有の実装にすることで、ロジックの使いまわしと個別処理の実装を分離することができます。

共通のロジックがコピー&ペーストでいろんな場所に分散すると、修正することも、テストすることも大変になります。
そういった手間をかけないようにするためのパターンです。

クラス図


スーパークラスのSalesReportでoutputメソッドが共通ロジックになっており、その中でtitle、detail、summaryメソッドが実行されるようになっています。
title、detail、summaryメソッドをサブクラスであるTextSalasReportとHtmlSalesReportで個別に実装することで、表示形式を分離しています。

実装

SalesReportクラス

売上レポートのスーパークラス。
・title、detail、summaryの表示形式はサブクラスで定義するため抽象メソッドとしている。
・outputメソッドは共通ロジックであり、変更不可のためfinalとしている。
・summaryAmount、yenメソッドも共通ロジックですが、個別の実装を要求するものではなく、サブクラスで利用できるように提供しているだけです。

TextSalesReportクラス

テキスト形式で売上レポートを出力するクラスです。
出力形式の仕様は以下のようになります。
< yyyy年M月売上レポート >
A社 : 5000000円
B社 : 2500000円
C社 : 500000円
合計 : 8000000円

HtmlSalesReportクラス

HTML形式で売上レポートを出力するクラスです。
出力形式の仕様は以下のようになります。
<h1>yyyy年M月売上レポート</h1>
<table>
<tr><td>A社</td><td>5000000円</td></tr>
<tr><td>B社</td><td>2500000円</td></tr>
<tr><td>C社</td><td>500000円</td></tr>
<tr><td>合計</td><td>8000000円</td></tr>
</table>

SalesRepotMainクラス

売上レポートを表示するためのクラスです。

<出力結果>

サブクラスで実装した仕様の違い

TextSalesReportクラスHtmlSalesReportクラス
titleメソッドタイトルを<>で囲って表示する。
タイトルの前後に半角スペースを入れること。
タイトルをh1タグで囲って表示する。
detailメソッド会社名と金額をコロンで区切って表示する。
会社名の前と、コロンの前後に半角スペースを入れること。
trタグ内に、tdタグで会社名と金額を表示する。
ただし、最初のtrタグを出力する時だけ、tableタグを追加しておく。
summaryメソッド"合計"と合計金額をコロンで区切って表示する。
"合計"の前と、コロンの前後に半角スペースを入れること。
trタグ内に、tdタグで"合計"と合計金額を表示する。
また、tableの閉じタグを追加しておく。

もし他の出力形式でレポートを出力する場合、ロジックのコピー&ペーストすることなく、別のクラスを追加することで対応できます。
例えば、CSV形式のファイルを出力する必要が出てきたら、CsvSalesReportクラスを作成すればよいということになります。
※サブクラスを追加した結果、スーパークラスに機能追加することが無いという意味では無く、必要に応じてリファクタリングは行われるべきかなとは思っています。

付録(テストコード)

新たなサブクラスの追加でスーパークラスの修正も行った場合、既存のサブクラスに影響を与える可能性があります。
そのためにテストコードを書いておくことはとてもとても重要だと思っています。

リファクタリングでも、既存のコードを修正するのであればテストコードを用意しておくことが望ましいと述べられています。
動いているコードを修正するリスクは高いのです!
テストコードを書けるのであれば、できる限り書くようにしていきましょう。

module-info

Java11の環境であるため、module-infoを利用しています。

TestTextSalesReport

TextSalesReportクラスのテストコードです。
個別に実装するメソッドのテストを行っています。

TestHtmlSalesReport

TestHtmlSalesReportクラスのテストコードです。
TestTextSalesReportと同様に、個別に実装するメソッドのテストを行っています。

テストコードのメリット

実際のところ、この記事を書きあげるまでに何度かコードを書き直しました。
まさしく、リファクタリングを行ったわけです。
その際、テストコードがあったおかげで私は自分の修正に確からしさを感じることができました。

よく「こんな小さな修正でバグが出るはずがない」という思い込みをすることがあります。
(読者のあなたにもあれば、要注意です!)
それでも、ポカはするものなのです。
なので、テストコードがあれば、自分の修正に問題がないことをある程度は保証することはできます。

ですから、何度も言うようですが、テストコードを書けるのであれば、できるだけ書いた方がよいです。
プロジェクト体制やスキルの問題もあると思いますが、私としては自分の仕事に確からしさをもたらし、品質と効率を求めていきたいと思っています。

まとめ

  • 共通ロジックをコピー&ペーストすることなく使いまわすことができるパターンである。
  • 個別の処理内容はサブクラスで自由に実装可能である。
  • 追加のサブクラスが必要になった場合、単純に追加するだけで対応可能である。

参考書籍

増補改訂版 Java言語で学ぶデザインパターン入門

 
最後までお読み頂き、ありがとうございました!
ご意見・ご要望がありましたら、遠慮なくコメント下さい!
もし内容が良かったらランキング評価を頂けると励みになります(^^)

ランキング評価する

-デザインパターン, プログラミング, Java
-, ,

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

Camtasia(カムタジア)でKrisp(クリスプ)を使う方法

Camtasiaで動画撮影する時のノイズ除去にKrispを導入する方法です。 前提 Krisp(無料版でOK)をインストール済みであること。 Pro版を試したい方は以下の招待URLからダウンロードして …

【Java】MapをStreamで処理する方法 7選!

概要 【Java】ListをStreamで処理する方法 7選! 【Java】SetをStreamで処理する方法 7選! に続き、Map編です。 Mapをstreamで扱う場合、entrySetまたはK …

【Java】オブジェクト指向の練習題材(成績オブジェクト)

前回記事、オブジェクト指向とは何なのかを簡単に説明してみるの練習題材です。 ここでは2つのオブジェクトを作成していきます。 成績オブジェクト:教科と点数などを保持 生徒オブジェクト:氏名と成績を保持 …

AWSへWebアプリケーション(Java)をデプロイする方法(書籍紹介)

対象者 ・個人開発者 ・ポートフォリオ作成者 手順 こちらの書籍を参考に私自身がAWSにデプロイした手順です。 書籍では図解もあってわかり易く解説されているので、ここでは流れを簡潔に説明します。 すで …

【SpringSecurity】#3~ 独自のログイン画面

概要 オリジナルのログイン画面を実装する方法です。 以下の内容になっています。 ログイン用のHTMLを用意する。 Controllerにログインの遷移先を定義する。 SecurityConfigクラス …

■運営者プロフィール
IT業界10年のエンジニア。
PHP -> VBA -> Javaと渡り歩いてきて、今はJavaをメインにフリーランスエンジニアとして活躍中!

[保有資格]
・Java SE 11 Gold

一度はエンジニアを辞めざるを得なかった私が再びエンジニアとして復活した数奇な物語

SpringFramworkの良書

■おすすめ教材
Javaの基本を学んだ人が、次のステップとして読む本(中級者向け)

※SpringはJavaのFrameworkの1つです。
変更のしやすさ、保守性の高さが特徴です。