Java入門(第14回)

前回振り返り

Decoratorパターン

Decoratorパターンでは、オブジェクトに付加的な責務(機能や振る舞い)を動的に加えることができます。

このパターンでは、既存のオブジェクトを新しい Decorator オブジェクトでラップし、機能を拡張する。実装としては、Decorator のコンストラクタの引数でラップ対象の Component オブジェクトを読み込み、コンストラクタの内部でそのオブジェクトをメンバに設定することが一般的である。

Decoratorパターンのクラス図

前回演習問題の解答 例

問題1

問題文

Decoratorパターン を作成してみましょう。

wikipedia のJava実装例を記述してみましょう。

解答例

public class DecoratorTest{
    public static void main(String[] argv){
        System.out.println(
            new WholesalePrice(
                new DoublePrice(
                    new WholesalePrice(
                        new DoublePrice(
                            new PrimePrice(120)
                            )
                        ,80
                        )
                    )
                ,200
                )
            .getValue()
            );
    }
}
/** 価格をあらわすインタフェース */
interface Price{
    int getValue();
}
/** 原価を表すクラス */
class PrimePrice implements Price{
    private int value;
    PrimePrice(int value){
        this.value = value;
    }
    public int getValue(){
        return this.value;
    }
}
/** マージンを介する価格 */
abstract class MarginPrice implements Price{
    protected Price originalPrice;
    MarginPrice(Price price){
        this.originalPrice = price;
    }
}
/** 設定された利益を仕入れ価格に上乗せする Price */
class WholesalePrice extends MarginPrice{
    private int advantage;
    WholesalePrice(Price price, int advantage){
        super(price);
        this.advantage = advantage;
    }
    public int getValue(){
        return this.originalPrice.getValue() + advantage;
    }
}
/** 仕入れ価格の 2 倍の値段を提示する Price */
class DoublePrice extends MarginPrice{
    DoublePrice(Price price){
        super(price);
    }
    public int getValue(){
        return this.originalPrice.getValue() * 2;
    }
}

問題2

問題文

問1のクラスを身近なものにアレンジしてみましょう。


解答例

public class DecoratorTest{
    public static void main(String[] argv){
        Item soap = new PrimePriceItem("石鹸",100);
        Item banana = new PrimePriceItem("バナナ",100);
        
        soap.print();
        banana.print();
        new DailyUseWithTaxDecorator(soap).print();
        new FoodWithTaxDecorator(banana).print();
        
        new DailyUseWithTaxDecorator(new TenPercentPriceIncreaseDecorator(soap)).print();
        new FoodWithTaxDecorator(new TenPercentPriceIncreaseDecorator(banana)).print();
        
        new DailyUseWithTaxDecorator(new TenPercentPriceIncreaseDecorator(new TenPercentPriceIncreaseDecorator(soap))).print();
        new FoodWithTaxDecorator(new TenPercentPriceIncreaseDecorator(new TenPercentPriceIncreaseDecorator(banana))).print();

        new DailyUseWithTaxDecorator(new DailyUseWithTaxDecorator(new TenPercentPriceIncreaseDecorator(soap))).print();

    }
}
/** 品目をあらわす抽象クラス */
abstract class Item {
    abstract String getName();
    abstract int getPrice();
    public void print() {
        System.out.println(getName()+":"+getPrice()+"円");
    }
}
/** 原価の品目を表すクラス */
class PrimePriceItem extends Item{
    private String name;
    private int price;
    PrimePriceItem(String name, int price){
        this.name = name;
        this.price = price;
    }
    public String getName() {
        return this.name;
    }
    public int getPrice(){
        return this.price;
    }
}
/** Decoratorクラス */
abstract class Decorator extends Item{
    protected Item originalItem;
    protected Decorator(Item item){
        this.originalItem = item;
    }
}
/** 食品に消費税を付与するクラス */
class FoodWithTaxDecorator extends Decorator{
    FoodWithTaxDecorator(Item item){
        super(item);
    }
    public String getName() {
        return this.originalItem.getName()+"(税込)";
    }
    public int getPrice(){
        if (this.originalItem instanceof FoodWithTaxDecorator) {
            throw new RuntimeException("多重課税です");
        }
        return (int)(this.originalItem.getPrice() * 1.08f);
    }
}
/** 日用品に消費税を付与するクラス */
class DailyUseWithTaxDecorator extends Decorator{
    protected DailyUseWithTaxDecorator(Item item) {
        super(item);
    }
    @Override
    public String getName() {
        return this.originalItem.getName()+"(税込)";
    }
    @Override
    public int getPrice(){
        if (this.originalItem instanceof DailyUseWithTaxDecorator) {
            throw new RuntimeException("多重課税です");
        }
        return (int)(this.originalItem.getPrice() * 1.1f);
    }
}
/** 10%値上げするクラス */
class TenPercentPriceIncreaseDecorator extends Decorator{
    protected TenPercentPriceIncreaseDecorator(Item item) {
        super(item);
    }
    @Override
    public String getName() {
        return this.originalItem.getName()+"("+this.originalItem.getPrice()+"→"+this.getPrice()+"円に改定)";
    }
    @Override
    public int getPrice(){
        return (int)(this.originalItem.getPrice() * 1.1f);
    }
}

今回の演習問題

問題1

問題文

Facadeパターン を作成してみましょう。

wikipedia のJava実装例を記述してみましょう。

問題2

問題文

問1のDrivingSimulator#simulateでは、pushPedalメソッドの引数に分速を渡しているが、時速に変更するとどうなるでしょうか。

コメント