JAVA - 扩展与接口 - 策略设计模式
JAVA - extends vs interface - Strategy design pattern
我有一个场景,其中多个具体 classes extends
多个 Abstract
classes。我不知所措想出一个干净的结构,减少文件数量,避免代码重复。
要求根据某些标准以不同方式显示各种传感器值。温度、电压、电流等传感器值可以有一个 anlaog 小部件、一个数字标签或两者的组合。对于 3 种不同类型的视图,我有 3 Abstract
classes。这 3 Abstract
classes 实现了一个定义如何绘制视图的方法。每个传感器查看 extends
3 Abstract
classes 并实现读取传感器的方法,执行一些工程转换并显示传感器值。
这里的问题是具体的 classes 实现的代码是相同的,无论它扩展什么 Abstract
class。 CAnalogTempView
、CDigitalTempView
和 CCustomTempView
都具有相同的实现,但扩展了不同的 classes。
这看起来很尴尬。代码重复并且源文件的数量增加了 3 倍。我在这里是否遗漏了一些简单的东西?有这样的问题的模式吗?我可以 extends
传感器在 运行 时间查看 classes 吗?实际代码更复杂。为了清楚起见,我过度简化了问题陈述。
编辑:
有几个传感器视图实现了 Abstract
视图 classes。每个传感器的 calculate()
方法不同。为了简单起见,我刚刚列出了 3 个具体的 classes。同样,你会有 CAnalogVoltageView
、CDigitalVoltageView
、CCustomVoltageView
和 CAnalogCurrentView
、CDigitalCurrentView
、CCustomCurrentView
等等
public abstract class CView
{
public abstract void draw();
public abstract void calculate();
}
public abstract class CAnalogView extends CView
{
public void draw()
{
// draw specific to analog view
}
}
public abstract class CDigitalView extends CView
{
public void draw()
{
// draw specific to digital view
}
}
public abstract class CCustomView extends CView
{
public void draw()
{
// draw specific to custom view
}
}
// concrete implementations
public class CAnalogTempView extends CAnalogView
{
public void calculate()
{
// read and calculate sensor value here
}
}
public class CDigitalTempView extends CDigitalView
{
public void calculate()
{
// calculate here. same as CAnalogTempView::calculate()
}
}
public class CCustomTempView extends CCustomView
{
public void calculate()
{
// calculate here. same as CAnalogTempView::calculate()
}
}
我会将 Sensor
实现与 View
分开。传感器不需要知道视图存在。我会创建一个 Sensor
接口,方法 calculate()
得到 returns 一些结果(我在示例中使用了 double
):
public interface Sensor {
double calculate();
}
public class TemperatureSensor implements Sensor {
public double calculate() {
// specific implementation for the temperature sensor
}
}
并更改抽象 CView
以具有传感器的属性,以及 calculate()
的实现,仅显示特定传感器计算的结果。
public abstract class CView {
private Sensor sensor;
CView(Sensor sensor) {
this.sensor = sensor;
}
public abstract void draw();
public void calculate() {
double result = this.sensor.calculate();
// display the result
}
}
public class CDigitalView extends CView {
CDigitalView(Sensor sensor) {
super(sensor);
}
public void draw() {
// draw specific to digital view
}
}
所以每次创建视图时,在构造函数中传递要显示的传感器,如下所示:
Sensor temperatureSensor = new TemperatureSensor();
CView digitalView = new CDigitalView(temperatureSensor);
这样,每个传感器都有一个具体的 class,每个视图都有一个具体的 class。如果 n 是视图数,m 是传感器数,则您的总数是 n + 米。使用模拟、数字和自定义视图,加上温度、电压和电流传感器,您将获得 6 classes。
相比之下,通过为每个视图的每个传感器创建一个具体的 class,正如您所做的那样,您将得到 n * m 具体classes。在上面的示例中,总数为 9,不包括 3 个抽象视图 classes.
我唯一能看到的是您可以在 CView
class 中提供 public abstract void calculate()
的实现。如果有 class 想要覆盖它,我会覆盖它
策略设计模式会帮助你。嗯,你应该记住一件事。
Use as less extends
keyword as possible, better to use Interfaces or composition.
解法:
封装calculate()
,因为calculate()
将来可能会改变,它有不同的实现。
进程:
1) 创建一个界面 CalcInterface
有 calculate()
.
2) 通过 3 个不同的 class 实现 CalcInterface
,比如 CAnalogTempCalc
、CDigitalTempCalc
和 CCustomTempCalc
。然后在每个 class.
中实现 calculate()
3) 现在是 composition
的时候了。假设你有 Sensor
class (main class) ...然后创建 CalcInterface
类型的对象。 PS:它将有display()
,这对所有人都是通用的。
4) 现在制作 3 个不同的 classes,extends Sensor
表示 AnalogSensor
、TempSensor
和 CustomSensor
...
5) 现在在运行时,您将生成任何类型的(CAnalogTempCalc
、CDigitalTempCalc
和 CCustomTempCalc
)对象。
编辑:
下面是 Class 图,我不擅长艺术...但是这个图会让你对 classes 和接口以及如何有效地使用它们有一些想法。
现在,只要实现 CalcInterface
...
,您就可以实现任意数量的 CustomCalcuations
这是 POWER 以在不改变当前实现的情况下适应变化 您通过遵循策略设计模式获得。
我有一个场景,其中多个具体 classes extends
多个 Abstract
classes。我不知所措想出一个干净的结构,减少文件数量,避免代码重复。
要求根据某些标准以不同方式显示各种传感器值。温度、电压、电流等传感器值可以有一个 anlaog 小部件、一个数字标签或两者的组合。对于 3 种不同类型的视图,我有 3 Abstract
classes。这 3 Abstract
classes 实现了一个定义如何绘制视图的方法。每个传感器查看 extends
3 Abstract
classes 并实现读取传感器的方法,执行一些工程转换并显示传感器值。
这里的问题是具体的 classes 实现的代码是相同的,无论它扩展什么 Abstract
class。 CAnalogTempView
、CDigitalTempView
和 CCustomTempView
都具有相同的实现,但扩展了不同的 classes。
这看起来很尴尬。代码重复并且源文件的数量增加了 3 倍。我在这里是否遗漏了一些简单的东西?有这样的问题的模式吗?我可以 extends
传感器在 运行 时间查看 classes 吗?实际代码更复杂。为了清楚起见,我过度简化了问题陈述。
编辑:
有几个传感器视图实现了 Abstract
视图 classes。每个传感器的 calculate()
方法不同。为了简单起见,我刚刚列出了 3 个具体的 classes。同样,你会有 CAnalogVoltageView
、CDigitalVoltageView
、CCustomVoltageView
和 CAnalogCurrentView
、CDigitalCurrentView
、CCustomCurrentView
等等
public abstract class CView
{
public abstract void draw();
public abstract void calculate();
}
public abstract class CAnalogView extends CView
{
public void draw()
{
// draw specific to analog view
}
}
public abstract class CDigitalView extends CView
{
public void draw()
{
// draw specific to digital view
}
}
public abstract class CCustomView extends CView
{
public void draw()
{
// draw specific to custom view
}
}
// concrete implementations
public class CAnalogTempView extends CAnalogView
{
public void calculate()
{
// read and calculate sensor value here
}
}
public class CDigitalTempView extends CDigitalView
{
public void calculate()
{
// calculate here. same as CAnalogTempView::calculate()
}
}
public class CCustomTempView extends CCustomView
{
public void calculate()
{
// calculate here. same as CAnalogTempView::calculate()
}
}
我会将 Sensor
实现与 View
分开。传感器不需要知道视图存在。我会创建一个 Sensor
接口,方法 calculate()
得到 returns 一些结果(我在示例中使用了 double
):
public interface Sensor {
double calculate();
}
public class TemperatureSensor implements Sensor {
public double calculate() {
// specific implementation for the temperature sensor
}
}
并更改抽象 CView
以具有传感器的属性,以及 calculate()
的实现,仅显示特定传感器计算的结果。
public abstract class CView {
private Sensor sensor;
CView(Sensor sensor) {
this.sensor = sensor;
}
public abstract void draw();
public void calculate() {
double result = this.sensor.calculate();
// display the result
}
}
public class CDigitalView extends CView {
CDigitalView(Sensor sensor) {
super(sensor);
}
public void draw() {
// draw specific to digital view
}
}
所以每次创建视图时,在构造函数中传递要显示的传感器,如下所示:
Sensor temperatureSensor = new TemperatureSensor();
CView digitalView = new CDigitalView(temperatureSensor);
这样,每个传感器都有一个具体的 class,每个视图都有一个具体的 class。如果 n 是视图数,m 是传感器数,则您的总数是 n + 米。使用模拟、数字和自定义视图,加上温度、电压和电流传感器,您将获得 6 classes。
相比之下,通过为每个视图的每个传感器创建一个具体的 class,正如您所做的那样,您将得到 n * m 具体classes。在上面的示例中,总数为 9,不包括 3 个抽象视图 classes.
我唯一能看到的是您可以在 CView
class 中提供 public abstract void calculate()
的实现。如果有 class 想要覆盖它,我会覆盖它
策略设计模式会帮助你。嗯,你应该记住一件事。
Use as less
extends
keyword as possible, better to use Interfaces or composition.
解法:
封装calculate()
,因为calculate()
将来可能会改变,它有不同的实现。
进程:
1) 创建一个界面 CalcInterface
有 calculate()
.
2) 通过 3 个不同的 class 实现 CalcInterface
,比如 CAnalogTempCalc
、CDigitalTempCalc
和 CCustomTempCalc
。然后在每个 class.
calculate()
3) 现在是 composition
的时候了。假设你有 Sensor
class (main class) ...然后创建 CalcInterface
类型的对象。 PS:它将有display()
,这对所有人都是通用的。
4) 现在制作 3 个不同的 classes,extends Sensor
表示 AnalogSensor
、TempSensor
和 CustomSensor
...
5) 现在在运行时,您将生成任何类型的(CAnalogTempCalc
、CDigitalTempCalc
和 CCustomTempCalc
)对象。
编辑:
下面是 Class 图,我不擅长艺术...但是这个图会让你对 classes 和接口以及如何有效地使用它们有一些想法。
现在,只要实现 CalcInterface
...
这是 POWER 以在不改变当前实现的情况下适应变化 您通过遵循策略设计模式获得。