随笔分类
装饰模式
Decorator
包装模式
通过一种对客户端透明的方式来扩展对象的功能,是继承关系的一个替换方案
先来看看传统的通过继承来扩展对象功能的方式
代码
public interface Car {
void show();
void run();
}
public class FlyCar implements Car{
@Override
public void run() {
System.out.println("可以跑");
}
@Override
public void show() {
System.out.println("拥有的功能");
this.run();
//扩展的功能
this.fly();
}
public void fly(){
System.out.println("可以飞");
}
}
public class MainClass {
public static void main(String[] args) {
Car car = new FlyCar();
car.show();
}
}
通过继承的方式的确可以扩展对象的功能,但也有一定的缺点
- 类的继承是强耦合的关系,但基类发生更改时,子类不得不也要做一些更改
- 子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性
- 当有多个类要进行功能的扩展或扩展的功能较多时,会增加系统结构的复杂度
- 基类的功能不能进行动态的更改
所以有了优化方案 : 装饰模式
结构图如下
代码实现
public interface Component {
void makeIt();
}
public class ConcreteComponent implements Component{
@Override
public void makeIt() {
System.out.println("这是原有对象的功能");
}
}
public abstract class Decorator implements Component{
private Component component;
public Decorator(Component component){
this.component = component;
}
public void addFun(){
if (component != null)
component.makeIt();
}
}
public class ConcreteDecorator extends Decorator{
public ConcreteDecorator(Component component){
super(component);
}
public void addFun1(){
System.out.println("这是新增的功能1");
}
public void addFun2(){
System.out.println("这是新增的功能2");
}
@Override
public void makeIt() {
this.addFun1();
super.addFun();
this.addFun2();
}
}
public class MainClass {
public static void main(String[] args) {
Component component = new ConcreteComponent();
ConcreteDecorator concreteDecorator = new ConcreteDecorator(component);//让具体的装饰者去扩展具体对象的功能
concreteDecorator.makeIt();
}
}
结构分析
- 抽象组件角色:一个抽象接口,被装饰类和装饰类的父接口
- 具体组件:为抽象组件的实现类
- 抽象装饰角色:包含一个组件的引用,并定义了与抽象组件一致的接口
- 具体装饰角色:负责具体的装饰
优点
- 避免了强耦合的继承,被装饰类与具体的装饰类相互独立,扩展性良好
- 可以通过装饰类动态的扩展被装饰的对象,且可以调换调整扩展功能的先后顺序