Java常用设计模式————装饰者模式

引言

装饰者模式,又叫装饰器模式。它可以动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更灵活,同时装饰者模式也体现了OCP原则

在客户端调用使用了装饰者模式的对象时,就好像在使用构造器层层包裹核心对象,层层装饰核心对象,因此叫做装饰者模式。

一、装饰者模式类图

装饰者模式属于结构型设计模式。在JDK的IO流API中,就利用了装饰者模式:

Java常用设计模式————装饰者模式_第1张图片

以简单的形状和颜色为例。如何为不同的形状装饰新的颜色呢?

Java常用设计模式————装饰者模式_第2张图片

上图中,Shape和ShapeDecorator都是抽象类,一般情况下,装饰者模式中的顶层装饰器类(ShapeDecorator)一定要是抽象类,因为它需要维护被装饰者,并重写特定行为。客户端在调用的时候,并不会直接使用它,而是会使用具体的装饰器类(Red、White)。

Shape类在本例中是一个抽象类,实际上也可以是一个接口,主要看有没有需要维护的属性。接口中是不允许有属性的,所以如果需要维护一些公共属性,那么可以采用抽象类,而如果只是封装了行为,那么建议采用接口。

装饰者模式的精髓在于,装饰者模式将继承和组合两种技巧相结合。

继承的目的是为了可以在原来的位置上取代被装饰对象(前提是调用方使用的是父类引用)。

组合(采用构造器传入一个被装饰对象,并在内部维护这个对象属性)的目的是可以在核心对象的基础之上加以装饰,即保留原来的核心对象的特征和行为,只做扩展,不做修改(OCP原则)。 

装饰器子类在重写被装饰者的特定行为时,一定要注意,根据业务是否需要严格遵守对原来对象行为的扩展,而不是修改。如果是只扩展不修改,那么一定要在抽象装饰器类中调用被装饰对象的方法,并在装饰器子类的方法中使用“super.”的形式间接调用被装饰者的方法,然后根据装饰需要,在调用的前后执行装饰逻辑。如果业务设计上允许对原有行为作出一些修改,那么其实并没有严格遵守OCP原则,这种情况下,抽象装饰器类的对原对象方法的调用可以视情况而定修改甚至忽略。后者违背OCP原则的方式不建议使用装饰者模式来完成。

二、装饰者模式代码实现

/**
 * 图形接口
 */
public abstract class Shape {
	
	protected String name;
	
	public abstract void draw();
	
	public String getName() {
		return name;
	}
}
public class Circle extends Shape {
	
	public Circle() {
		name = "圆形";
	}
	
	@Override
	public void draw() {
		System.out.println(name);
	}
}
public class Square extends Shape {
	
	public Square() {
		name = "正方形";
	}

	@Override
	public void draw() {
		System.out.println(name);
	}
}
/**
 * 装饰器抽象类
 */
public abstract class ShapeDecorator extends Shape {

	protected Shape decoratedShape;
	
	public ShapeDecorator(Shape shape) {
		this.decoratedShape = shape;
	}
	
	@Override
	public void draw() {
		decoratedShape.draw();
	}
}
public class Red extends ShapeDecorator {
	
	public Red(Shape shape) {
		super(shape);
	}

	@Override
	public void draw() {
		paint();
	}
	
	// 随意增加想要装饰在核心对象上的功能
	private void paint() {
		System.out.println("红色的" + decoratedShape.getName());
		
	}
}
public class White extends ShapeDecorator {
	
	public White(Shape shape) {
		super(shape);
	}

	@Override
	public void draw() {
		paint();
	}
	
	private void paint() {
		System.out.println("白色的" + decoratedShape.getName());
	}
}

测试代码:

public class Client {

	public static void main(String[] args) {
		Shape redCircle = new Red(new Circle());
		redCircle.draw();
		
		Shape whiteCircle = new White(new Circle());
		whiteCircle.draw();
		
		Shape redSquare = new Red(new Square());
		redSquare.draw();
		
		Shape whiteSquare = new White(new Square());
		whiteSquare.draw();
	}
}

测试结果:

红色的圆形
白色的圆形
红色的正方形
白色的正方形

总结

装饰者模式主要用于对现有对象添加新的功能,可在一定程度上代替继承关系,实现低耦合关系。与桥接模式类似,都是为了防止类的膨胀而引出的结构型设计模式。而且在思路上,与桥接模式呈现相反的类的依赖关系。

装饰者模式基于OCP原则,不改变原来对象的属性及行为,只做扩展。

它的类结构特点有两个:继承和组合

其中:

继承的目的是为了可以在原来的位置上替代被装饰对象(前提是调用方使用的是父类引用)。

组合(采用构造器传入一个被装饰对象,并在内部维护这个对象属性)的目的是可以在核心对象的基础之上加以装饰,即保留原来的核心对象的特征和行为,只做扩展,不做修改(OCP原则)。

除了更好的实现对象功能的扩展和特性组合,但是如果扩展功能较多,被迫多层装饰,就会使代码变得较为复杂。

 

你可能感兴趣的:(设计模式)