首页 > 解决方案 > 使用装饰器模式时找到特定类型的装饰器?

问题描述

我正在构建一个需要使用多种类似传感器的应用程序。由于传感器也可能具有不同的行为或行为组合,因此我决定使用装饰器模式

简而言之,我的层次结构如下所示:

在此处输入图像描述

因此,任何具体ISensorDecorator类都可以装饰(包装)任何具体IMeasureSensor类,但由于具体 ISensorDecorator也是具体的IMeasureSensor,它们可以相互包装。所以例如

IMeasureSensor sensor = new FilteredSensorDecorator(
    new CalibratedSensorDecorator(
        new AccelerometerSensor()
    )
);

是声明经过过滤和校准的加速度计传感器的有效语句。

现在假设我有一个名为setCalibration()in的方法CalibratedSensorDecorator。显然我不能打电话

sensor.setCalibration();

因为IMeasureSensor没有setCalibration()方法。并尝试使用

((CalibratedSensorDecorator)sensor).setCalibration()

也不行,因为sensorFilteredSensorDecorator.

在这种特殊情况下,更一般地说,我怎样才能到达CalibratedSensorDecorator任何装饰器“链”中的任何特定装饰器?我不想将它们存储为单独的变量,我想动态地进行。

标签: javaandroiddesign-patternsreflectiondecorator

解决方案


由于它是一个设计问题,因此不会有任何正确答案,您需要做出选择,可能好或不好。

您不应该为特定类添加方法,因为它会违反Liskov substitution principle

程序中的对象应该可以用其子类型的实例替换,而不会改变该程序的正确性。

您可以初始化calibrationin 构造函数CalibratedSensorDecorator并在执行所需函数时使用它。

如果这不符合您的要求,则可能CalibratedSensorDecorator不属于您的传感器层次结构。考虑将其分离并使用策略模式来决定使用哪一个。

编辑1:

我的理解并不是说您不应该向子类型添加方法?

是的你是对的。它不禁止添加方法,但如果方法正在更改对象的状态,则应重新考虑。所有这些模式只是可以根据我们的需要进行调整的指导方针。

解释我的理由:

想象一下,您已经创建了setCalibration()on CalibratedSensorDecorator。您可以通过以下方式向CalibratedSensorDecorator内部开发人员或外部开发人员公开。您创建了一个工厂,它只返回IMeasureSensor如下:

public IMeasureSensor getCalibratedSensor(){
    ...
}

现在,您的 API 用户只需了解这一点,并且很高兴他/她当前的代码正在运行。但意识到他/她错过了setCalibration()几个小时的调试后发现的。此外,他/她必须编写类型检查和类型转换代码才能使用此功能,这对于干净的代码可能不是很好。

你应该尽量保持你的类是不可变的,以便调试和维护方便。重新创建对象没有害处,因为旧对象将被垃圾收集。

这只是我的建议,您决定仔细考虑什么最适合您的用例。如果它是强制性的,您仍然可以继续使用您的新方法来创建该方法,并确保已制作适当的文档以使用户了解其用法。


推荐阅读