裝飾:基於已有的功能,並提供加強功能,裝飾類通常會通過構造方法接收被裝飾的對象。並基於被裝飾的對象的功能,提供更強的功能。相對於繼承來說裝飾模式可以在不使用創造更多子類的情況下,將對象的功能加以擴展。英文叫: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 }
效果: