Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 具有可变契约的装饰模式_Java_Design Patterns - Fatal编程技术网

Java 具有可变契约的装饰模式

Java 具有可变契约的装饰模式,java,design-patterns,Java,Design Patterns,在decorator模式中,我对如何使用decorator方法感到困惑。我了解到decorator模式用于向基类添加函数。但我只能调用最外层的decorator方法,所以如果接口中没有提到内部decorator方法,我应该如何使用它呢。我不擅长英语,所以我写代码来演示我的问题 public class OrderSystem { public static void main(String[] args) { Pancakes pancakes = new MixedPa

在decorator模式中,我对如何使用decorator方法感到困惑。我了解到decorator模式用于向基类添加函数。但我只能调用最外层的decorator方法,所以如果接口中没有提到内部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;
    }
}
正如我在annotation中所问的,当一个decorator被另一个decorator包装时,只有在接口中声明的方法(如
cost()
getDescription()
)可以工作,而另一个方法将不再被调用。我想如果我创造了一个士兵,如果我用枪装饰他,他将是枪的功能。如果我明天用剑装饰他,他不仅能射击,而且还能切割剑的功能。我可以用装饰图案来实现吗?
很抱歉出现任何误解,感谢您的帮助。

正如您问题中评论中提到的,装饰图案的使用方式与此不同

以士兵为例,装饰师的工作方式如下:

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...");
    }
}
将你的士兵从一个装饰师转移到另一个装饰师会增强他们的攻击力

现在要添加行为/方法,可以使用普通的旧继承

您可以通过扩展类来添加行为,BaseStardier可以行走,但SoldierWithGun扩展了BaseStardier,在行走之外添加了一种射击方法

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


这并不完全是你想要的“装饰”,但我认为这是你想要做的事情的方式

decorator的重点不是添加方法。这是为了使装饰对象的方法做得更多,或不同。装饰器应该与被装饰的对象具有相同的类型。例如,BufferedReader装饰另一个读卡器。它的read()方法委托给修饰过的reader的read()方法,但在顶部添加了缓冲。@JBNizet,我认为这应该是一个答案,而不是一个注释。@GrzegorzGórkiewicz不会回答这个问题。@YuhangHan方法名为
eggState
hambate
真的没有意义。这些方法应该做什么?这将有助于回答这个问题。@CKing一个具有多个实例的单例不是单例。它是一个多线程、一个对象池或类似的东西。在这个问题上,问题在于误解。不要试图假装这是别的东西,这不是一个好答案。