1. 程式人生 > 實用技巧 >jQuery之外掛

jQuery之外掛

正文

一、定義

裝飾者模式動態地將責任(功能)附加到物件上。若要擴充套件功能,裝飾者提供了比繼承更有彈性的替代方案。

要點:

  • 裝飾者和被裝飾者有相同的超型別。
  • 可以用一個或多個裝飾者包裝一個物件。
  • 既然裝飾者和被裝飾者有相同的超型別,所以在任何需要原始物件(被裝飾者)的場合,都可以用裝飾過的物件代替它。
  • 裝飾者可以在被裝飾者的行為之前與/或之後,加上自己的行為,甚至將被裝飾者的行為整個取代掉,以到達特定的目的。
  • 物件可以在任何時候被裝飾,所以可以在執行時動態地、不限量地用裝飾者裝飾物件。
  • 裝飾者會導致設計中出現許多小物件,如果過度使用,會讓程式變得很複雜。

二、實現步驟

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());
    }
}