摘要:測(cè)試類設(shè)計(jì)模式裝飾者模式工廠模式只能讀啦會(huì)報(bào)錯(cuò)只讀異??梢哉_運(yùn)行第二部分定義抽象組件是具體組件和抽象裝飾類的共同父類,聲明了在具體組件中實(shí)現(xiàn)的方法。
前言
本篇文章分為四個(gè)部分:第一部分會(huì)舉一個(gè)例子引出裝飾者模式,讓讀者對(duì)裝飾者模式有個(gè)感官上的認(rèn)識(shí);第二部分會(huì)給出裝飾者模式的定義(當(dāng)然我們主要不是來(lái)背定義,就當(dāng)做積累專業(yè)名詞來(lái)記吧,我個(gè)人是很不喜歡下定義的);第三部分,我會(huì)拿jdk中兩個(gè)使用裝飾者模式的例子進(jìn)行分析,讓讀者在學(xué)習(xí)模式的同時(shí)熟悉一下jdk源碼。第四部分,我會(huì)結(jié)合裝飾者模式理清楚java I/O各種流之間的關(guān)系(說(shuō)實(shí)話,工作中用得最多,但是記了又忘,因?yàn)镮/O類實(shí)在太多)后面學(xué)習(xí)到其他框架的時(shí)候再補(bǔ)充。
第一部分假如有這樣的需求:要求實(shí)現(xiàn)只能夠讀的List,要是你來(lái)完成這個(gè)任務(wù)你會(huì)如何做?
看下面代碼實(shí)現(xiàn):
package decorate; import java.util.*; public class ReadOnlyListimplements List { private List target; public ReadOnlyList(List target) { super(); this.target = target; } @Override public int size() { return target.size(); } @Override public boolean isEmpty() { return target.isEmpty(); } @Override public boolean contains(Object o) { return target.contains(o); } @Override public Iterator iterator() { return target.iterator(); } @Override public Object[] toArray() { return target.toArray(); } @Override public T[] toArray(T[] a) { return target.toArray(a); } @Override public boolean add(E e) { throw new RuntimeException("only read"); } @Override public boolean remove(Object o) { throw new RuntimeException("only read"); } @Override public boolean containsAll(Collection> c) { return target.containsAll(c); } @Override public boolean addAll(Collection extends E> c) { throw new RuntimeException("only read"); } @Override public boolean removeAll(Collection> c) { throw new RuntimeException("only read"); } @Override public boolean retainAll(Collection> c) { throw new RuntimeException("only read"); } @Override public void clear() { throw new RuntimeException("only read"); } @Override public boolean addAll(int index, Collection extends E> c) { throw new RuntimeException("only read"); } @Override public E get(int index) { return target.get(index); } @Override public E set(int index, E element) { throw new RuntimeException("only read"); } @Override public void add(int index, E element) { throw new RuntimeException("only read"); } @Override public E remove(int index) { throw new RuntimeException("only read"); } @Override public int indexOf(Object o) { return target.indexOf(o); } @Override public int lastIndexOf(Object o) { return target.lastIndexOf(o); } @Override public ListIterator listIterator() { return target.listIterator(); } @Override public ListIterator listIterator(int index) { return target.listIterator(index); } @Override public List subList(int fromIndex, int toIndex) { return target.subList(fromIndex, toIndex); } }
這里的set,add,remove和addAll等操作都被限制了,只能夠讀。
測(cè)試類
package decorate; import java.util.ArrayList; import java.util.List; public class ReadOnlyListMain { public static void main(String[] args) { List第二部分 定義list = new ArrayList<>(); list.add("設(shè)計(jì)模式"); list.add("裝飾者模式"); list.add("工廠模式"); ReadOnlyList onlyList = new ReadOnlyList<>(list); // onlyList.add("只能讀啦"); // 會(huì)報(bào)錯(cuò)只讀異常 System.out.println(onlyList.size()); // 可以正確運(yùn)行 } }
Component(抽象組件): 是具體組件和抽象裝飾類的共同父類,聲明了在具體組件中實(shí)現(xiàn)的方法。比如第一部分的List
ConcreteComponent(具體組件): 抽象組件的子類,實(shí)現(xiàn)抽象組件的方法,裝飾器可以給他加新的功能。比如ReadOnlyList
Decorator(抽象裝飾者): 抽象組件的子類,用來(lái)裝飾具體組件或者裝飾其他裝飾組件
ConcreteDecorator(具體裝飾者):抽象裝飾類的子類
具體的可以看下面的結(jié)構(gòu)圖:
第一部分我們引出裝飾者模式,ReadOnlyList 只讀List將List給包裝起來(lái),提供了只讀的功能,jdk Collection中也有個(gè)類似的實(shí)現(xiàn):
public static
讓我來(lái)看看它的源碼:
public staticList unmodifiableList(List extends T> list) { return (list instanceof RandomAccess ? new UnmodifiableRandomAccessList<>(list) : new UnmodifiableList<>(list)); }
我們進(jìn)入 UnmodifiableList
/** * @serial include */ static class UnmodifiableListextends UnmodifiableCollection implements List { private static final long serialVersionUID = -283967356065247728L; final List extends E> list; UnmodifiableList(List extends E> list) { super(list); this.list = list; } public boolean equals(Object o) {return o == this || list.equals(o);} public int hashCode() {return list.hashCode();} public E get(int index) {return list.get(index);} public E set(int index, E element) { throw new UnsupportedOperationException(); } public void add(int index, E element) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); } public int indexOf(Object o) {return list.indexOf(o);} public int lastIndexOf(Object o) {return list.lastIndexOf(o);} public boolean addAll(int index, Collection extends E> c) { throw new UnsupportedOperationException(); } @Override public void replaceAll(UnaryOperator operator) { throw new UnsupportedOperationException(); } @Override public void sort(Comparator super E> c) { throw new UnsupportedOperationException(); } public ListIterator listIterator() {return listIterator(0);} public ListIterator listIterator(final int index) { return new ListIterator () { private final ListIterator extends E> i = list.listIterator(index); public boolean hasNext() {return i.hasNext();} public E next() {return i.next();} public boolean hasPrevious() {return i.hasPrevious();} public E previous() {return i.previous();} public int nextIndex() {return i.nextIndex();} public int previousIndex() {return i.previousIndex();} public void remove() { throw new UnsupportedOperationException(); } public void set(E e) { throw new UnsupportedOperationException(); } public void add(E e) { throw new UnsupportedOperationException(); } @Override public void forEachRemaining(Consumer super E> action) { i.forEachRemaining(action); } }; } public List subList(int fromIndex, int toIndex) { return new UnmodifiableList<>(list.subList(fromIndex, toIndex)); } private Object readResolve() { return (list instanceof RandomAccess ? new UnmodifiableRandomAccessList<>(list) : this); } }
你們發(fā)現(xiàn)了啥,沒(méi)錯(cuò),就是它:addAll、replaceAll和sort等都拋出 UnsupportedOperationException異常,說(shuō)明只支持讀。
還沒(méi)結(jié)束,再舉個(gè)例子,Collections中還有將線程不安全的集合轉(zhuǎn)換成線程安全的集合synchronizedList,也就是使用裝飾者模式,本質(zhì)上就是在方法加上synchronized 同步鎖
讓我們看源碼:
public staticList synchronizedList(List list) { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : new SynchronizedList<>(list)); }
老規(guī)矩,進(jìn)入SynchronizedList
/** * @serial include */ static class SynchronizedListextends SynchronizedCollection implements List { private static final long serialVersionUID = -7754090372962971524L; final List list; SynchronizedList(List list) { super(list); this.list = list; } SynchronizedList(List list, Object mutex) { super(list, mutex); this.list = list; } public boolean equals(Object o) { if (this == o) return true; synchronized (mutex) {return list.equals(o);} } public int hashCode() { synchronized (mutex) {return list.hashCode();} } public E get(int index) { synchronized (mutex) {return list.get(index);} } public E set(int index, E element) { synchronized (mutex) {return list.set(index, element);} } public void add(int index, E element) { synchronized (mutex) {list.add(index, element);} } public E remove(int index) { synchronized (mutex) {return list.remove(index);} } public int indexOf(Object o) { synchronized (mutex) {return list.indexOf(o);} } public int lastIndexOf(Object o) { synchronized (mutex) {return list.lastIndexOf(o);} } public boolean addAll(int index, Collection extends E> c) { synchronized (mutex) {return list.addAll(index, c);} } public ListIterator listIterator() { return list.listIterator(); // Must be manually synched by user } public ListIterator listIterator(int index) { return list.listIterator(index); // Must be manually synched by user } public List subList(int fromIndex, int toIndex) { synchronized (mutex) { return new SynchronizedList<>(list.subList(fromIndex, toIndex), mutex); } } @Override public void replaceAll(UnaryOperator operator) { synchronized (mutex) {list.replaceAll(operator);} } @Override public void sort(Comparator super E> c) { synchronized (mutex) {list.sort(c);} } private Object readResolve() { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : this); }
嘿嘿,我們現(xiàn)在已經(jīng)學(xué)會(huì)從設(shè)計(jì)模式的角度看jdk源碼啦,開(kāi)心。
第四部分 Java I/O流中的裝飾者模式我們來(lái)看看Java I/O中的流圖
我們以輸入流來(lái)分析,首先InputStream 相當(dāng)于我們的抽象組件,F(xiàn)ileInputStream、StringBufferInputStream、ByteArrayInputStream都是可以被裝飾者包裝起來(lái)的組件,F(xiàn)ilterInputStream相當(dāng)于抽象裝飾者,PushbackInputStream、BufferedInputStream、DataInputStream和LineNumberInputStream都是具體的裝
飾者
他們可以這樣用: 一層裝飾一層
InputStream ip = new DataInputStream(new BufferedInputStream(new FileInputStream(new File("/file_path"))));
如下圖所示:
有了這樣的思路,我們以后想編寫自己的I/O,給流增加新的特性,我們就可以繼承FilterInputStream,
package decorate; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; /** * 將輸入的流內(nèi)所有的大寫字符轉(zhuǎn)成小寫字符 */ public class LowerCaseInputStream extends FilterInputStream{ public LowerCaseInputStream(InputStream in) { super(in); } @Override public int read() throws IOException { int c = super.read(); if (c == -1) { return c; } else { return 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 < off + result; i++) { b[i] = (byte) Character.toLowerCase((char)b[i]); } return result; } }
測(cè)試類:把文件路徑替換成你自己的路徑
package decorate; import java.io.*; /** * 測(cè)試類 */ public class MyInputStreamTest { public static void main(String[] args) { int c; try { InputStream in = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("file_path"))); while((c = in.read()) >= 0) { System.out.println((char)c); } } catch (IOException e) { e.printStackTrace(); } } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/75010.html
摘要:什么是裝飾者模式今天我們來(lái)講另外一個(gè)非常實(shí)用的設(shè)計(jì)模式裝飾者模式。就增加功能來(lái)說(shuō),裝飾者模式相比生成子類更為靈活。下面,裝飾者模式就要正式登場(chǎng)了。下一步,我們可以愉快的去使用裝飾者模式啦 什么是裝飾者模式 今天我們來(lái)講另外一個(gè)非常實(shí)用的設(shè)計(jì)模式:裝飾者模式。這個(gè)名字聽(tīng)上去有些莫名其妙,不著急,我們先來(lái)記住它的一個(gè)別名:包裝器模式。 我們記著這兩個(gè)名字來(lái)開(kāi)始今天的文章。 首先還是上《設(shè)計(jì)...
摘要:相關(guān)設(shè)計(jì)模式裝飾者模式和代理模式裝飾者模式關(guān)注再一個(gè)對(duì)象上動(dòng)態(tài)添加方法代理模式關(guān)注再對(duì)代理對(duì)象的控制訪問(wèn),可以對(duì)客戶隱藏被代理類的信息裝飾著模式和適配器模式都叫包裝模式關(guān)于新職責(zé)適配器也可以在轉(zhuǎn)換時(shí)增加新的職責(zé),但主要目的不在此。 0x01.定義與類型 定義:裝飾模式指的是在不必改變?cè)愇募褪褂美^承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能。它是通過(guò)創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾來(lái)包裹真實(shí)的...
摘要:裝飾者模式組成結(jié)構(gòu)抽象構(gòu)件給出抽象接口或抽象類,以規(guī)范準(zhǔn)備接收附加功能的對(duì)象。裝飾者模式圖解裝飾者模式應(yīng)用場(chǎng)景需要擴(kuò)展一個(gè)類的功能,或給一個(gè)類添加附加職責(zé)。裝飾者對(duì)象接受所有來(lái)自客戶端的請(qǐng)求。參考資料設(shè)計(jì)模式 一、了解裝飾者模式 1.1 什么是裝飾者模式 裝飾者模式指的是在不必改變?cè)愇募褪褂美^承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能。它是通過(guò)創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾者來(lái)包裹真實(shí)的對(duì)...
摘要:這是設(shè)計(jì)模式系列的第二篇,系列文章目錄如下用一句話總結(jié)那些殊途同歸的設(shè)計(jì)模式工廠策略模版方法美顏相機(jī)中的設(shè)計(jì)模式裝飾者模式幾乎所有的設(shè)計(jì)模式都是通過(guò)增加一層抽象來(lái)解決問(wèn)題。 這是設(shè)計(jì)模式系列的第二篇,系列文章目錄如下: 用一句話總結(jié)那些殊途同歸的設(shè)計(jì)模式:工廠=?策略=?模版方法 美顏相機(jī)中的設(shè)計(jì)模式——裝飾者模式 幾乎所有的設(shè)計(jì)模式都是通過(guò)增加一層抽象來(lái)解決問(wèn)題。 上一篇中提...
摘要:作者按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用和兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)現(xiàn)方式,但此小冊(cè)只記錄最直截了當(dāng)?shù)膶?shí)現(xiàn)方式原文地址是每天一個(gè)設(shè)計(jì)模式之裝飾者模式歡迎關(guān)注個(gè)人技術(shù)博客。 作者按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript和python兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)現(xiàn)方式,但此小冊(cè)只記錄最直截了當(dāng)?shù)膶?shí)現(xiàn)方式...
閱讀 3904·2021-09-27 13:35
閱讀 1083·2021-09-24 09:48
閱讀 2912·2021-09-22 15:42
閱讀 2353·2021-09-22 15:28
閱讀 3156·2019-08-30 15:43
閱讀 2624·2019-08-30 13:52
閱讀 2981·2019-08-29 12:48
閱讀 1460·2019-08-26 13:55