『JAVAとモード』のリフォーム者モード

23354 ワード

デコレーションモード
オブジェクトに責任を動的に付加します.機能を拡張するには、装飾者は継承よりも弾力性のある代替案を提供します.
具体的には被装飾者も抽象装飾類も抽象被装飾者類に継承され、行為ではなくタイプが継承される.動作は、装飾者とベースコンポーネント、または他の装飾者との組合せ関係から生じる.
デコレーションモードのキャラクター
抽象コンポーネントロール(Component):追加の責任を受け取るオブジェクトを指定する抽象インタフェースが与えられます.
コンポーネントロール(Concrete Component):追加の責任を受け取るクラスを定義します.
装飾キャラクタ(Decorator):コンポーネントオブジェクトの参照を持ち、抽象コンポーネントインタフェースと一致するインタフェースを定義します.
具体的な装飾キャラクタ(Concrete Decorator):コンポーネントオブジェクトに「貼り付け」を付加する責任を負います.
装飾モードの特徴
装飾オブジェクトと実際のオブジェクトには同じインタフェースがあります.これにより、クライアントオブジェクトは、実際のオブジェクトと同じ方法で装飾オブジェクトとインタラクティブになります.
装飾オブジェクトには、実際のオブジェクトの参照(reference)が含まれます.
装飾オブジェクトは、クライアントからのすべてのリクエストを受信し、これらのリクエストを実際のオブジェクトに転送します.
装飾オブジェクトは、これらのリクエストを転送する前または後にいくつかの機能を付加することができる.
これにより、実行時に特定のオブジェクトの構造を変更することなく、外部に追加の機能を追加できることが保証されます.
 
コード#コード#
 1 public class Zhuangxiuzhe {
 2     public static void main(String[] args) {
 3         Zhuangxiuzhe zhuangxiuzhe=new Zhuangxiuzhe();
 4         Component component=zhuangxiuzhe.new ConcreteComponent();
 5         Component decorator=zhuangxiuzhe.new ConcreteDecorator1(component);
 6         decorator.doMethod();
 7         Component decorator2=zhuangxiuzhe.new ConcreteDecorator2(decorator);
 8         decorator2.doMethod();
 9         
10     }
11 
12     interface Component {
13 
14         public void doMethod();
15 
16     }
17 
18     class ConcreteComponent implements Component {
19 
20         public void doMethod() {
21             System.out.println("    ");
22 
23         }
24 
25     }
26     abstract class  Decorator implements Component{
27         
28         protected Component component;
29         public Decorator(Component component){
30             this.component=component;
31         }
32             
33         
34     }
35     class ConcreteDecorator1 extends Decorator{
36 
37         public ConcreteDecorator1(Component component) {
38             super(component);
39             
40         }
41         public void test1(){
42             System.out.println("ConcreteDecorator1     ");
43         }
44 
45         public void doMethod() {
46             super.component.doMethod();
47             test1();
48         }
49     }
50     class ConcreteDecorator2 extends Decorator{
51         
52         public ConcreteDecorator2(Component component) {
53             super(component);
54             
55         }
56         
57         public void doMethod() {
58             super.component.doMethod();
59             test2();
60         }
61         
62         public void test2(){
63             System.out.println("ConcreteDecorator2     ");
64         }
65     }
66     
67 
68 }

実行結果
一般操作ConcreteDecorator 1追加操作一般操作ConcreteDecorator 1追加操作ConcreteDecorator 2追加操作
 
 突然、装飾者モードが責任チェーンモードと少し同じであることに気づき、自身が抽象クラスを引用し、伝達された包装クラスを呼び出すことができるようになった.
違いは機能上:責任チェーンは誰が処理するかを強調し、装飾者モデルは導入対象の既存の機能を包装し、変化を強化する.
Java IOでのデコレーションモード
IOでは、特定のコンポーネントキャラクタはノードフローであり、装飾キャラクタはフィルタフローである.
FilterInputStreamとFilterOutputStreamは装飾キャラクタであり、他の派生クラスは具体的な装飾キャラクタである.
コードを見てみましょう
抽象キャラクタクラスInputStream
1 public abstract class InputStream implements Closeable {
2 
3 
4 //   read   
5 public int read(byte b[]) throws IOException {
6     return read(b, 0, b.length);
7     }
8 
9 }

具体的なロールクラスFileInputStream
1 public
2 class FileInputStream extends InputStream{
3 
4 
5 }

抽象パッケージクラスFilterInputStream
 1 public
 2 class FilterInputStream extends InputStream {
 3     /**
 4      * The input stream to be filtered. 
 5      */
 6     protected volatile InputStream in;
 7 
 8 
 9 protected FilterInputStream(InputStream in) {
10     this.in = in;
11     }
12 
13  public int read() throws IOException {
14     return in.read();
15     }
16 
17 
18 }

パッケージクラスBufferedInputStream
 1 public
 2 class BufferedInputStream extends FilterInputStream {
 3 
 4 public BufferedInputStream(InputStream in) {
 5     this(in, defaultBufferSize);
 6     }
 7 
 8 //             
 9  public BufferedInputStream(InputStream in, int size) {
10     super(in);
11         if (size <= 0) {
12             throw new IllegalArgumentException("Buffer size <= 0");
13         }
14     buf = new byte[size];
15     }
16 
17 //read     fill()
18  public synchronized int read() throws IOException {
19     if (pos >= count) {
20         fill();
21         if (pos >= count)
22         return -1;
23     }
24     return getBufIfOpen()[pos++] & 0xff;
25     }
26  private void fill() throws IOException {
27         byte[] buffer = getBufIfOpen();
28     if (markpos < 0)
29         pos = 0;        /* no mark: throw away the buffer */
30     else if (pos >= buffer.length)    /* no room left in buffer */
31         if (markpos > 0) {    /* can throw away early part of the buffer */
32         int sz = pos - markpos;
33         System.arraycopy(buffer, markpos, buffer, 0, sz);
34         pos = sz;
35         markpos = 0;
36         } else if (buffer.length >= marklimit) {
37         markpos = -1;    /* buffer got too big, invalidate mark */
38         pos = 0;    /* drop buffer contents */
39         } else {        /* grow buffer */
40         int nsz = pos * 2;
41         if (nsz > marklimit)
42             nsz = marklimit;
43         byte nbuf[] = new byte[nsz];
44         System.arraycopy(buffer, 0, nbuf, 0, pos);
45                 if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
46                     // Can't replace buf if there was an async close.
47                     // Note: This would need to be changed if fill()
48                     // is ever made accessible to multiple threads.
49                     // But for now, the only way CAS can fail is via close.
50                     // assert buf == null;
51                     throw new IOException("Stream closed");
52                 }
53                 buffer = nbuf;
54         }
55         count = pos;
56     int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
57         if (n > 0)
58             count = n + pos;
59     }
60 
61 
62 }

fill()メソッドでは,自己操作のほかに, int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
1  private InputStream getInIfOpen() throws IOException {
2         InputStream input = in;
3     if (input == null)
4         throw new IOException("Stream closed");
5         return input;
6     }

getInIfOpen()メソッドを見ると、プロセス全体がわかります.
 
参照先:
http://www.cnblogs.com/mengdd/archive/2013/02/12/2910302.html
http://blog.csdn.net/cai1213/article/details/8003445
http://xubindehao.iteye.com/blog/474636