装飾者モードとJava APIでの運用


一、装飾者モードの紹介
装飾者モードは,オブジェクト向けプログラミング分野において,動的にクラスに新しい挙動を追加する設計モードである.機能については、デザイナモードがサブクラスを生成するよりも柔軟であり、クラス全体ではなくオブジェクトにいくつかの機能を追加することができます.
1.基本原理
デザイナモードを使用することで、実行時にクラスの機能を拡張できます.原理は:1つの装飾類を増やして元の類を包み、包みの方式は一般的に元の対象を修飾類の構造関数のパラメータとすることによってである.装飾クラスは新しい機能を実現するが,新しい機能を必要としない場所では,元のクラスのメソッドを直接呼び出すことができる.装飾類は元の類と同じインタフェースを持たなければならない.
装飾者モードはクラス継承の別の選択です.クラス継承はコンパイル時に動作を増加させ、装飾者モードは実行時に動作を増加させる.
いくつかの相互に独立した機能が拡張される必要がある場合,この違いは重要になる.オブジェクト向けのプログラミング言語では、クラスは実行時に作成できません.通常、設計時にどの機能の組み合わせがあるか予測できません.これは、各組合せに新しいクラスを作成することを意味します.逆に、装飾者モードは、実行時のオブジェクトインスタンス向けであり、実行時に必要に応じて組み合わせることができる.装飾者モードの一例はJAVAにおけるJava I/O Streamsの実装である.
装飾者モードのUMLクラス図:
2.サンプルコード
土鍋羊肉麺を例として、なぜかと聞かないで(′°□°)|(┻━┻
ComponentはMarmite(土鍋)類に相当します.
public abstract class Marmite {
    String description = "  ";

    public String getDescription() {
        return description;
    }

    public abstract Integer cost();

    @Override
    public String toString() {
        return "    :" + getDescription() + ",  :" + cost() + " ";
    }
}

ConcreteComponentはNoddlesMarmite(土鍋うどん)類です.
public class NoddlesMarmite extends Marmite {

    public NoddlesMarmite() {
        description = "    ";
    }

    public Integer cost() {
        return 8;
    }
}

DecoratorはMaterialDecorator
public abstract class MaterialDecorator extends Marmite {
    public abstract String getDescription();
}

ConcreteDecoratorはMuttonMarmiteです.
public class MuttonMarmite extends MaterialDecorator {
    Marmite marmite;

    public MuttonMarmite(Marmite marmite) {
        this.marmite = marmite;
    }

    @Override
    public String getDescription() {
        return "  、" + marmite.getDescription();
    }

    @Override
    public Integer cost() {
        return 5 + marmite.cost();
    }
}

これはテストコードです.
public class MarmiteTest {
    public static void main(String[] args) {
        Marmite marmiteNoddle = new NoddlesMarmite();
        System.out.println(marmiteNoddle.toString());
        Marmite muttonMarmiteNoddle = new MuttonMarmite(marmiteNoddle);
        System.out.println(muttonMarmiteNoddle.toString());
    }
}

二、Java APIにおける装飾者の運用
まずdemoを見てみましょう
public class JavaDemo {
    public static void main(String[] args) {
        System.out.println("      :");
        BufferedInputStream bufferedInputStream = new BufferedInputStream(System.in);
        String msg = "wocao";
        try {
            BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(bufferedInputStream));
            msg = bufferedReader.readLine();
        } catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("    :" + msg);
    }
}

このコードの機能は、コンソールに入力された内容を印刷することです.
Java apiを見るとBufferedInputStreamがFilterInputStreamを継承していることがわかります.次の図です.FilterInputStreamはInputStreamを継承し、InputStreamオブジェクトの参照があります.
ここから
InputStreamはComponent、FilterInputStreamはDecorator、BufferedInputStreamはConcreteDecorator、Systemに相当する.inはConcreteComponentに相当します.
三、自らInputStreamに関するConcreteDecoratorを実現する
talk is cheap, show me the code
public class LowerCaseInputStream extends FilterInputStream {

    public LowerCaseInputStream(InputStream in){
        super(in);
    }

    @Override
    public int read() throws IOException {
        int c=super.read();
        return (c==-1?c:Character.toLowerCase((char)c));
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int result=super.read(b,off,len);
        for(int i=off;i

説明したくなくて、心が疲れて読めないので、図をあげます.
---------------------------------------EOF--------------------------------------
参考資料:
  • https://zh.wikipedia.org/wiki...
  • Head First設計モード
  • 私の愿いは世界平和です!( ゜▽゜)つロ