裝飾:基於已有的功能,並提供加強功能,裝飾類通常會通過構造方法接收被裝飾的對象。並基於被裝飾的對象的功能,提供更強的功能。相對於繼承來說裝飾模式可以在不使用創造更多子類的情況下,將對象的功能加以擴展。英文叫:Decorator
繼承:因為要擴展某個功能,就得繼承父類,然後覆蓋重寫,導致這個體系更加臃腫,並且內存占用高。
一般情況下,其實接口也可以當做一種抽象類來看待,也就是說父類對象也可以是接口,如果一個類A實現了一個接口T,當我們在聲明實例:T t =new A();時,t看起來是一個T,本質上是一個A,這也是多態的一種!
驗證一下,首先先創建一個接口a:
1 public class test {
2 interface a{
3 void fun();
4 }
5 class b implements a{
6
7 public void fun() {
8 System.out.println("這個實現接口類!");
9 }
10
11 }
12 class c extends b{
13 public void fun(){
14 System.out.println("這是實現接口類的子類!!");
15 }
16 }
17 public static void main(String[] args) {
18 a dd = new test().new c();
19 dd.fun();
20 }
21 }
運行:

摘自CSDN的一位大神的例子,看這個程序只要多態的功能理清楚也就明白了,說白了裝飾模式無非就是多態與構造方法的靈活運用罷了:
1 public class decorateMode{
2 //定義被裝飾者
3 public interface Human {
4 public void wearClothes();
5
6 public void walkToWhere();
7 }
8
9 //定義裝飾者
10 public abstract class Decorator implements Human {
11 private Human human;
12
13 public Decorator(Human human) {
14 this.human = human;
15 }
16
17 public void wearClothes() {
18 human.wearClothes();
19 }
20
21 public void walkToWhere() {
22 human.walkToWhere();
23 }
24 }
25
26 //下面定義三種裝飾,這是第一個,第二個第三個功能依次細化,即裝飾者的功能越來越多
27 public class Decorator_zero extends Decorator {
28
29 public Decorator_zero(Human human) {
30 super(human);
31 }
32
33 public void goHome() {
34 System.out.println("進房子。。");
35 }
36
37 public void findMap() {
38 System.out.println("書房找找Map。。");
39 }
40
41 public void wearClothes() {
42 // TODO Auto-generated method stub
43 super.wearClothes();
44 goHome();
45 }
46
47 public void walkToWhere() {
48 // TODO Auto-generated method stub
49 super.walkToWhere();
50 findMap();
51 }
52 }
53
54 public class Decorator_first extends Decorator {
55
56 public Decorator_first(Human human) {
57 super(human);
58 }
59
60 public void goClothespress() {
61 System.out.println("去衣櫃找找看。。");
62 }
63
64 public void findPlaceOnMap() {
65 System.out.println("在Map上找找。。");
66 }
67
68 public void wearClothes() {
69 // TODO Auto-generated method stub
70 super.wearClothes();
71 goClothespress();
72 }
73
74 public void walkToWhere() {
75 // TODO Auto-generated method stub
76 super.walkToWhere();
77 findPlaceOnMap();
78 }
79 }
80
81 public class Decorator_two extends Decorator {
82
83 public Decorator_two(Human human) {
84 super(human);
85 }
86
87 public void findClothes() {
88 System.out.println("找到一件D&G。。");
89 }
90
91 public void findTheTarget() {
92 System.out.println("在Map上找到神秘花園和城堡。。");
93 }
94
95 public void wearClothes() {
96 // TODO Auto-generated method stub
97 super.wearClothes();
98 findClothes();
99 }
100
101 public void walkToWhere() {
102 // TODO Auto-generated method stub
103 super.walkToWhere();
104 findTheTarget();
105 }
106 }
107
108 //定義被裝飾者,被裝飾者初始狀態有些自己的裝飾
109 public class Person implements Human {
110
111 public void wearClothes() {
112 // TODO Auto-generated method stub
113 System.out.println("穿什麼呢。。");
114 }
115
116 public void walkToWhere() {
117 // TODO Auto-generated method stub
118 System.out.println("去哪裡呢。。");
119 }
120 }
121 //測試類,看一下你就會發現,跟java的I/O操作有多麼相似
122 public static void main(String[] args) {
123 decorateMode decorateMode=new decorateMode();
124 Human person =decorateMode. new Person();
125 Decorator decorator = decorateMode.new Decorator_two(decorateMode.new Decorator_first(
126 decorateMode.new Decorator_zero(person)));
127 decorator.wearClothes();
128 decorator.walkToWhere();
129 }
130 }
運行結果:

讀取文件的行內容,並給每行前加上行數、行後加上分號
1 package com.beiwo.Io;
2
3 import java.io.BufferedReader;
4 import java.io.FileNotFoundException;
5 import java.io.FileReader;
6 import java.io.IOException;
7 import java.io.Reader;
8
9 /*
10
11 BufferedReader : 拓展FileReader的功能。
12
13 需求1 :實現通過readLine讀取代碼 ,每一行加上一個行號。
14 需求2 :實現通過readLine讀取代碼 ,每一行加上一個分號。
15 需求3 :實現通過readLine讀取代碼 ,每一行加上一個引號。
16
17 //=========================================================
18 需求4 :實現通過readLine讀取代碼 ,每一行加上一個引號 + 行號。
19 需求5 :實現通過readLine讀取代碼 ,每一行加上一個分號 + 行號。
20 需求6 :實現通過readLine讀取代碼 ,每一行加上一個分號 + 引號。
21 需求7 :實現通過readLine讀取代碼 ,每一行加上一個分號 + 引號 + 行號。
22
23 如果用繼承:
24 好處:代碼結構和清晰容易理解
25 缺點:繼承體系會很龐大。實現七個需求就得創建七個子類
26
27
28 裝飾者模式 : 增強一個類的功能還可以讓裝飾者類之間互相裝飾。
29
30
31
32 */
33
34 //添加行號
35 class BufferedReaderLineNum extends BufferedReader{
36 //定義一個對象來接收傳進來的對象
37 BufferedReader bufferedReader;
38 int count = 1;
39
40 //子類繼承父類會默認調用父類的無參構造方法
41 public BufferedReaderLineNum (BufferedReader in) {
42 super(in);
43 this.bufferedReader = in;
44 }
45
46 //復寫readLine方法
47 @Override
48 public String readLine() throws IOException {
49 // TODO Auto-generated method stub
50 //調用父類的readLine
51 String content = bufferedReader.readLine();
52 //給內容田間一個行號
53 if(content == null){
54
55 return null;
56 }
57 content = count+" "+content;
58 count++;
59 return content;
60 }
61
62 }
63
64 //添加分號的
65 class BufferedReaderLineSemi extends BufferedReader{
66 //定義一個對象來接收傳進來的對象
67 BufferedReader bufferedReader;
68 //子類繼承父類會默認調用父類的無參構造方法
69 public BufferedReaderLineSemi (BufferedReader in) {
70 super(in);
71 this.bufferedReader = in;
72 }
73
74 //復寫(重寫)readLine方法
75 @Override
76 public String readLine() throws IOException {
77 // TODO Auto-generated method stub
78 //調用父類的readLine
79 String content = bufferedReader.readLine();
80 //給內容田間一個行號
81 if(content == null){//表示數據已經讀完
82
83 return null;
84 }
85
86 return content+";";
87 }
88
89 }
90
91
92
93 public class Demo1 {
94
95 /**
96 * @param args
97 * @throws IOException
98 */
99 public static void main(String[] args) throws IOException {
100 // TODO Auto-generated method stub
101 testLineNum();
102 }
103
104 public static void testLineNum () throws IOException{
105
106 //1.開啟一個通道,並且帶一個文件路徑
107 FileReader reader = new FileReader("這裡填上文件路徑如:C:\\a.java");
108 //創建緩沖流
109 BufferedReader bufferedReader = new BufferedReader(reader);
110 //2.創建一個帶分號的緩沖流
111 BufferedReaderLineSemi lineSemi = new BufferedReaderLineSemi(bufferedReader);
112 //創建一個緩沖流 ,帶行號加分號
113 BufferedReaderLineNum lineNum = new BufferedReaderLineNum(lineSemi);
114 //3.開始讀取數據
115 String content = null;
116 while((content = lineNum.readLine())!=null){
117
118 System.out.println(content);
119 }
120
121 //4.關閉資源
122 lineNum.close();
123 }
124 }
效果:
