使用Decorator模式时找到特定类型的装饰器?

时间:2018-04-29 14:01:47

标签: java android design-patterns reflection decorator

我正在构建一个需要使用多种类似传感器的应用。由于传感器也可能有不同的行为或行为组合,我决定使用decorator pattern

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

enter image description here

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

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

是一个有效的声明,声明了经过滤波和校准的加速计传感器。

现在让我们说setCalibration()中有一个名为CalibratedSensorDecorator的方法。显然我无法打电话

sensor.setCalibration();

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

((CalibratedSensorDecorator)sensor).setCalibration()
由于sensorFilteredSensorDecorator

也不会工作。

如何在这种特殊情况下进入CalibratedSensorDecorator,更常见的是在任何"链中的任何特定装饰者"装饰者?我不想将它们存储为单独的变量,我想动态地将它们存储起来。

2 个答案:

答案 0 :(得分:1)

由于它是一个设计问题,所以没有任何正确的答案,你需要做出好的或不好的选择。

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

  

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

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

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

编辑1:

  

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

是的,你是对的。它不禁止添加方法,但如果方法正在改变Object的状态,那么应该重新考虑它。所有这些模式都只是可以根据我们的需求进行调整的指南。

解释我的理由:

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

public IMeasureSensor getCalibratedSensor(){
    ...
}

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

您应该尽量使您的类保持不变,以便调试和维护变得轻松。重新创建对象没有坏处,因为旧的将被垃圾收集。

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

答案 1 :(得分:0)

虽然Sagar的回答讨论了考虑使用另一种方法而不是装饰器模式的一些(有效)原因,但我想出了一个解决找到正确装饰器的实际问题的工作解决方案。

=

方法/** * Walks the decorator hierarchy recursively from the outside in (excluding the final * IMeasureSensor which is not a ISensorDecorator), and returns the decorator of the given class. * If none can be found, null is returned. */ IMeasureSensor findDecorator(IMeasureSensor sensor, Class decoratorClass){ if( ISensorDecorator.class.isAssignableFrom(sensor.getClass()) ){ return (sensor.getClass() == decoratorClass) ? sensor : findDecorator(((ISensorDecorator) sensor).getDecoratee(), decoratorClass); } else return null; } 只返回“decoratee”,即装饰器装饰的ISensorDecorator.getDecoratee()

IMeasureSensor

然后,您可以使用public IMeasureSensor getDecoratee(){ return mMeasureSensor; } 找到给定类型的(最外层)装饰器,如下所示:

findDecorator()