看到字眼,你应该心里有个数了,所谓装饰,就是在原有的基础上加些东西化化装,有修睫毛的,有化口红的,有时尚的衣服等等,然后呢就 变漂亮了;比如礼品,都要加个礼品
盒,然后档次提高了,可以开个好价 ,这也是“装饰”。
装饰者模式有个 需要遵循的原则:开闭原则,即对修改关闭,对扩展开放。
什么情况下需要用到装饰装者模式? 我的理解就是:当我已经提供了一些method,而你要使用我的method,那么你只能在不损坏我的method 的前提下,在我的method的基础
上 进行扩展,也就是覆盖处理。
使用装饰者模式有什么好处? 就是不损坏需要装饰的类,也即保护需要装饰的类。
实例代码:
beverage.java
public abstract class Beverage{ String description="Unknown Beverage"; String size="medium"; public String getDescription(){ return description; } public abstract double cost(); public String getSize(){ return size; } public void setSize(String size_){ this.size=size_; } }
CondimentDecorator.java
public abstract class CondimentDecorator extends Beverage{ public abstract String getDescription(); }
Espresso.java
public class Espresso extends Beverage{ public Espresso(){ description="Espresso"; } public double cost(){ return 1.99; } }
HouseBlend.java
public class HouseBlend extends Beverage{ public HouseBlend(){ description="HouseBlend"; } public double cost(){ return 0.89; } }
DarkRoast.java
public class DarkRoast extends Beverage{ public DarkRoast(){ description="DarkRoast"; } public double cost(){ return 0.99; } }
Mocha.java
public class Mocha extends CondimentDecorator{ Beverage beverage; public Mocha(Beverage beverage){ this.beverage=beverage; } public String getDescription(){ return beverage.getDescription()+",Mocha"; } public double cost(){ return 0.2+beverage.cost(); } }
Soy.java
public class Soy extends CondimentDecorator{ Beverage beverage; public Soy(Beverage beverage){ this.beverage=beverage; } public String getDescription(){ return beverage.getDescription()+",Soy"; } public double cost(){ return 0.15+beverage.cost(); } }
Whip.java
public class Whip extends CondimentDecorator{ Beverage beverage; public Whip(Beverage beverage){ this.beverage=beverage; } public String getDescription(){ return beverage.getDescription()+",Whip"; } public double cost(){ return 0.10+beverage.cost(); } }
BeverageSize.java
public class BeverageSize extends CondimentDecorator{ public double size=0; public Beverage beverage; public BeverageSize(Beverage beverage){ this.beverage=beverage; } public String getDescription(){ return beverage.getDescription()+","+beverage.getSize(); } public double cost(){ switch(beverage.getSize()){ case "small": return 0.10+beverage.cost(); case "medium": return 0.15+beverage.cost(); case "big": return 0.20+beverage.cost(); default: return 0.15+beverage.cost(); } } }
StarBuzzCoffee.java
public class StarBuzzCoffee{ public static void main(String args[]){ Beverage beverage = new Espresso(); System.out.println(beverage.getDescription()+'$'+beverage.cost()); Beverage beverage2 = new DarkRoast(); beverage2 = new Mocha(beverage2); beverage2 = new Mocha(beverage2); beverage2 = new Whip(beverage2); beverage2.setSize("big"); beverage2 = new BeverageSize(beverage2); System.out.println(beverage2.getDescription()+'$'+beverage2.cost()); Beverage beverage3 = new HouseBlend(); beverage3 = new Mocha(beverage3); beverage3 = new Mocha(beverage3); beverage3 = new Whip(beverage3); beverage3 = new BeverageSize(beverage3); System.out.println(beverage3.getDescription()+'$'+beverage3.cost()); } }
对应StarBuzzCoffee.java文件,里面的装饰类采用了很多new的方法,优化的方法就是使用工厂方法,所谓工厂也就是生产具体实例的地方;工厂方法有区别于抽象工厂。
有关抽象的概念,比如说抽象类和接口,抽象类里面的方法可以有具体的实现,但是抽象类里面可以有自己的具体实现的方法;而接口只能在其继承类的里面实现方法细节(必须实现)。两者共同的地方就是 继承的类有公共的 方法,既然有共同的方法,就提取出来,做成接口(抽象类)。
下面举例说明下 针对接口编程,不针对实现编程 的原则 :
animals.java
interface animals { public void bark(); }
cat.java
class cat implements animals { public void bark() { System.out.println("miao miao"); } }
dog.java
class dog implements animals { public void bark() { System.out.println("wang wang"); } }
test.java
public class test{ public static void main(String args[]) { animals a = new dog(); a.bark(); } }
dog,cat都有一个bark的方法,把这个方法提取出来作为一个接口声明。比如说电脑的打印机,电脑提供了USB接口,不论任何打印机只要实现了这个接口,就可以进行打印了,具体怎么实现的,那是打印机厂家的事情了。
如果现在需要cat的bark方法,那么只需要把animals a = new dog();改成 animals a = new cat();即可。如果是针对实现编程 ,那么就是 dog a = new dog(); cat a = new cat();