2

これはデコレータパターンの例です。

public class Computer {
public String Description(){
    return "Computer";
}
}

public abstract class Decorator extends Computer{
public abstract String description();
}

public class Monitor extends Decorator{

Computer computer;
public Monitor(Computer c){
    computer = c;
}

public String description() {
    return computer.Description() + " and Monitor";
}
}

public class main {
public static void main(String args[]){
    Computer c = new Computer();
    Monitor m = new Monitor(c);
    System.out.println(m.description());
}
}

これは、スーパークラスのスーパーメソッドを呼び出す場合と同じですか?モニターがコンピューターから継承され、モニタークラスのDescriptionメソッド内のコンピュータークラスでsuper.Description()を呼び出す場合のように?

4

2 に答える 2

5

スーパー メソッドを呼び出すと、すべての可能性に対して新しいサブクラスを作成する必要があります。たとえば、モニターとマウスを備えたコンピューターが必要な場合はどうしますか? を継承したサブクラスを作ることができますMonitor。ここで、モニターなしでマウスを備えたコンピューターが必要だとします。を継承する別のサブクラスも必要になりますComputer。デバイスは 2 つしかなく、すでに 3 つのサブクラス ( MonitorMouseおよびMonitorAndMouse) が必要です。コンピューターにプリンター、スキャナー、スピーカーのセットも搭載できるとしたら?

デコレーター パターンを使用すると、コンピューターを新しいデバイスで「装飾」できます。で行ったようにMonitor、デバイスごとに異なるデコレータを作成できます。すべてのデバイスを備えたコンピューターを作成するには、次のようなことができます

Computer = new Speakers(
    new Scanner(
        new Printer(
            new Mouse(
                new Monitor(
                    new Computer()
                )
            )
        )
    )
);
computer.description();

description()を返すようになりましComputer and Monitor and Mouse and Printer and Scanner and Speakersた。組み合わせごとに新しいサブクラスを作成する必要なく、デバイスをコンピューターと組み合わせることができます。

コメントについて:

私の例では、decorator クラスを削除してから、モニターはコンピューター クラスから継承しませんでした。代わりに、コンピューター クラスのインスタンスをモニター クラス内に配置して、同じことを行います。

この方法では、1 レベルの深さしか進むことができず、コンピューターに追加できるデバイスは 1 つだけです。本質的に、これは拡張不可能なデコレーターです。デコレーター パターンは、複数のデバイスを追加することで得られる可能性が非常に大きくなるため、継承よりもコンポジションを優先する方法です。あなたのソリューションでは、 のサブクラスを作成するのではComputerなく、で を構成することにより、継承よりも構成を優先MonitorしていComputerます。これはほぼデコレータ パターンですが、一歩後退しただけです。

于 2012-04-04T07:43:30.357 に答える
1

質問に簡単に答えると: いいえ、同じではありません。

デコレーターは、既存のオブジェクトを使用してその動作を変更しますが、外の世界では、それが装飾するクラスの典型であるかのように見えます。

あなたの例でこれを説明するために、コンピューターがあり、コンピューターにはいくつかのプロパティがあります。コードのどこかで、このコンピューターのインスタンスを作成しています。必要なすべてのデータを入力しています。

これで、Decorator が配置されます。作成したコンピュータのこのインスタンスを装飾するクラスが必要です! まさにこれ。

私はあなたのコンピュータを取り、それをオン/オフする方法を追加します

public class Computer {
    private boolean isOn = true;
    private String description = "Computer";        

    public vod turnOn(){
        this.isOn=true;
    }

    public void turnOff(){
        this.isOn = false;
    }

    public void setDescription(String description){
        this.description = description;
    }

    public String Description(){
        return this.description;
    }
}

現在、コンピューターの電源を切ることができないデコレーターを作成しています。

public class ComputerDecorator1 extends Computer {
    private Computer computer;

    public ComputerDecorator1(Computer computer){
       this.computer = computer;
    }

    public vod turnOn(){
        this.computer.turnOn();
    }

    public void turnOff(){
        System.out.println("You cannot turn me off!!!!");
    }

    public void setDescription(String description){
        this.computer.setDescrition(descritption);
    }

    public String Description(){
        return this.computer.Description();
    }
}

ご覧のとおり、コンストラクターで彼に Computer インスタンスを与える必要があります。これが私たちが飾っているコンピュータです。すべてのメソッド呼び出しは、このクラスに渡されます。通常、すべてのメソッドを上書きして、装飾されたオブジェクトに渡す必要があります。この場合、コンピュータ。

これを使用して、新しいクラスを作成することなく、オブジェクトの動作を変更できます。利点は、別の場所からコンピューターのインスタンスを取得するときに、このフィルターを追加できるため、プログラムの残りの部分がそれをオフにできないことです。

これは、プログラムでデコレーターを使用する方法です。

public void getMyComputerAndTurnItOff(){
    Computer myComputer = getMyComputer();
    myComputer.turnOff();
}

public Computer getMyComputer(){
    //Here you will load a Computer from an other class
    Computer computer = this.otherClass.loadComputerFromDB();

    //Now we could return it, but what if you shouldn't be able to turn it off?
    //easy add our decorator
    return new ComputerDecorator1(computer);
}

デコレータを使用したい場合は、動作を変更する必要があります。そうしないと役に立ちません! 論理的なポイントからのコンピューターとモニターの例では、モニターはコンピューターのデコレーターになることはできません。私にとって、これらは 2 つの異なるオブジェクトです。

デコレータとは何かをもう少し明確にしていただければ幸いです。

于 2012-04-04T08:16:55.850 に答える