■ Decoratorパターン
* 既存クラスのメソッドに対して、継承を使わずに ラッパークラス(機能を一つひとつかぶせていくイメージ)を作ることで 機能追加を行うデザインパターン
■ 使いどころ
* 機能を追加(拡張)する場合
■ 登場人物
Component (部品)
* 機能追加の核となるクラス * 機能拡張するメソッドのインタフェースを定義
ConcrenteComponent (具体的な部品)
* 基本機能を実装 * Component を継承
Decorator (装飾者)
* 「Component」を実装しているオブジェクトを保持
ConcreteDecorator (具体的な装飾者)
* Decorator を継承
Client (依頼者)
* 利用者
■ サンプル
* ベースとなるPriceとカスタマイズをIPriceインタフェースで同一視することにより、 さまざまな組み合わせのカスタマイズが可能になる
IPrice.java : Component (部品)
import java.math.BigDecimal; public interface IPrice { BigDecimal getPrice(); void setPrice(BigDecimal priceValue); }
Price.java : ConcrenteComponent (具体的な部品)
import java.math.BigDecimal; public class Price implements IPrice { private BigDecimal priceValue; @Override public BigDecimal getPrice() { return this.priceValue; } @Override public void setPrice(BigDecimal priceValue) { this.priceValue = priceValue; } }
PriceDecorator.java : Decorator (装飾者)
public abstract class PriceDecorator implements IPrice { protected IPrice price; public PriceDecorator(IPrice price) { this.price = price; } }
PriceFormatter.java : ConcreteDecorator (具体的な装飾者)
import java.math.BigDecimal; public class PriceFormatter extends PriceDecorator { public enum RoundingType { None, // 四捨五入 RoundOff, // 切上げ Revaluation, // 切捨て RoundDown, } private RoundingType type; public PriceFormatter(IPrice price, RoundingType type) { super(price); this.type = type; } @Override public BigDecimal getPrice() { BigDecimal priceValue = super.price.getPrice(); switch (this.type) { case RoundOff: priceValue = priceValue.setScale(1, BigDecimal.ROUND_HALF_UP); break; case Revaluation: priceValue = priceValue.setScale(1, BigDecimal.ROUND_UP); break; case RoundDown: priceValue = priceValue.setScale(1, BigDecimal.ROUND_DOWN); break; case None: default: break; } return priceValue; } @Override public void setPrice(BigDecimal priceValue) { super.price.setPrice(priceValue); } }
Main.java : Client (依頼者)
import java.math.BigDecimal; import com.decorator.PriceFormatter.RoundingType; public class Main { public static void main(String[] args) { Price price = new Price(); price.setPrice(BigDecimal.valueOf(42.195)); PriceFormatter formatter1 = new PriceFormatter(price, RoundingType.Revaluation); System.out.println("切り上げ " + formatter1.getPrice()); PriceFormatter formatter2 = new PriceFormatter(price, RoundingType.RoundDown); System.out.println("切捨て " + formatter2.getPrice()); PriceFormatter formatter3 = new PriceFormatter(price, RoundingType.RoundOff); System.out.println("四捨五入 " + formatter3.getPrice()); } }
出力結果
切り上げ 42.2 切捨て 42.1 四捨五入 42.2
参考文献
Decorator パターン
http://blog.asial.co.jp/541
http://www.mochi-programming-ras.info/contents/Java/GoF/9
http://ja.wikipedia.org/wiki/Decorator_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3
http://www.itsenka.com/contents/development/designpattern/decorator.html
http://www.sgnet.co.jp/java/java06_05.html
http://sizuki0514.blogspot.jp/2012/12/decorator.html
http://www.h7.dion.ne.jp/~a.d.1976/design20090121.html
お金などの数に関する型
http://www.atmarkit.co.jp/ait/articles/0702/27/news100.html
http://java-reference.sakuraweb.com/java_number_round.html