`

Decorator装饰模式

    博客分类:
  • Java
阅读更多

Decorator装饰模式是一种结构型模式,它主要是解决:“过度地使用了继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀(多继承)。继承为类型引入的静态特质的意思是说以继承的方式使某一类型要获得功能是在编译时。所谓静态,是指在编译时;动态,是指在运行时。

GoF《设计模式》中说道:动态的给一个对象添加一些额外的职责。就增加功能而言,Decorator模式比生成子类更为灵活。

下面来看看Decorator模式的结构:

 

 

 

看这个结构好像不是很明白,下面我根据代码讲解一下这个结构。我想了一个场景:我们现在用的手机功能很多,我就用Decorator模式实现一下对某个手机的GSP和蓝牙功能扩展。

首先,我们需要一个手机的接口或者是抽象类,我这里就用抽象类来实现,代码如下:

 

 

package decorator_phone;

public abstract class AbstractCellPhone {
	public abstract String CallNumber();
    public abstract String SendMessage();
}

 

 

AbstractCellPhone也就是结构图中的Component,然后,我再来实现NokiaMoto的手机类,这类要继承AbstractCellPhone,也就是图中ConcreteComponent类要继承Component,实现代码如下:

 

 

package decorator_phone;

public class NokiaPhone extends AbstractCellPhone {

	public String CallNumber() {
		return "NokiaPhone call sombody";
	}

	public String SendMessage() {
		return "NokiaPhone send a message to somebody";
	}
}

 

package decorator_phone;

public class MotoPhone extends AbstractCellPhone {

	public String CallNumber() {
		return "MotoPhone call sombody";
	}

	public String SendMessage() {
		return "MotoPhone send a message to somebody";
	}
}

 

 

接下来我需要一个Decorator接口或者抽象类,实现代码如下:

分享到:
评论
2 楼 csdn_zuoqiang 2010-08-17  
AbstractCellPhone phoneMoto = new MotoPhone();
...
DecoratorGPS gpsMoto = new DecoratorGPS(phoneMoto);
...

如果你细心,会发现,上面调用类似我们读取文件时的调用:

FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);

实际上Java 的I/O API就是使用Decorator实现的,I/O变种很多,如果都采取继承方法,将会产生很多子类,显然相当繁琐.
1 楼 csdn_zuoqiang 2010-08-14  
package decorator_phone;


public abstract class Decorator extends AbstractCellPhone {

	private AbstractCellPhone _phone ;
		
	public Decorator(AbstractCellPhone phone) {
		_phone = phone ;
	}
	
	public String CallNumber() {
		return _phone.CallNumber();
	}

	public String SendMessage() {
		return _phone.SendMessage();
	}

}


正如结构图中,这个Decorator即继承了AbstractCellPhone,又包含了一个私有的AbstractCellPhone的对象。这样做的意义是:Decorator类又使用了另外一个Component类。我们可以使用一个或多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。在下来,我要实现GSP和蓝牙的功能扩展,它们要继承自Decorator,代码如下:

package decorator_phone;

public class DecoratorGPS extends Decorator {
	
	public DecoratorGPS(AbstractCellPhone phoneGPS) {
		super(phoneGPS);
	}
	
	public String CallNumber() {
		return super.CallNumber() + " with GPS";
	}

	public String SendMessage() {
		return super.SendMessage() + " with GPS";
	}
}


package decorator_phone;

public class DecoratorBlueTooth extends Decorator {
	
	public DecoratorBlueTooth(AbstractCellPhone phoneGPS) {
		super(phoneGPS);
	}
	
	public String CallNumber() {
		return super.CallNumber() + " with BlueTooth";
	}

	public String SendMessage() {
		return super.SendMessage() + " with BlueTooth";
	}
}

最后,用客户端程序验证一下:

package decorator_phone;

public class TestPhone {
	public static void main(String[] args) {
		
		AbstractCellPhone phoneNokia = new NokiaPhone();
		
		System.out.println("============== 直接继承方式 ==============");
		System.out.println(phoneNokia.CallNumber());
		System.out.println(phoneNokia.SendMessage());
		
		//add GSP
        DecoratorGPS gpsNokia = new DecoratorGPS(phoneNokia);
        System.out.println("============== 经  过   装  饰 ==============");
        System.out.println(gpsNokia.CallNumber());
        System.out.println(gpsNokia.SendMessage());
        //add GSP and bluetooth
        DecoratorBlueTooth bluetoothNokia = new DecoratorBlueTooth(gpsNokia);
        System.out.println(bluetoothNokia.CallNumber());
        System.out.println(bluetoothNokia.SendMessage());
        
        
        AbstractCellPhone phoneMoto = new MotoPhone();
		
		System.out.println("\n============== 直接继承方式 ==============");
		System.out.println(phoneMoto.CallNumber());
		System.out.println(phoneMoto.SendMessage());
		
		//add GSP
        DecoratorGPS gpsMoto = new DecoratorGPS(phoneMoto);
        System.out.println("============== 经  过   装  饰 ==============");
        System.out.println(gpsMoto.CallNumber());
        System.out.println(gpsMoto.SendMessage());
        //add GSP and bluetooth
        DecoratorBlueTooth bluetoothMoto = new DecoratorBlueTooth(gpsMoto);
        System.out.println(bluetoothMoto.CallNumber());
        System.out.println(bluetoothMoto.SendMessage());
	}
}

结果是:

============== 直接继承方式 ==============
NokiaPhone call sombody
NokiaPhone send a message to somebody
============== 经  过   装  饰 ==============
NokiaPhone call sombody with GPS
NokiaPhone send a message to somebody with GPS
NokiaPhone call sombody with GPS with BlueTooth
NokiaPhone send a message to somebody with GPS with BlueTooth

============== 直接继承方式 ==============
MotoPhone call sombody
MotoPhone send a message to somebody
============== 经  过   装  饰 ==============
MotoPhone call sombody with GPS
MotoPhone send a message to somebody with GPS
MotoPhone call sombody with GPS with BlueTooth
MotoPhone send a message to somebody with GPS with BlueTooth

相关推荐

Global site tag (gtag.js) - Google Analytics