薛磊 Job Seeker

23种设计模式——9.Decorator 装饰(结构型模式)


  是你还有你,一切拜托你。   是你——继承,还有你——关联,拜托你——调用父类方法

  继承是为了后续的继续装饰,如果不继承,后续的加强将不能传递他们共有的父类作为参数,而是他们的实现类,耦合度太高。

意图(Intent)

  动态地给一个对象增加一些额外的职责。就增加功能而言,装饰模式相比生成子类更加灵活。

结构(Structure)

  • Component 抽象构件

  • ConcreteComponent 具体构件

  • Decorator 装饰角色

  • ConcreteDecorator 具体装饰角色

装饰模式的几个要点

  • 通过采用组合、而非继承的手法,装饰模式实现了在运行时动态地扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了单独使用继承带来的“灵活性差”和“多姿类衍生问题”。

  • Component类在装饰模式中充当抽象接口的角色,不应该去实现具体的行为。而且Decorator类对于Component类应该透明——换言之,Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。

  • Decorator类在接口上表现为 is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但是实现上又表现为 has-a Component的组合关系,即Decorator类又使用了另外一个Component类。我们可以使用一个或者多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。

  • Decorator模式并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决”主体类在多个方向上的扩展功能“——是为“装饰”的含义。

使用场景

  • 需要扩展一个类的功能,或给一个类添加附加功能

  • 需要动态地给一个对象增加功能,这些功能可以在动态地撤销。

  • 需要为一批的兄弟类进行改装或加功能,首选装饰模式。

实例代码

抽象构件:

public abstract class Component {
	public abstract void operate();
}

具体构件:

public class ConcreteComponent extends Component {
	@Override
	public void operate() {
	System.out.println("do something!");
	}
}

抽象装饰者:

public abstract Decorator extends Component {
	private Component component = null;

	//通过构造函数传递被修饰者
	public Decorator(Cpmponent component){
		this.component = component;
	}

	//委托给被修饰者执行
	@Override
	public void operate(){
		this.component.operate();
	}
}

具体装饰类:

public class ConcreteDecorator extends Decorator {
	//传入被修饰者
	public ConcreteDecorator(Component component){
		super(component);
	}

	//被装饰方法之前调用
	public void before(){
		System.out.println("operate之前调用!");
	}

	//被装饰方法之后调用
	public void later(){
		System.out.println("operate之后调用!");
	}

	//重写父类的operate方法
	public void operate(){
		this.before();
		super.operate();
		this.later();
	}
}

场景类:

public class Clent{
	public static void main(Stirng[] args) {
		Component component = new ConcreteComponent();
		//第一次装饰
		component = new ConcreteDecorator(component);

		//可被多个装饰类装饰
		......

		//修饰后运行
		component.operator();
	}
}

Comments

Content