要點: 裝飾者與被裝飾者擁有共同的超類,繼承的目的是繼承類型,而不是行爲
裝飾者包含一個超類的對象,這樣,可以在被裝飾者行爲前或者行爲後加上新的行爲,甚至取代原有的行爲裝飾者會使程序中出現很多小類,增加使用難度
使用場景:對象由主體+許多可選的部件或者功能構成,使用繼承或者接口會產生很多類,且很難擴展。例如,現在需要一個三明治,主體是麪包,添加的材料有豬肉、羊肉、芹菜、青菜、雞蛋等等。
package com.iter.devbox.decorator.sandwich;
/**
* 公共接口或抽象類
* 所有成分的父類,抽象類有一個描述自己的方法和一個得到價格的方法,
* 以及一個打印自身描述和價格的方法(該方法與另外兩個方法構成模板方法)
* @author Shearer
*
*/
public abstract class Ingredient {
public abstract String getDescription();
public abstract double getCost();
public void printDescription() {
System.out.println(" Name " + this.getDescription());
System.out.println(" Price RMB " + this.getCost());
}
}
package com.iter.devbox.decorator.sandwich;
/**
* 被裝飾對象
* 麪包類,因爲它是一個具體的成分,因此實現父類的所有的抽象方法。
* 描述可以通過構造器傳入,也可以通過set方法傳入。同樣價格也是一樣的,我就很簡單地返回了。
* @author Shearer
*
*/
public class Bread extends Ingredient {
private String description;
public Bread(String desc) {
this.description = desc;
}
public String getDescription() {
return description;
}
public double getCost() {
return 2.5;
}
}
package com.iter.devbox.decorator.sandwich;
/**
* 裝飾器對象,所有具體裝飾器對象父類。 它最經典的特徵就是:1.必須有一個它自己的父類爲自己的成員變量;2.必須繼承公共父類。
* 這是因爲裝飾器也是一種成分,只不過是那些具體具有裝飾功能的成分的公共抽象罷了。
* 在我們的例子中就是有一個Ingredient作爲其成員變量。Decorator繼承了Ingredient類。
*
* @author Shearer
*
*/
public abstract class Decorator extends Ingredient {
protected Ingredient ingredient;
public Decorator(Ingredient igd) {
this.ingredient = igd;
}
public abstract String getDescription();
public abstract double getCost();
}
package com.iter.devbox.decorator.sandwich;
/**
* 具體的豬肉成分,同時也是一個具體的裝飾器,因此它繼承了Decorator類
* @author Shearer
*
*/
public class Pork extends Decorator {
public Pork(Ingredient igd) {
super(igd);
}
public String getDescription() {
String base = this.ingredient.getDescription();
return base + "\n" + "Decrocated with Pork !";
}
public double getCost() {
double basePrice = ingredient.getCost();
double porkPrice = 2;
return basePrice + porkPrice;
}
}
package com.iter.devbox.decorator.sandwich;
/**
* 羊肉的包裝器。
* @author Shearer
*
*/
public class Mutton extends Decorator {
public Mutton(Ingredient igd) {
super(igd);
}
public String getDescription() {
String base = ingredient.getDescription();
return base + "\n" + "Decrocated with Mutton !";
}
public double getCost() {
double basePrice = ingredient.getCost();
double muttonPrice = 3.5;
return basePrice + muttonPrice;
}
}
package com.iter.devbox.decorator.sandwich;
/**
* 芹菜的包裝器
* @author Shearer
*
*/
public class Celery extends Decorator {
public Celery(Ingredient igd) {
super(igd);
}
public String getDescription() {
String base = ingredient.getDescription();
return base + "\n" + "Decrocated with Celery !";
}
public double getCost() {
double basePrice = ingredient.getCost();
double celeryPrice = 0.6;
return basePrice + celeryPrice;
}
}
package com.iter.devbox.decorator.sandwich;
/**
* 青菜的包裝器
* @author Shearer
*
*/
public class GreenGrocery extends Decorator {
public GreenGrocery(Ingredient igd) {
super(igd);
}
public String getDescription() {
String base = ingredient.getDescription();
return base + "\n" + "Decrocated with GreenGrocery !";
}
public double getCost() {
double basePrice = ingredient.getCost();
double greenGroceryPrice = 0.4;
return basePrice + greenGroceryPrice;
}
}
package com.iter.devbox.decorator.sandwich;
public class Client {
public static void main(String[] args) {
//加豬肉和青菜的三明治
Ingredient sandwich = new GreenGrocery(new Pork(new Bread("加豬肉和青菜的三明治")));
sandwich.printDescription();
}
}
運行結果:
Name 加豬肉和青菜的三明治
Decrocated with Pork !
Decrocated with GreenGrocery !
Price RMB 4.9
最典型的裝飾器類就是Java IO中的 java.io.FilterInputStream