java设计模式之装饰者模式

设计原则:对扩展开放,对修改关闭

装饰者模式:动态的给对象添加一些额外的属性或行为,来扩展功能。提供了比继承更有弹性的代替方案。

类图与角色:

    抽象构件角色(Component):通常是一个抽象类或者一个接口,定义了一系列方法,方法的实现可以由子类实现或者自己实现。通常不会直接使用该类,而是通过继承该类或者实现该接口来实现特定的功能。(例如,对于动物类,有一个抽象方法输出所有的功能,基本功能包括:呼吸,觅食,睡觉等等)。这是此类角色都会有的功能的集合,可以在不同的动物类中进行重用。 具体构件角色(Concrete Component):是Component的子类,实现了对应的方法,它就是那个被装饰的类。(具体构建角色可以建立很多个,例如狗,猫,鸟等等,如果是狗,我们可以装饰一些吼叫的功能,吃肉的功能;鸟可以装饰一些飞行的功能,带有翅膀的功能等等。当然这些需要在具体装饰角色中去具体定义)。 装饰角色(Decorator):是Component的子类,它是具体装饰角色共同实现的抽象类(也可以是接口),并且持有一个Component类型的对象引用,它的主要作用就是把客户端的调用委派到被装饰类。 具体装饰角色(Concrete Decorator):它是具体的装饰类,是Decorator的子类,当然也是Component的子类。它主要就是定义具体的装饰功能,例如上面说的,对于鸟这个具体构建角色而言,除了具备抽象构件角色基本的功能,它还具有一些飞行的功能,带翅膀的功能。那么我们可以把这两个功能定义成一个具体装饰角色1,对于狗这个具体构件角色而言,我们可以把吼叫,吃肉这两个功能定义成一个具体装饰角色2,这样,如果我们再定义一个狼这样的具体构件角色的时候,就可以直接用具体装饰角色2来进行装饰。

以上面所说的动物的例子来写代码演示。

抽象构件角色(对应动物类)

public interface Component {
          
   
	void function();
}

具体构件角色(对应狗)

public class ConcreteComponent implements Component {
          
   
 
	@Override
	public void function() {
          
   
		System.out.println("基本功能:呼吸+觅食+睡觉");
	}
	
}
装饰角色

public class Decorator implements Component {
          
   
 
	private Component component; //持有一个Component类型的对象引用
	
	public Decorator(Component component) {
          
   
		this.component = component;
	}
 
	@Override
	public void function() {
          
   
		component.function(); //客户端的调用委派给具体的子类
	}
	
}

具体装饰角色(对应吼叫和吃肉这两个功能)

public class ConcreteDecorator extends Decorator {
          
   
 
	public ConcreteDecorator(Component component) {
          
   
		super(component);
	}
 
	@Override
	public void function() {
          
   
		super.function();
		System.out.println("附加功能:");
		this.eat();
		this.bellow();
		
	}
	
	private void eat() {
          
   
		System.out.println("吃肉");
	}
	
	private void bellow() {
          
   
		System.out.println("吼叫");
	}
}

客户端测试:

public class ClientTest {
          
   
	public static void main(String[] args) {
          
   
		Component component = new ConcreteComponent(); 
		System.out.println("------装饰前:-------");
		component.function();
		Component newComponent = new ConcreteDecorator(component);
		System.out.println("------装饰后:-------");
		newComponent.function();
	}
}

输出: ------装饰前:------- 基本功能:呼吸+觅食+睡觉 ------装饰后:------- 基本功能:呼吸+觅食+睡觉 附加功能:吃肉+吼叫

使用持有component,将功能重用。用组合代替继承,代码更灵活

经验分享 程序员 微信小程序 职场和发展