概述:
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
装饰器模式,顾名思义,给别的类进行装饰,使别的类变得更漂亮(功能更强),同时有保留原有类,不改变原有的类。
特点:
优点:
装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式
装饰模式可以动态扩展一个实现类的功能。
缺点:
多层装饰比较复杂。
使用场景:
1、扩展一个类的功能。
2、动态增加功能,动态撤销。
实现方法:
例如装修房子,我们买来的房子如果是毛坯房(被包装的类),我们在收房之后会对其进行装修(Decorator),得到一个装修的很漂亮(被增强的功能)的房子(装饰之后的类)
首先房子开发商定义了一个房子的基本功能living()
public interface House {
// 居住
void living();
}
然后房子开发商批量创建了一批毛坯房(被包装的类)Room
,只有基本的功能living()
public class Room implements House {
@Override
public void living() {
System.out.println("Room living");
}
}
再然后我们买了毛坯房(被包装的类)Room
,然后对毛坯房进行装饰,得到一个精装修的房子BeautyRoom
,除了实现了本来定义的基本功能living()
外,还变得更好看了(被增强功能)
public class BeautyRoom implements House {
private House room;
BeautyRoom(House room){
this.room = room;
}
@Override
public void living() {
// 基本功能
room.living();
// 增强功能
System.out.println("this room becomes more beauty");
}
}
这样我们在不破坏房子原来结构的情况下,使得房子变得更漂亮了。我们在没装修之前可以居住(v1.0需求),然后有钱了进行了装修,居住更好了(v2.0)
public class DecoratorTest {
public static void main(String[] args) {
House room = new Room();
House beautyRoom = new BeautyRoom(room);
// v1.0 基础功能
// room.living();
// v2.0 添加了增强功能
beautyRoom.living();
}
}
思考:这个装饰器BeautyRoom
是不是可以用继承Room
并重写living()
方法实现一样的功能呢?
从功能实现角度看,2者可以互相代替的。
public class BeautyRoomExtends extends Room{
@Override
public void living() {
// 基本功能
super.living();
// 增强功能
System.out.println("this room becomes more beauty");
}
}
那么2者的区别是什么呢?为什么使用装饰器不使用继承来实现这个需求?
试想一下,如果这个时候,开发商又开发了另外一种房子Room2
,这个房子也要进行装修,如果使用继承,那么就需要再创建一个BeautyRoom2Extends
来实现Room2
的装修
public class BeautyRoom2Extends extends Room2{
@Override
public void living() {
super.living();
// 增强功能
System.out.println("this room becomes more beauty");
}
}
public class DecoratorTest {
public static void main(String[] args) {
House room2 = new Room2();
House beautyRoom2Extends = new BeautyRoom2Extends();
beautyRoom2Extends.living();
}
}
随着需求的越来越多,需要被装修的House
越来越多,每多一个House
,我们都需要去创建一个对应的继承类Room2Extends
去进行装修(功能增强),慢慢的类越来越多
如果使用装饰器的话,那么还需要去创建装修类吗?我们只需要把要被装修的类传入到我们创建的那个装修的装饰器内就行了
public class DecoratorTest {
public static void main(String[] args) {
House room2 = new Room2();
House beautyRoom = new BeautyRoom(room2);
beautyRoom.living();
}
}
同样实现为Room2
装修的功能,但是根本不需要去创建Room2Extends
这个继承类。