2017-02-18 5 views
4

デコレータパターンでは、デコレータメソッドの使い方が混乱しています。私はデコレータパターンが基底クラスに関数を追加するために使用されることを学びました。しかし、私は最も外側のデコレータのメソッドだけを呼び出すことができます。したがって、内部デコレータのメソッドをインターフェイスで言及されていない場合はどうすればよいですか。私は英語が上手ではないので、私は自分の質問を示すコードを書く。コントラクトの異なるデコレータパターン

public class OrderSystem { 
    public static void main(String[] args) { 
     Pancakes pancakes = new MixedPancakes(); 
     pancakes = new Ham(pancakes); 
     ((Ham) pancakes).hamState(); // call hamState 
     pancakes = new Egg(pancakes); 
     ((Egg) pancakes).eggState(); 
     // i can't call hamState() there because it not belong to Egg 

     Pancakes pancakes1 = new Ham(new Egg(new FlourPancakes())); 
     // similarly, i can't use eggState() there. 
     System.out.println("订单:" + pancakes1.getDescription()); 
     System.out.println("价格:" + pancakes1.cost()); 
    } 
} 

interface Pancakes { 
    public abstract String getDescription(); 

    public abstract int cost(); 
} 

abstract class Seasoning implements Pancakes { 
    @Override 
    public abstract String getDescription(); 
} 

class Ham extends Seasoning { 

    Pancakes pancakes; 

    public Ham(Pancakes pancakes) { 
     this.pancakes = pancakes; 
    } 

    @Override 
    public int cost() { 
     return pancakes.cost() + 2; 
    } 

    @Override 
    public String getDescription() { 
     return pancakes.getDescription() + "+火腿"; 
    } 

    public void hamState() { 
     System.out.println("火腿切碎"); 
    } 

} 

class Egg extends Seasoning { 

    Pancakes pancakes; 

    public Egg(Pancakes pancakes) { 
     this.pancakes = pancakes; 
    } 

    @Override 
    public int cost() { 
     return pancakes.cost() + 1; 
    } 

    @Override 
    public String getDescription() { 
     return pancakes.getDescription() + "+鸡蛋"; 
    } 

    public void eggState() { 
     System.out.println("鸡蛋打碎"); 
    } 
} 

class MixedPancakes implements Pancakes { 

    @Override 
    public String getDescription() { 
     return "五谷杂粮煎饼"; 
    } 

    @Override 
    public int cost() { 
     return 6; 
    } 
} 

class FlourPancakes implements Pancakes { 

    @Override 
    public String getDescription() { 
     return "白面煎饼"; 
    } 

    @Override 
    public int cost() { 
     return 5; 
    } 
} 

私は注釈に尋ねたようデコレータが相互に包まれていたとき、(cost()getDescription()のような)インタフェースで宣言された唯一の方法は動作しますし、他の方法はもう呼び出されません。私は兵士を作ったら、銃を使って飾ると彼はshoot() - 銃の機能になると思った。私は明日剣で彼を飾ると、彼はshoot()だけでなく、cut()でも剣の機能を果たすことができます。デコレータパターンで実現できますか? ご迷惑をおかけして申し訳ありません。ご協力いただきありがとうございます。

+10

デコレータのポイントはメソッドを追加することではありません。それは装飾されたオブジェクトのメソッドを何か*もっと*する、または*別のものにすることです。デコレータは、装飾されるオブジェクトと同じ型を持つと想定されます。たとえば、BufferedReaderは別のリーダーを装飾します。そのread()メソッドは装飾されたリーダーのread()メソッドに委譲しますが、一番上にバッファリングを追加します。 –

+2

@JBNizet、これは答えではなく、コメントではないと思います。 –

+0

@GrzegorzGórkiewiczそれは質問に答えないだろう。 – CKing

答えて

1

あなたの質問にコメントの中で言及された人々のように、デコレータパターンはまったく同じように使用されていません。

あなたの兵士の例を使用して、デコレータは次のように動作します:

public abstract class Soldier { 
    public abstract void attack(); 
} 

public abstract class SoldierDecorator extends Soldier { 

    protected Soldier soldier; 

    public SoldierDecorator(Soldier soldier) { 
     this.soldier = soldier; 
    } 

    @Override 
    public abstract void attack(); 
} 

、その後

public class SoldierWithGun extends SoldierDecorator { 

    public SoldierWithGun(Soldier soldier) { 
     super(soldier); 
    } 

    @Override 
    public void attack() { 
     soldier.attack(); 
     shootWithTheGun(); 
    } 

    private void shootWithTheGun() { 
     System.out.println("Shooting with the gun..."); 
    } 
} 

public class SoldierWithSword extends SoldierDecorator { 

    public SoldierWithSword(Soldier soldier) { 
     super(soldier); 
    } 

    @Override 
    public void attack() { 
     soldier.attack(); 
     cutWithSword(); 
    } 

    private void cutWithSword() { 
     System.out.println("Cutting with the sword..."); 
    } 
} 

はデコレータからデコレータにあなたの兵士を渡す彼らの攻撃を高めるであろう。

これで、ビヘイビア/メソッドを追加するには、普通の古い継承を使用できます。

クラスを拡張することで動作を追加できますが、BaseSoldierは歩くことができますが、SoldierWithGunはBaseSoldierを拡張し、歩く以外にも撮影するメソッドを追加します。

インターフェイスを使用して、特定の機能が実装されているクラスで使用できるようにすることができます。

あなたが望むように正確に「装飾」しているわけではありませんが、これはあなたがしたいことに行く方法だと思います。

関連する問題