装饰图案与不同的合同

时间:2017-02-18 12:29:26

标签: java design-patterns

在装饰器模式中,我对如何使用装饰器方法感到困惑。我了解到装饰器模式用于向基类添加函数。但是我只能调用最外面的装饰器方法,所以我应该如何使用内部装饰器的方法,如果在接口中没有提到的话。我不擅长英语,所以我编写代码来证明我的问题。

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() - 剑的功能。我可以用装饰模式实现吗? 对于任何误解,我感到抱歉,感谢您的帮助。

1 个答案:

答案 0 :(得分: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,添加了一种除了走路之外拍摄的方法。

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

这不完全是#34;装饰"如你所愿,但我认为这是你想要做的事情的方法。

相关问题