jQuery之外掛
阿新 • • 發佈:2020-07-13
正文
一、定義
裝飾者模式動態地將責任(功能)附加到物件上。若要擴充套件功能,裝飾者提供了比繼承更有彈性的替代方案。
要點:
- 裝飾者和被裝飾者有相同的超型別。
- 可以用一個或多個裝飾者包裝一個物件。
- 既然裝飾者和被裝飾者有相同的超型別,所以在任何需要原始物件(被裝飾者)的場合,都可以用裝飾過的物件代替它。
- 裝飾者可以在被裝飾者的行為之前與/或之後,加上自己的行為,甚至將被裝飾者的行為整個取代掉,以到達特定的目的。
- 物件可以在任何時候被裝飾,所以可以在執行時動態地、不限量地用裝飾者裝飾物件。
- 裝飾者會導致設計中出現許多小物件,如果過度使用,會讓程式變得很複雜。
二、實現步驟
1、建立元件介面
裝飾者和被裝飾者都必須實現元件介面。
也可以用元件抽象類,然後讓裝飾者和被裝飾者繼承元件抽象類,只要裝飾者和被裝飾者具有相同的超型別即可。
/**
* 元件介面(裝飾者和被裝飾者都必須實現該介面)
*/
public interface Component {
public void doSomething();
}
2、建立具體的元件,並實現元件介面
/** * 具體元件(被裝飾者) */ public class ConcreteComponent implements Component { @Override public void doSomething() { System.out.println("ConcreteComponent do something..."); } }
3、建立裝飾者抽象類,並實現元件介面
如果只有一個裝飾者,也可以不建立裝飾者抽象類,而是由具體的裝飾者直接實現元件介面
/** * 元件裝飾者抽象類 */ public abstract class ComponentDecorator implements Component { protected Component component; public ComponentDecorator(Component component) { // 通過構造傳入元件(被裝飾者) this.component = component; } @Override public void doSomething() { // 委託給元件(被裝飾者) component.doSomething(); } }
4、建立具體的裝飾者,並繼承裝飾者抽象類
(1)裝飾者 A
/**
* 裝飾者A
*/
public class ComponentDecoratorA extends ComponentDecorator {
public ComponentDecoratorA(Component component) {
super(component);
}
@Override
public void doSomething() {
// 裝飾者新增自己的業務程式碼
component.doSomething();
// 裝飾者新增自己的業務程式碼
System.out.println("ComponentDecoratorA do something...");
}
}
(2)裝飾者 B
/**
* 裝飾者B
*/
public class ComponentDecoratorB extends ComponentDecorator {
public ComponentDecoratorB(Component component) {
super(component);
}
@Override
public void doSomething() {
// 裝飾者新增自己的業務程式碼
component.doSomething();
// 裝飾者新增自己的業務程式碼
System.out.println("ComponentDecoratorB do something...");
}
}
5、使用裝飾者裝飾元件
public class Test {
public static void main(String[] args) {
// 具體元件(被裝飾者)
Component component = new ConcreteComponent();
// 用裝飾者A裝飾元件
ComponentDecorator componentDecoratorA = new ComponentDecoratorA(component);
// 用裝飾者B裝飾元件
ComponentDecorator componentDecoratorB = new ComponentDecoratorB(component);
component.doSomething();
componentDecoratorA.doSomething();
componentDecoratorB.doSomething();
}
}
三、舉個栗子
1、背景
星巴茲是以擴張速度最快而聞名的咖啡連鎖店。因為擴張速度實在太快了,他們準備更新訂單系統,以合乎他們的飲料供應要求——
顧客在購買咖啡時,可以要求在其中加入各種調料,例如:蒸奶、豆漿、摩卡(巧克力風味)或覆蓋奶泡。星巴茲會根據所加入的調料收取不同的費用。所以訂單系統必須考慮到這些調料部分。
2、實現
把調料理解為飲料裝飾者,然後以飲料為主體,用調料來“裝飾”飲料。
(1)建立飲料抽象類
/**
* 飲料抽象類(元件)
*/
public abstract class Beverage {
public String description = "Unknown Beverage";
/**
* 描述
*/
public String getDescription() {
return description;
}
/**
* 價格
*/
public abstract double cost();
}
(2)建立具體的飲料,並繼承飲料抽象類
/**
* 濃縮咖啡
*/
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
/**
* 綜合咖啡
*/
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
@Override
public double cost() {
return 0.89;
}
}
(3)建立調料抽象類,並繼承飲料抽象類
/**
* 調料抽象類(裝飾者抽象類)
*/
public abstract class CondimentDecorator extends Beverage {
@Override
public abstract String getDescription();
}
(4)建立具體的調料,並繼承調料抽象類
/**
* 摩卡(裝飾者)
*/
public class Mocha extends CondimentDecorator {
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.20;
}
}
/**
* 豆漿(裝飾者)
*/
public class Soy extends CondimentDecorator {
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;
}
}
/**
* 奶泡(裝飾者)
*/
public class Whip extends CondimentDecorator {
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.10;
}
}
(5)測試
public class Test {
public static void main(String[] args) {
// 濃縮咖啡
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
// 綜合咖啡
Beverage beverage2 = new HouseBlend();
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
// 新增摩卡
beverage2 = new Mocha(beverage2);
// 新增豆漿
beverage2 = new Soy(beverage2);
// 新增奶泡
beverage = new Whip(beverage2);
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
}
}