@(JAVA开发)
在这之前,先看一下一个原则
开闭原则
类应该对扩展开放,对修改关闭。
但也要注意允许不直接修改代码的情况下对其进行扩展。并且不用在每个地方都这么做,这是浪费时间和精力的一件事情。所以要善用这个原则。而装饰者模式就很好地遵循了这个原则。
定义
动态的将责任附加到对象上,若要扩展功能,装饰者模式提供了比继承更有弹性的替代方案。
应用
我们都知道,可以使用两种方式给一个类或者对象添加行为。
一是使用继承。继承是给一个类添加行为的比较有效的途径。通过使用继承,可以使得子类在拥有自身方法的同时,还可以拥有父类的方法。但是使用继承是静态的,在编译的时候就已经决定了子类的行为,我们不便于控制增加行为的方式和时机。
二是使用组合。组合即将一个对象嵌入到另一个对象中,由另一个对象来决定是否引用该对象来扩展自己的行为。这是一种动态的方式,我们可以在应用程序中动态的控制。
与继承相比,组合关系的优势就在于不会破坏类的封装性,且具有较好的松耦合性,可以使系统更加容易维护。但是它的缺点就在于要创建比继承更多的对象。
场景
1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2、需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。
图解
实现
这次我举了一个麻辣香锅的例子、
麻辣香锅抽象类,作为被装饰的对象
public abstract class SpicyPot {
String description ="这是一份基础麻辣香锅。";
public String getDescription() {
return description;
}
public abstract double cost();
}
继承麻辣香锅的装饰者配菜抽象类,重写了描述方法
public abstract class Garnish extends SpicyPot {
public abstract String getDescription();
}
肉类套餐
/**
* 肉类香锅套餐
* @author super
*
*/
public class MeatSpicyPot extends SpicyPot{
public MeatSpicyPot(){
description="肉很多的麻辣香锅";
}
@Override
public double cost() {
return 30;
}
}
蔬菜套餐
/**
* 蔬菜香锅套餐
* @author super
*
*/
public class FruteSpicePot extends SpicyPot{
public FruteSpicePot(){
description="蔬菜香锅,蔬菜多!";
}
@Override
public double cost() {
return 20;
}
}
装饰者之一的加肉
public class WhithMoreMeat extends Garnish{
private SpicyPot spicyPot;
public WhithMoreMeat( SpicyPot spicyPot){
this.spicyPot=spicyPot;
}
@Override
public String getDescription() {
return spicyPot.getDescription()+",加上更多的肉";
}
@Override
public double cost() {
return spicyPot.cost()+10;
}
}
另外的装饰者 加蔬菜
public class WithMoreFrute extends Garnish{
private SpicyPot spicyPot;
public WithMoreFrute( SpicyPot spicyPot){
this.spicyPot=spicyPot;
}
@Override
public String getDescription() {
return spicyPot.getDescription()+",加上更多的蔬菜";
}
@Override
public double cost() {
return spicyPot.cost()+5;
}
}
看看最后测试的结果
public class TestSpicePot {
public static void main(String[] args) {
SpicyPot spicyPot=new FruteSpicePot();
System.out.println(spicyPot.getDescription()+spicyPot.cost());
SpicyPot spicyPot2=new MeatSpicyPot();
spicyPot2=new WithMoreFrute(spicyPot2);
spicyPot2=new WhithMoreMeat(spicyPot2);
System.out.println(spicyPot2.getDescription()+spicyPot2.cost());
}
}
蔬菜香锅,蔬菜多!20.0
肉很多的麻辣香锅,加上更多的蔬菜,加上更多的肉45.0
总结
1、 组合和委托可以在运行时动态的添加新的行为,而继承是静态的,在系统编译时就已经决定了对象的行为。
2、装饰者模式意味着一群装饰者类,这些类用来包装具体组件
3、装饰者可以在被装饰者的行为前面或者后面加上自己的行为,甚至可以将被装饰者的行为整个取代掉,从而达到特定的目的。
4、可以用多个装饰者包装一个组件。
5、装饰者一般对于组件的客户是透明的,除非客户程序依赖于组件的具体类型。
6、装饰者会导致设计中出现许多的小对象,如果过度的使用,会让系统变得更加复杂。
7、装饰者和被装饰者对象有相同的超类型。
我们可以任意的组合装饰者,装饰者外面可以随便的再加上一层装饰者,也就是说你可以吃任何你想要吃的麻辣香锅组合套餐,而且新增加组合的方式,比如我增加一个可以加水果的装饰,也不会影响到现有的代码,只要在装饰的时候加上就好了。
装饰者模式在java的内置API中的io得到了广泛的使用。