decorator与concreteComponent通过继承重写相同方法,同时decorator通过组合依赖concreteComponent,在不修改concreteComponent的方法的情况下进行拓展。
案例(主体咖啡,装饰者各种调料,最后组合得到的统称为饮品)
/**
* 角色(Component)
*/
public abstract class Drink {
protected int price;
protected String description;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public abstract int cost();
public abstract String bill();
}
/**
* 可以在ConcreteComponent与component中间将共同方法再抽象一层
*/
public abstract class Coffee extends Drink{
@Override
public int cost() {
// System.out.println(getDescription() + " : " + getPrice());
return this.getPrice();
}
@Override
public String bill() {
return this.getDescription() + "(" + this.cost() + ")";
}
}
/**
* 角色(ConcreteComponent)
*/
public class LongCoffee extends Coffee{
public LongCoffee(){
setPrice(1);
setDescription("美式咖啡");
}
}
/**
* 角色(ConcreteComponent)
*/
public class ShotCoffee extends Coffee{
public ShotCoffee(){
setPrice(3);
setDescription("浓缩咖啡");
}
}
/**
* 角色(Decorator)
*/
public abstract class Condiment extends Drink{
protected Drink drink;
public Condiment(Drink drink){
this.drink = drink;
}
@Override
public int cost() {
return drink.cost() + this.getPrice();
}
@Override
public String bill(){
return drink.bill() + " && " + this.getDescription() + "(" + this.price + ")";
}
public void complete(){
System.out.println("总价 : " + this.cost());
System.out.println("发票 : " + this.bill());
}
}
/**
* 角色(ConcreteDecorator)
*/
public class Chocolate extends Condiment{
public Chocolate(Drink drink) {
super(drink);
setPrice(5);
setDescription("巧克力");
}
}
/**
* 角色(ConcreteDecorator)
*/
public class Milk extends Condiment{
public Milk(Drink drink) {
super(drink);
setPrice(6);
setDescription("牛奶");
}
}
测试类
public class Test {
public static void main(String[] args) {
LongCoffee longCoffee = new LongCoffee();
Milk milk = new Milk(longCoffee);
milk.complete();
Chocolate chocolate = new Chocolate(milk);
chocolate.complete();
}
}
结果
inputStream中源码应用
可以看出FilterInputStream是decorator角色,一般BufferInputStream也是通过装饰FileInputStream来使用
FileInputStream fileInputStream = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\decoratorPattern"));
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
BufferedInputStream的read()默认调用FileInputStream的read(byte b[], int off, int len),这也是为什么都是使用read(),而BufferedInputStream比FileInputStream效率高的原因,单纯因为是FileInputStream的两个不同方法,默认做没做缓冲的区别
public int read(byte b[], int off, int len) throws IOException {
return in.read(b, off, len);
}
HttpServletRequestWrapper类是HttpServletRequest类的装饰类,解决乱码问题就在这里解决