JAVA设计模式——装饰者模式
一.主要概念
1.定义
以对客户端透明的方式动态扩展对象的功能,是继承关系的一个替代(继承会产生大量的子类,而且代码有冗余)
2.装饰者模式涉及的角色
抽象构件角色(Component):通常是一个抽象类或者一个接口,可以给这些对象动态的添加职责
具体构件角色(Concrete Component):是Component的子类,实现了对应的方法,它就是那个被装饰的类。
装饰角色(Decorator):是Component的子类,它是具体装饰角色共同实现的抽象类(也可以是接口),并且持有一个Component类型的对象引用,它的主要作用就是把客户端的调用委派到被装饰类。
具体装饰角色(Concrete Decorator):定义具体的装饰类,给Component添加职责
3.装饰者模式的UML图
二.具体实现
抽象构件角色(Component)
/**
* 抽象构件角色(Component):定义对象动态的添加职责
* 定义手抓饼的行为
*/
public interface Cake {
String nameDetails();
double price();
}
具体构件角色(Concrete Component)
/**
* 具体构件角色(Concrete Component):就是那个被装饰的类。
* 具体手抓饼(原味)
*/
public class CakeImpl implements Cake {
@Override
public String nameDetails() {
return "原味手抓饼";
}
@Override
public double price() {
return 5;
}
}
装饰角色(Decorator)
/**
*装饰角色(Decorator):持有一个Component类型的对象引用,它的主要作用就是把客户端的调用委派到被装饰类。
* 手抓饼装饰类
*/
public class CakeDecorator implements Cake {
Cake cake;
// 构造方法是重点,通过构造方法实现装饰
public CakeDecorator(Cake cake){
this.cake = cake;
}
@Override
public String nameDetails() {
return cake.nameDetails();
}
@Override
public double price() {
return cake.price();
}
}
具体装饰角色(Concrete Decorator)
/**
* 具体装饰角色(Concrete Decorator)
* 奶油手抓饼
*/
public class CreamCakeDecorator extends CakeDecorator {
public CreamCakeDecorator(Cake cake) {
super(cake);
}
@Override
public String nameDetails() {
return "奶油" + super.nameDetails();
}
@Override
public double price() {
return super.price() + 3.0;
}
}
test类
/**
* test类
* 采用装饰的方法相对于继承方法:减少了类定义的个数,通过装饰来组合原料,而不需要继承来实现不同的组合关系
* eg:1,2,3的组合关系有4种(1,2)(1,3)(2,3)(1,2,3)
* 继承方式需要再增加四个类来实现,而装饰是让客户端自由组合,而且还可以控制组合的顺序!
*/
public class Main {
public static void main(String[] args) {
System.out.println("小明要:");
Cake plainCake = new CakeImpl(); // 需要被装饰的对象
System.out.println(plainCake.nameDetails() + " $ " + plainCake.price());
System.out.println("小花要:");
// 通过构造方法装饰对象
Cake eggCake= new EggCakeDecorator(plainCake);
System.out.println(eggCake.nameDetails() + " $ " + eggCake.price());
System.out.println("张三需要所有配料:");
//让客户端自由组合,而且还可以控制组合的顺序!
Cake beefEggCake = new BeefCakeDecorator(eggCake);
Cake creamBuffEggCake = new CreamCakeDecorator(beefEggCake);
System.out.println(creamBuffEggCake.nameDetails() + " $ " + creamBuffEggCake.price());
}
}
三.总结
1.适配器模式与装饰模式的区别
适配器模式是为了包装接口的兼容性
装饰模式包装是为了动态的添加方法行为
2.优点
1.装饰模式代替继承模式更具灵活性
2.通过动态的方式来扩展对象功能,在客户端选择不同的装饰器,实现不同的行为
3.jdk使用情况
java.io.BufferedInputStream(InputStream)
java.io.DataInputStream(InputStream)
java.io.BufferedOutputStream(OutputStream)