使用场景
在不修改类源码的情况下,丰富类的各个行为
场景假设
小无和他的同事小头下班后一起回家,发现路边有个歌手在唱歌
小头:小无,你看这个歌手唱歌的的场景是不是可以抽象成代码
小无:(啥子哦,下班还在这想代码,多少带点)是的,可以抽象成代码,首先是将歌手抽象成一个Singer类
public class Singer {
String sing() {
return "唱歌";
}
}
然后创建实例,调用就行
public class Main {
public static void main(String[] args) {
Singer singer = new Singer();
System.out.println("歌手在" + singer.sing());
}
}
小头:那如果我想这个歌手在唱歌的时候同时跳舞呢
小无:那么修改sing方法,让他支持跳舞
public class Singer {
String sing(boolean isDance) {
String action = "唱歌";
if (isDance) {
action = action + "、跳舞";
}
return action;
}
}
小头:这样写违背了设计六大原则的开闭原则
开闭原则是指一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。也就是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化
小无:(你平时不都是这样写的嘛,这个时候给我说六大原则?)那我们可以继承Singer新写一个子类,重写sing方法,在唱歌时同时跳舞
public class SingerWithDance extends Singer {
@Override
String sing() {
return super.sing() + "、跳舞";
}
}
然后调用时初始化这个类的实例就行
public class Main {
public static void main(String[] args) {
Singer singer = new SingerWithDance();
System.out.println("歌手在" + singer.sing());
}
}
小头:那我如果还想在唱歌的时候同时rap呢
小无:(这人今天是不是来找茬的呀)那。。。再继承写个子类?
小头:如果我还想唱歌的同时打篮球呢,排列组合下来,这得写多少个子类呀
小无:那应该咋写呢
小头:这种情况就可以使用装饰模式了
装饰模式
小头:装饰模式主要就是被封装者和装饰器,放在代码中分四个部分
-
被封装者的抽象接口
- 主要是定义被封装的行为是哪些
-
被封装者的具体类
- 被封装的行为的基础实现
-
装饰器的基础类
- 里面定义了装饰器的基本原理,就是会持有被封装者对象,封装完的最后都会由被封装者去执行
-
装饰器的具体实现类
-
实现各种装饰逻辑
-
UML图
放在我们这个场景,以UML图表示就是这样
各部分具体代码实现
ISinger
public interface ISinger {
String sing();
}
Singer
public class Singer implements ISinger {
@Override
public String sing() {
return "唱歌";
}
}
SingerBaseDecorator
public class SingerBaseDecorator implements ISinger {
ISinger singerWapper;
public SingerBaseDecorator(ISinger singer) {
singerWapper = singer;
}
@Override
public String sing() {
return singerWapper.sing();
}
}
SingerDanceDecorator
public class SingerDanceDecorator extends SingerBaseDecorator{
public SingerDanceDecorator(ISinger singer) {
super(singer);
}
@Override
public String sing() {
return super.sing()+"、跳舞";
}
}
SingerRapDecorator
public class SingerRapDecorator extends SingerBaseDecorator{
public SingerRapDecorator(ISinger singer) {
super(singer);
}
@Override
public String sing() {
return super.sing() + "、rap";
}
}
SingerBasketballDecorator
public class SingerBasketballDecorator extends SingerBaseDecorator {
public SingerBasketballDecorator(ISinger singer) {
super(singer);
}
@Override
public String sing() {
return super.sing()+"、篮球";
}
}
运行代码
小头:现在我们就可以随意的封装我们的Singer了
public class Main {
public static void main(String[] args) {
ISinger singer = new Singer();
singer = new SingerDanceDecorator(singer);
singer = new SingerRapDecorator(singer);
singer = new SingerBasketballDecorator(singer);
System.out.println("歌手在" + singer.sing());
}
}
小结
装饰模式跟我们平时穿衣服很像,在身体上,穿上各种衣物,身体是被封装者,而各种衣物就是装饰器。身体是必要的,衣服是非必要。