Java:一夜一発デザインモード(一)------デコレーションモード

15208 ワード

一、装飾者モードはいつ使いますか?
例えば、ある店で飲み物を売っていると、飲み物にはいろいろな種類があります.それぞれに追加することができます.例えば、コーラに氷を入れたり、砂糖を入れたり、水を入れたりすることができます.追加するたびに価格が異なり、コードが煩雑になります.この場合、装飾者モードを使って実現することができます.
二、装飾者モードとは何ですか.
上記の例では、飲み物を主体として、不要な様々なニーズで装飾することができ、例えばコーラのオブジェクトがある場合、私は氷を入れるオブジェクトで装飾し、砂糖を入れるオブジェクトで装飾し、最後に氷を入れる砂糖を入れるコーラを得ることができ、この時、元のコーラのオブジェクトを拡張し、氷を入れる砂糖を入れる2つの装飾を得ることができる.装飾者モード:オブジェクトに動的に責任を付加する、拡張機能に対して、装飾者は継承よりも弾力性がある(子類が親拡張機能を継承する前提は、拡張する機能がどのようなものかが知られているため、コンパイル時に決定されるが、装飾者モードは動的(実行時)に拡張機能を実現することができる).
三、装飾者モード構造
Decorator:装飾者の親であり、各装飾者はこの抽象類を継承する必要がある(またはこのインタフェースを実現する).ConcreteDecoratorA/B:具体的な装飾者としては、上記の例における氷、砂糖等が対応する.ConcreteComponent:具体的な対象は、上記の例のコーラである.Component:装飾者モードの中で最もトップクラスの親であり、装飾者と被装飾者はその子または実現類である.
四、コードが立ち上がる
コードディレクトリ構造:
最上位の親の作成
飲み物類:すべての装飾された類はそれを受け継ぐ必要がある.
package componet;

/**
 * Created by zyf on 2017/3/30.
 *             
 */
public abstract class    {
    String name;

    /**
     *          ,   price     
* " " * */
public abstract int price(); /*** * * @return */ public String getName(){ return name; } }

飾られたコーラComponent類
package componet;

/**
 * Created by zyf on 2017/3/30.
 */
public class   Component extends    {

    public   Component() {
        //  name   
        //  name            
        name = "  ";
    }

    /***
     *          
     * @return      
     */
    @Override
    public int price() {
        //  30   ~
        return 30;
    }
}

飾られたビールComponent類
package componet;

/**
 * Created by zyf on 2017/3/30.
 */
public class   Component  extends   {
    public   Component() {
        //  name   
        //  name            
        name = "  ";
    }

    /***
     *          
     * @return      
     */
    @Override
    public int price() {
        //  3   ~
        return 3;
    }
}

Decoratorクラス、すべての装飾クラスの親
package decorator;

import componet.  ;

/**
 * Created by zyf on 2017/3/30.
 *       ,        
 */
public abstract class Decorator extends    {

    /***
     *         ,          
*/
protected yp; public Decorator( yp) { this.yp = yp; } }

装飾類:酢入りデコレータ類
package decorator;

import componet.  ;

/**
 * Created by zyf on 2017/3/30.
 */
public class   Decorator extends Decorator {


    public   Decorator(   yp) {
        super(yp);
    }

    public void addVinegar(){
        System.out.println("    ,   ");
    }

    /***
     *               ?
* * @return */
@Override public int price() { return 5 + yp.price(); } /*** *
* * @return */
@Override public String getName() { // addVinegar(); return " " + yp.getName(); } }

装飾類:水割りDecorator類
package decorator;

import componet.  ;

/**
 * Created by zyf on 2017/3/30.
 */
public class   Decorator extends Decorator {


    public   Decorator(   yp) {
        super(yp);
    }

    public void   (){
        System.out.println("    ....     ...");
    }

    /***
     *               ?
* * @return 2 */
@Override public int price() { return 2 + yp.price(); } /*** *
* * @return */
@Override public String getName() { (); return " " + yp.getName(); } }

五、テストクラス
public static void main(String[] args) {
  //    ,            yp
  //                   
  //                  ,      ,                    (         )
       yp = new   Component();
    yp = new   Decorator(yp);
    yp = new   Decorator(yp);
//              ,    IO   ?
//  yp = new   Decorator(new   Decorator(new   Component()));

    System.out.println("   :" + yp.getName() + "---  :" + yp.price());
}

六、カスタムIOストリームプレゼンテーション
Java中のIOストリームは装飾者モードの典型的な例であるので、自分で装飾クラスのプレゼンテーションを書いて、読み取った英語の文字をすべて大文字に切り替える変換ストリームを完成することができます.
package main;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Created by zyf on 2017/3/29.
 */
public class ToUpperCaseInputStream extends FilterInputStream {

    InputStream inputStream;

    /**
     * Creates a FilterInputStream
     * by assigning the  argument in
     * to the field this.in so as
     * to remember it for later use.
     *
     * @param in the underlying input stream, or null if
     *           this instance is to be created without an underlying stream.
     */
    protected ToUpperCaseInputStream(InputStream in) {
        super(in);
        this.inputStream = in;
    }

    /**
     *       
     * @return
     * @throws IOException
     */
    @Override
    public int read() throws IOException {
        //         
        int result = super.read();
        //       a,     
        if(result == 'a'){
            throw new ToUpperException();
        }
        //    -1,     
        //  ,     char,  char         
        //      int  ,              
        return (result == -1 ? result : Character.toUpperCase(Character.toChars(result)[0]));
    }

    /**
     *        b    , off,  len     
* for i off, off * @param b * @param off * @param len * @return * @throws IOException */
@Override public int read(byte[] b, int off, int len) throws IOException { int result = super.read(b,off,len); for (int i = off; i < off + result; i++) { // b[i] = (byte) Character.toUpperCase((char)b[i]); } return result; } /*** * , */ class ToUpperException extends IOException { @Override public void printStackTrace() { System.out.println(" , "); } } }
private static void toUpper() {
    int result = 0;
    InputStream inputStream = null;
    try {
        inputStream = new ToUpperCaseInputStream(new BufferedInputStream(new FileInputStream("test.txt")));

        while ((result = inputStream.read()) >= 0) {
            System.out.print((char) result);
        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

七、まとめ
  • 装飾者モードは六大原則の一つである開閉原則に非常に適合することができる.
  • 継承は拡張も可能であるが、継承する拡張需要はすでに拡張需要があり、コンパイル期間に拡張し、装飾者モードは運転期間に拡張することができる.
  • の装飾者は、被装飾者の行為において行為を拡張することもできるし、被装飾者の行為を完全に代替することもできる.
  • 一般的な場合の引用は親の引用を用いるが、装飾者の引用を用いれば、その装飾者独自の方法を用いることになる.
  • 装飾者モードを使用すると、クラスの数が多くなり、過度に使用することはできません.主に他の人のコードを見ているときに装飾者モードに出会って自分で分からないと、愚かになるのは普通です.
  • は巨人の肩に立って、一緒に頑張りましょう.