天天看點

結構型模式---裝飾模式(Decorator)

一:定義:

Decorator:Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

二:引入

假設現在有一家咖啡店,經營咖啡,茶等飲料,我們來為它設計一個系統。

結構型模式---裝飾模式(Decorator)

問題:

  • 飲料加糖或牛奶等調料時是要另收費的(每包1元),顧客可以要也可以不要,是以這個固定價格的cost方法不符合要求. 不符合OCP(open for extension,close for modification)

重新設計:

結構型模式---裝飾模式(Decorator)

很顯然,這種設計也不合适,會導緻

  • 類數量爆炸性增長(class exploson).
  • 也不符合要求,比如有的顧客要兩包糖等情況沒有考慮到.

引入Decorator設計模式:

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

public   abstract   class  Beverage  ... {

結構型模式---裝飾模式(Decorator)

    private String discription;

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    public String getDiscription() ...{

結構型模式---裝飾模式(Decorator)

        return discription;

結構型模式---裝飾模式(Decorator)

    }

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    public void setDiscription(String discription) ...{

結構型模式---裝飾模式(Decorator)

        this.discription = discription;

結構型模式---裝飾模式(Decorator)

    }

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    public abstract double cost() ;

結構型模式---裝飾模式(Decorator)

}

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

public   class  Coffee  extends  Beverage ... {

結構型模式---裝飾模式(Decorator)

    public Coffee()

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    ...{

結構型模式---裝飾模式(Decorator)

        setDiscription("coffee");

結構型模式---裝飾模式(Decorator)

    }

結構型模式---裝飾模式(Decorator)

    public  double cost() 

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    ...{

結構型模式---裝飾模式(Decorator)

        return 10;

結構型模式---裝飾模式(Decorator)

    }

結構型模式---裝飾模式(Decorator)

}

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

public   abstract   class  CondimentDecorator  extends  Beverage ... {

結構型模式---裝飾模式(Decorator)

    public abstract String getDiscription() ;

結構型模式---裝飾模式(Decorator)

}

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

public   class  CondimentMilk  extends  CondimentDecorator ... {

結構型模式---裝飾模式(Decorator)

    private Beverage beverage;

結構型模式---裝飾模式(Decorator)

    public CondimentMilk(Beverage beverage)

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    ...{

結構型模式---裝飾模式(Decorator)

        this.beverage=beverage;

結構型模式---裝飾模式(Decorator)

    }

結構型模式---裝飾模式(Decorator)

    public  double cost() 

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    ...{

結構型模式---裝飾模式(Decorator)

        return beverage.cost()+1;

結構型模式---裝飾模式(Decorator)

    }

結構型模式---裝飾模式(Decorator)

    public  String getDiscription() 

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    ...{

結構型模式---裝飾模式(Decorator)

        return beverage.getDiscription()+",milk";

結構型模式---裝飾模式(Decorator)

    }

結構型模式---裝飾模式(Decorator)

}

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

public   class  Client  ... {

結構型模式---裝飾模式(Decorator)

    public static void main(String args[])

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    ...{

結構型模式---裝飾模式(Decorator)

        Beverage coffee=new Coffee();

結構型模式---裝飾模式(Decorator)

        System.out.println(coffee.getDiscription()+":"+coffee.cost());

結構型模式---裝飾模式(Decorator)

        System.out.println(new CondimentMilk(coffee).getDiscription()+":"+new CondimentMilk(coffee).cost());

結構型模式---裝飾模式(Decorator)

        System.out.println(new CondimentSugar(new CondimentMilk(coffee)).getDiscription()+":"+new CondimentSugar( new CondimentMilk(coffee)).cost());

結構型模式---裝飾模式(Decorator)

        System.out.println(new CondimentSugar(new CondimentSugar(new CondimentMilk(coffee))).getDiscription()+":"+new CondimentSugar(new CondimentSugar( new CondimentMilk(coffee))).cost());

結構型模式---裝飾模式(Decorator)

    }

結構型模式---裝飾模式(Decorator)

}

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

三:結構

結構型模式---裝飾模式(Decorator)

四:實際應用

  1. JAVA I/O  系統是decorator模式的典型應用
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

我們自己來寫一個InputStream decorator,用來使所有的輸出字元變成小寫.

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

public   class  LowerCaseInputStream  extends  FilterInputStream  ... {

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    protected LowerCaseInputStream(InputStream in) ...{

結構型模式---裝飾模式(Decorator)

        super(in);

結構型模式---裝飾模式(Decorator)

    }

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    public  int read() throws IOException

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    ...{

結構型模式---裝飾模式(Decorator)

        int c=super.read();

結構型模式---裝飾模式(Decorator)

        return (c==-1?c:Character.toLowerCase(c));

結構型模式---裝飾模式(Decorator)

    }

結構型模式---裝飾模式(Decorator)

}

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

public   class  IoTest  ... {

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

    public static void main(String args[]) ...{

結構型模式---裝飾模式(Decorator)

        int c;

結構型模式---裝飾模式(Decorator)

        String filePath = "f:/temp/designPatten.txt";

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

        try ...{

結構型模式---裝飾模式(Decorator)

            InputStream in = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream(

結構型模式---裝飾模式(Decorator)

                    filePath)));

結構型模式---裝飾模式(Decorator)

            while(( c=in.read())!=-1)

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

            ...{

結構型模式---裝飾模式(Decorator)

                System.out.print((char)c);

結構型模式---裝飾模式(Decorator)

            }

結構型模式---裝飾模式(Decorator)

            in.close();

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

        } catch (FileNotFoundException e) ...{

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

            e.printStackTrace();

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

        } catch (IOException e) ...{

結構型模式---裝飾模式(Decorator)
結構型模式---裝飾模式(Decorator)

            e.printStackTrace();

結構型模式---裝飾模式(Decorator)

        }

結構型模式---裝飾模式(Decorator)

    }

結構型模式---裝飾模式(Decorator)

}

五:适用情形

Use Decorator

  • to add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects.  
  • for responsibilities that can be withdrawn.
  • when extension by subclassing is impractical. Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination. Or a class definition may be hidden or otherwise unavailable for subclassing.

參考文獻:

1:閻宏,《Java與模式》,電子工業出版社

2:Eric Freeman & Elisabeth Freeman,《Head First Design Pattern》,O'REILLY