1.装饰
1.1定义
装饰者模式:动态地给一个对象增加一些额外的职责。就扩展功能而言,装饰者模式提供了一种比使用子类更加灵活的替代方案。
对象结构型模式
装饰者模式的定义说明:
-
以对客户透明的方式动态地给一个对象附加上更多的责任
-
可以在不需要创建更多子类的情况下,让对象的功能得以扩展
1.2角色
装饰者模式包含以下4个角色:
- Component(抽象构件)
- ConcreteComponent(具体构件)
- Decorator(抽象装饰者类)
- ConcreteDecorator(具体装饰者类)
1.3优点
- 对于扩展一个对象的功能,装饰者模式比继承更加灵活,不会导致类的个数急剧增加
- 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰者类,从而实现不同的行为
- 可以对一个对象进行多次装饰者
- 具体构件类与具体装饰者类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰者类,且原有类库代码无须改变,符合开闭原则
1.4缺点
- 使用装饰者模式进行系统设计时将产生很多小对象,大量小对象的产生势必会占用更多的系统资源,在一定程度上影响程序的性能
- 比继承更加易于出错,排错也更困难,对于多次装饰者的对象,调试时寻找错误可能需要逐级排查,较为烦琐
1.5适用环境
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
- 当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰者模式
1.6教学例子
(1)分析
-
可以在不改变一个图片本身功能的基础上给图片动态增加额外的职责(加边框)
-
引入了装饰者(装饰器):加蓝框、加灰框……,同时在加了边框的图片中还可以再加边框(组合的装饰者),以不断扩展原有图片的功能
-
不应也不能穷举所有装饰者(装饰器),因为装饰者组合的情况是几乎无限的
-
只能设定基本装饰者(装饰器):加蓝框|加灰框|加紫框,由用户动态组合
(2)类图
(3)代码
Component(抽象构件)
public abstract class Paint {
public abstract void showPaint();
}
ConcreteComponent(具体构件)
public class DogPhoto extends Paint {
@Override
public void showPaint() {
System.out.println("这是一张小狗的照片。");
}
}
Decorator(抽象装饰者类)
public abstract class PhotoFrame extends Paint{
private Paint paint;
public void setPaint(Paint paint) {
this.paint = paint;
}
public void showPaint(){
if(paint != null){
paint.showPaint();
}
addFrame();
}
public abstract void addFrame();
}
ConcreteDecorator(具体装饰者类)
public class BlueFrame extends PhotoFrame{
@Override
public void addFrame() {
System.out.println("增加一个蓝色的相框。");
}
}
public class RedFrame extends PhotoFrame {
@Override
public void addFrame() {
System.out.println("增加一个红色的相框。");
}
}
Client(客户端)
public class Client {
public static void main(String[] args) {
System.out.println("----照片内容展示------");
Paint dogPhoto = new DogPhoto();
dogPhoto.showPaint();
System.out.println("----红色边框展示------");
PhotoFrame redFrame = new RedFrame();
redFrame.showPaint();
System.out.println("----照片和红色边框组合之后展示------");
redFrame.setPaint(dogPhoto);
redFrame.showPaint();
System.out.println("----蓝色边框展示------");
PhotoFrame blueFrame = new BlueFrame();
blueFrame.showPaint();
System.out.println("----蓝色边框装饰用红色边框装饰之后的装配------");
blueFrame.setPaint(redFrame);
blueFrame.showPaint();
}
}
1.7实操案例
(1)问题:
某手机美图APP软件支持多种不同的的图像格式,例如JPG,PNG,BMP等常用的图像格式,同时提供了多种不同的滤镜对图像进行处理,例如木刻滤镜(Cutout)、模糊滤镜(Blur),锐化滤镜(Sharpen),纹理滤镜(Texture)等,用户可以随意的选择其中的滤镜,甚至可以使用多个滤镜来处理图像。请选择一种合适的设计模式来设计该APP,同时还能够很方便地增加新的图像格式和滤镜,画出类图并模拟实现。
(2)类图:
(3)代码:
Component(抽象构件)
public abstract class FormatComponent {
public abstract void show();
}
ConcreteComponent(具体构件)
public class BMP extends FormatComponent {
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println("这是一张BMP格式的图片");
}
}
public class JPG extends FormatComponent {
/**
* @author Zhao-Benshan
* 实体格式
*/
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println("这是一张JPG格式的图片");
}
}
public class PNG extends FormatComponent {
/**
* @author Zhao-Benshan
* 实体格式
*/
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println("这是一张格式PNG的图片");
}
}
Decorator(抽象装饰者类)
public abstract class FilterDecorator extends FormatComponent {
private FormatComponent format;
public void setFormat(FormatComponent format) {
this.format = format;
}
@Override
public void show() {
// TODO Auto-generated method stub
this.format.show();
addFilter();
}
public abstract void addFilter();
}
ConcreteDecorator(具体装饰者类)
public class Blur extends FilterDecorator {
@Override
public void addFilter() {
// TODO Auto-generated method stub
System.out.println("加了一个模糊滤镜");
}
}
public class Cutout extends FilterDecorator {
@Override
public void addFilter() {
// TODO Auto-generated method stub
System.out.println("加了一个木刻滤镜");
}
}
public class Sharpen extends FilterDecorator {
@Override
public void addFilter() {
// TODO Auto-generated method stub
System.out.println("加了一个锐化滤镜");
}
}
public class Texture extends FilterDecorator {
@Override
public void addFilter() {
// TODO Auto-generated method stub
System.out.println("加了一个纹理滤镜");
}
}
Client(客户端)
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
FormatComponent format = new PNG();
FilterDecorator filter1 = new Blur();
filter1.setFormat(format);
filter1.show();
FilterDecorator filter2 = new Sharpen();
filter2.setFormat(filter1);
filter2.show();
}
}