今天来讲讲装饰器模式,对于这个模式我还是比较有印象的。因为我去年考软件设计师的设计模式大题考的就是这个装饰器模式。当时真的是一窍不通,连拼带凑的把题做完了,还好我运气好给通过了:)。
装饰模式: 动态的为一个对象添加一些额外的职责。就增加功能来说,装饰器模式比生成子类的方式更加的灵活。
1. Component: 定义一个对象的接口,同时也可以动态的为其添加职责。
2. ConcreteComponent: 定义的具体的对象,实现Component接口。
3. Decorator: 装饰器抽象类,实现Component接口,拥有Component的职责,同时也可以扩展职责。
4. ConcreteDecorator: 定义具体的装饰器实现类对象,可以向ConcreteComponent添加职责,同时也可以定义额外的职责。
女朋友最喜欢的事就是吃,干的最多的事也就是每次吃饭的时候发图片给我看,然后顺便安慰下正在苦逼撸代码的我要好好上班(我很感动,默默的拿出了我的刀。也没办法,谁让人家吃饭的时间总提早我半小时)。
既然说到吃,那这里我就用吃举例子吧。
我这里就以正餐 Dinner(即四个要素中的 Component)为例子,具体分为中餐ChineseMeal和西餐WesternStyleMeal(这两者即四个要素中的ConcreteComponent)。然后还有我们正餐所需的各种食物(即四个要素中的 ConcreteDecorator),至于四个要素中的Decorator我们可以理解为我们的菜单(Menu)。
1. 创建对象接口 Dinner
public interface Dinner {
void eat();
}
2. 创建具体的对象类 ChineseMeal、WesternStyleMeal
public class ChineseMeal implements Dinner {
@Override
public void eat() {
System.out.println("-----中餐套餐-----");
}
}
public class WesternStyleMeal implements Dinner {
@Override
public void eat() {
System.out.println("-----西餐套餐-----");
}
}
3. 创建抽象装饰器类 Menu
public abstract class Menu implements Dinner {
protected Dinner dinner;
public Menu(Dinner dinner) {
this.dinner = dinner;
}
@Override
public void eat() {
dinner.eat();
}
}
4. 创建具体的装饰器类(我这里建的有点多)Steak、Spaghetti、Salad、Rice、BoiledMeat、BoiledFish
public class Steak extends Menu {
public Steak(Dinner dinner) {
super(dinner);
}
@Override
public void eat() {
super.eat();
System.out.println("牛排");
}
}
public class Spaghetti extends Menu {
public Spaghetti(Dinner dinner) {
super(dinner);
}
@Override
public void eat() {
super.eat();
System.out.println("意大利面");
}
}
public class Salad extends Menu {
public Salad(Dinner dinner) {
super(dinner);
}
@Override
public void eat() {
super.eat();
System.out.println("沙拉");
}
}
public class Rice extends Menu {
public Rice(Dinner dinner) {
super(dinner);
}
@Override
public void eat() {
super.eat();
System.out.println("米饭");
}
}
public class BoiledMeat extends Menu {
public BoiledMeat(Dinner dinner) {
super(dinner);
}
@Override
public void eat() {
super.eat();
System.out.println("水煮牛肉");
}
}
public class BoiledFish extends Menu {
public BoiledFish(Dinner dinner) {
super(dinner);
}
@Override
public void eat() {
super.eat();
System.out.println("水煮鱼");
}
}
5. 创建装饰器测试类 DecoratorTest
public class DecoratorTest {
public static void main(String[] args) {
System.out.println("今天吃中餐");
Dinner cmd = new ChineseMeal();
Rice rice = new Rice(cmd);
BoiledMeat boiledMeat = new BoiledMeat(rice);
boiledMeat.eat();
Rice rice1 = new Rice(cmd);
BoiledFish boiledFish = new BoiledFish(rice1);
boiledFish.eat();
System.out.println("----------------\n\n今天吃西餐");
Dinner wmd = new WesternStyleMeal();
Salad salad = new Salad(wmd);
Steak steak = new Steak(salad);
steak.eat();
Salad salad1 = new Salad(wmd);
Spaghetti spaghetti = new Spaghetti(salad1);
spaghetti.eat();
}
}
程序运行结果如下:
今天吃中餐
-----中餐套餐-----
米饭
水煮牛肉
-----中餐套餐-----
米饭
水煮鱼
----------------
今天吃西餐
-----西餐套餐-----
沙拉
牛排
-----西餐套餐-----
沙拉
意大利面
1. 解耦: 装饰类和被装饰类可以独立发展不会相互耦合,每个具体的装饰对象只关心自己的功能。
2. 易扩展: 作为继承的一个替代模式,可以动态的扩展装饰类。