Decorator设计模式
- 装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。
- 从语义上来说和代理模式很像
应用场景
- 需要扩展一个类的功能
- 动态的为一个对象增加功能,而且还能动态撤销。不使用继承(继承不能做到这一点,继承的功能是静态的,不能动态增删。)
例子
涉及一下角色:咖啡,糖咖啡,加糖加牛奶咖啡
- Coffee:被装饰者
- Decorate:抽象装饰类
- Milk:具体的装饰类(加了牛奶)
- Sugar:具体的装饰类(加了糖)
- 类图
public class Coffee implements Drinkable {
private int price = 20;
private String name = "纯咖啡";
/**
* 纯咖啡的价格
*/
@Override
public int cost() {
return price;
}
@Override
public String info() {
return name;
}
public static void main(String[] args) {
Drinkable coffee = new Coffee();
Milk miltCoffee = new Milk(coffee);
Sugar sugarCoffee = new Sugar(miltCoffee);
System.out.println(sugarCoffee.info()+"--价格是:"+sugarCoffee.cost());
//纯咖啡加牛奶加糖--价格是:25
/*
* new Sugar( new Milk( new Coffee() ) ).info();
*/
}
}
abstract class Decorate implements Drinkable {
private Drinkable drink;
public Decorate(Drinkable drink) {
this.drink = drink;
}
@Override
public int cost() {
return drink.cost();
}
@Override
public String info() {
return drink.info();
}
}
class Milk extends Decorate {
public Milk(Drinkable drink) {
super(drink);
}
@Override
public int cost() {
return super.cost()+2;
}
@Override
public String info() {
return super.info()+"加牛奶";
}
}
class Sugar extends Decorate {
public Sugar(Drinkable drink) {
super(drink);
}
@Override
public int cost() {
return super.cost()+3;
}
@Override
public String info() {
return super.info()+"加糖";
}
}
interface Drinkable {
int cost();
String info();
}
jdk中IO也用到了装饰器模式
如下在F盘的文件中写进去一段话。只用FileOutputStream ,也可以实现。为什么要用其它两个呢?能起到什么作用呢?
起装饰作用(增加了新功能):
- FileOutputStream 是字节流,它一个字节一个字节的向外边送数据
- OutputStreamWrite (是转换流,指的是将字节流转化为字符流)即是字符流,它一个字符一个字符的向外边送数据
- BufferedWriter是一个缓冲区,缓存起来最后一下写入,减少IO操作。
public class Main {
public static void main(String[] args) throws Exception {
File f = new File("F:/test.txt");
FileOutputStream fos = new FileOutputStream(f);
OutputStreamWriter osw = new OutputStreamWriter(fos);
BufferedWriter bw = new BufferedWriter(osw);
bw.write("hello world !");
bw.flush();
bw.close();
}
}
学习设计模式需要注意的点
- 把握住好的设计的指导思想:代码的可扩展性。因为需求总是在变化的。
- 学习设计模式不能死扣概念,很多设计模式都是相通的,语法类似,只是在语义上由一些区别。实际使用时没有必要非得说用的是哪种设计模式,能用着方便,合适就行。