JAVA实现装饰模式
环境:汽车4s店汽车销售,出售奥迪A1,A4,A6。可装饰的组件有倒车雷达,真皮座椅,GPS定位。有一辆裸车,要实现对裸车的装饰
分析:买车的人需求各不一样,有的人要奥迪A1装有雷达、GPS,有的人要奥迪A4装有真皮座椅、GPS等等。如果你把所有的可能情况都例举出来,就会出现“类爆炸”的现象,显然这是不合理的。
问题:动态的给一个对象添加一些功能扩展
解决方案:装饰模式
角色:装饰者
被装饰者
Car.java
public abstract class Car {
protected int cost;
protected String description;
public abstract String getDescription();
public abstract int getCost();
}
A1Car.java
public class A1Car extends Car{
public A1Car()
{
cost = 100000;
description = "Audi A1 Car";
}
@Override
public int getCost() {
return cost;
}
@Override
public String getDescription() {
return description;
}
}
A4Car.java
public class A4Car extends Car{
public A4Car()
{
cost = 120000;
description = "Audi A4 Car";
}
@Override
public int getCost() {
return cost;
}
@Override
public String getDescription() {
return description;
}
}
Decorator.java
public class Decorator extends Car{
protected Car c;
protected int decoratorcost;
protected String decoratordescription;
public void setCar(Car a){
c = a;
}
@Override
public int getCost() {
return decoratorcost+c.getCost();
}
@Override
public String getDescription() {
return decoratordescription+c.getDescription();
}
}
GPS.java
public class Gps extends Decorator{
public Gps(){
decoratorcost=500;
decoratordescription="with GPS";
}
}
Radar.java
public class Radar extends Decorator{
public Radar(){
decoratorcost=1500;
decoratordescription="with Radar";
}
}
Test.java
public class Test {
public static void main(String[] args) {
//给奥迪A1装配GPS
Car a1 = new A1Car();
Decorator decorator = new Gps();
decorator.setCar(a1);
System.out.println(a1.getDescription()+"的价格是"+a1.getCost());
System.out.println(decorator.getDescription()+"的价格是"+decorator.getCost());
//想再给A1装配Radar,由于装饰者与被装饰者具有相同的类型,我们可以用装饰后的对象代替原来的对象
Decorator decorator2 = new Radar();
decorator2.setCar(decorator);
System.out.println(decorator2.getDescription()+"的价格是"+decorator2.getCost());
}
}
运行结果
Audi A1 Car的价格是100000
with GPS Audi A1 Car的价格是100500
with Radar with GPS Audi A1 Car的价格是102000
在Java I/O库中输入输出流的设计模式就使用了装饰模式
项目中,我们经常这样写
FileReader fr = new FileReader("d:\\myDoc\\test.txt");
BufferedReader br = new BufferedReader(fr);//这里接收一个Reader类型参数
BufferedReader相当于装饰者,而Reader及其子类都可以作为被装饰者