2017-02-18 47 views
4

在装饰模式,我很困惑如何使用装饰方法。我已经了解到,装饰器模式用于将函数添加到基类。但是我只能调用最外层的装饰器的方法,所以如果在接口中没有提到,我应该如何使用inner-decorator的方法。我不擅长英语,所以我编写代码来演示我的问题。装修模式与合同

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,增加一种除步行拍摄的方法。

您可以使用接口来确保某些功能在实现它们的类中可用。

它不完全是你想要的“装饰”,但我认为这是你想要做的事。