说明
装饰者模式可以实现对原类进行动态的功能扩展,装饰者与被装饰者共同继承一个超类或实现一个接口,并且装饰者要拥有被装饰者的对象实例,具体代码如下。
UML
代码
以为电脑扩展内存、硬盘、软件为例,计算价格。
顶级父类,是一个没有规定类型的电脑
/**
* @author ctl
* @date 2021/1/16
* 顶级父类
*/
public abstract class Computer {
protected String name;
public String getName() {
return name;
}
public abstract int getPrice();
}
要扩展的类,是一台macbook,原价为9999
/**
* @author ctl
* @date 2021/1/16
* 要扩展的类
*/
public class MacBook extends Computer {
public MacBook() {
name = "MacBook";
}
@Override
public int getPrice() {
return 9999;
}
}
要扩展的类都继承这个抽象父类
/**
* @author ctl
* @date 2021/1/16
* 扩展类,给后面具体扩展类做抽象父类
*/
public abstract class Adder extends Computer {
@Override
abstract public String getName();
}
内存扩展类,价格1500
/**
* @author ctl
* @date 2021/1/16
* 加内存 要1500
*/
public class Memory extends Adder {
Computer computer;
public Memory(Computer computer) {
this.computer = computer;
}
@Override
public String getName() {
return computer.getName() + " 加内存";
}
@Override
public int getPrice() {
return computer.getPrice() + 1500;
}
}
软件扩展类,价格1000
/**
* @author ctl
* @date 2021/1/16
* 软件扩展类 价格1000
*/
public class SoftWare extends Adder {
Computer computer;
public SoftWare(Computer computer) {
this.computer = computer;
}
@Override
public String getName() {
return computer.getName() + " 装软件";
}
@Override
public int getPrice() {
return computer.getPrice() + 1000;
}
}
硬盘扩展类,价格3000
/**
* @author ctl
* @date 2021/1/16
* 硬盘 价格3000
*/
public class Ssd extends Adder {
Computer computer;
public Ssd(Computer computer) {
this.computer = computer;
}
@Override
public String getName() {
return computer.getName() + " 加硬盘";
}
@Override
public int getPrice() {
return computer.getPrice() + 3000;
}
}
测试类
/**
* @author ctl
* @date 2021/1/16
*/
public class DecoratorMain {
public static void main(String[] args) {
// 一步一步扩展
Computer computer = new MacBook();
System.out.println(computer.getName() + " 价格:" + computer.getPrice());
Memory memory = new Memory(computer);
System.out.println(memory.getName() + " 价格:" + memory.getPrice());
SoftWare softWare = new SoftWare(memory);
System.out.println(softWare.getName() + " 价格:" + softWare.getPrice());
Ssd ssd = new Ssd(softWare);
System.out.println(ssd.getName() + " 价格:" + ssd.getPrice());
// 分割线
System.out.println("---------------------------");
// 一步到位
Computer computer1 = new Memory(new SoftWare(new Ssd(new MacBook())));
System.out.println(computer1.getName() + " 价格:" + computer1.getPrice());
}
}
结果如下
可以一步一步扩展计算价格,也可以一步扩展多个,再计算价格。
总结
这种模式的要点就在于继承关系,并且装饰者要拥有被装饰者的实例。其实也是用到了一些委托的概念,一级一级向上委托计算并返回结果。Java的IO中大量用到了这种模式。