Java設計模式之裝飾者模式
阿新 • • 發佈:2019-01-02
一、概念
裝飾者模式:動態的將責任附加到物件上,若要擴充套件功能,裝飾者提供了比繼承更有彈性的替代方案。
關係圖:
說明:
- 裝飾者和被裝飾者物件有相同的超類
- 你可以擁有一個和多個裝飾者包裝一個物件
- 由於第一點,在任何需要原始物件的場合都可以使用裝飾過後的的物件代替它
- 裝飾者可以在所委託被裝飾者的行為之前或之後加上自己的行為,以達到特定的目的
- 物件可以在任何時候被裝飾,可以在執行時動態的、不限量的用你喜歡的裝飾者來裝飾物件
實現程式碼: Beverage類
CondimentDecorator類package com.hanxin.decorator; /** * 抽象基類,相當於Component * Created by hanxin on 2017/11/12. */ public abstract class Beverage { String description = "Unknown Berverage"; public String getDescription(){ return description; } //抽象方法,必須在子類中實現 public abstract double cost(); }
package com.hanxin.decorator;
/**
* 調味料父類,擴充套件自Beverage
* Created by hanxin on 2017/11/12.
*/
public abstract class CondimentDecorator extends Beverage {
//調味料要重新實現該方法
public abstract String getDescription();
}
DarkRoast類
Decaf類package com.hanxin.decorator; /** * Created by hanxin on 2017/11/12. */ public class DarkRoast extends Beverage { public DarkRoast(){ this.description = "DarkRoast"; } @Override public double cost() { return 1.05; } }
package com.hanxin.decorator;
/**
* Created by hanxin on 2017/11/12.
*/
public class Decaf extends Beverage {
public Decaf(){
this.description = "Decaf";
}
@Override
public double cost() {
return 0.99;
}
}
Espresso類
HourseBlend類package com.hanxin.decorator; /** * Created by hanxin on 2017/11/12. */ public class Espresso extends Beverage { public Espresso(){ this.description = "Espresso"; } @Override public double cost() { return 1.99; } }
package com.hanxin.decorator;
/**
* Created by hanxin on 2017/11/12.
*/
public class HouseBlend extends Beverage {
public HouseBlend(){
this.description = "HouseBlend";
}
@Override
public double cost() {
return 0.89;
}
}
Mocha類
package com.hanxin.decorator;
/**
* Created by hanxin on 2017/11/12.
*/
public class Mocha extends CondimentDecorator {
//用一個引用記錄飲料(就是被裝飾者)
private Beverage beverage;
//初始化,並將被裝飾者引用傳進來
public Mocha(Beverage beverage){
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+",Mocha";
}
/*
計算價格,呼叫被裝飾者方法計算後,再加上調料價格
*/
@Override
public double cost() {
return beverage.cost()+0.2;
}
}
Milk類
package com.hanxin.decorator;
/**
* Created by hanxin on 2017/11/12.
*/
public class Milk extends CondimentDecorator {
private Beverage beverage;
public Milk(Beverage beverage){
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+",Milk";
}
@Override
public double cost() {
return beverage.cost()+0.1;
}
}
Soy類
package com.hanxin.decorator;
/**
* Created by hanxin on 2017/11/12.
*/
public class Soy extends CondimentDecorator {
private Beverage beverage;
public Soy(Beverage beverage){
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+",Soy";
}
@Override
public double cost() {
return beverage.cost()+0.15;
}
}
Whip類
package com.hanxin.decorator;
/**
* Created by hanxin on 2017/11/12.
*/
public class Whip extends CondimentDecorator {
private Beverage beverage;
public Whip(Beverage beverage){
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+",Whip";
}
@Override
public double cost() {
return beverage.cost()+0.1;
}
}
測試類
package com.hanxin.decorator;
/**
* Created by hanxin on 2017/11/12.
*/
public class Test {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription()+" $"+beverage.cost());
Beverage beverage1 = new DarkRoast();
beverage1 = new Mocha(beverage1);
beverage1 = new Mocha(beverage1);
beverage1 = new Whip(beverage1);
System.out.println(beverage1.getDescription()+" $"+beverage1.cost());
Beverage beverage2 = new HouseBlend();
beverage2 = new Soy(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription()+" $"+beverage2.cost());
}
}
2.自定義IO類 實現程式碼: LowerCaeInputStream類
package com.hanxin.decorator.javaAPI;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Java IO 包中的流採用的是裝飾者模式,以下是自定義大小寫轉換流
* Created by hanxin on 2017/11/12.
*/
public class LowerCaseInputStream extends FilterInputStream {
public LowerCaseInputStream(InputStream in){
super(in);
}
@Override
public int read() throws IOException {
int c = super.read();
return (c==-1? c:Character.toLowerCase(c));
}
@Override
public int read(byte[] b,int offset,int len) throws IOException {
int result = super.read(b,offset,len);
for(int i=offset;i<offset+len;i++){
b[i] = (byte)Character.toLowerCase((char)b[i]);
}
return result;
}
}
測試類
package com.hanxin.decorator.javaAPI;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
/**
* Created by hanxin on 2017/11/12.
*/
public class Test {
public static void main(String[] args) {
int c;
try{
InputStream in = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("D:/test.txt")));
while((c=in.read())>0){
System.out.println((char)c);
}
in.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
三、裝飾者模式優缺點 優點:
- 裝飾者模式可以提供比繼承跟多的靈活性
- 可以通過一種動態的方式來擴充套件一個物件的功能,在執行時選擇不同的裝飾器,實現不同的功能
- 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創造出不同的行為組合,可裝用多個裝飾器類來裝飾物件,得到功能強大的物件
- 具體構建類與具體裝飾類可以獨立化,使用者可以根據需要增加新的具體構件類和具體裝飾類,在使用時在對其進行組合,原有程式碼無需改變(開閉原則)
- 會產生很多的小物件,增加了系統的複雜性
- 比繼承更加易於出錯,排錯也很困難