这是装饰者还是策略模式,或者两者都不是?

etx*_*lpo 8 java design-patterns decorator strategy-pattern

我有以下界面.

PowerSwitch.java

public interface PowerSwitch {
    public boolean powerOn();
    public boolean powerOff();
    public boolean isPowerOn();
}
Run Code Online (Sandbox Code Playgroud)

上面的接口应该包含可以从中派生出任何其他功能的最小方法集,以便尽可能简单地添加其他PowerSwitch实现.

我想在运行时向PowerSwitch接口添加功能(装饰器做什么),创建一个包含PowerSwitch实例组合的类并添加新方法,如下面的两个toggleOnOff()方法.这样我只需要实现两次切换方法,它将适用于所有PowerSwitch实现.

这被认为是一种好/坏的做法吗?如果不好,还有其他建议吗?

它并不真正符合装饰器模式,因为它增加了额外的方法.它是策略模式还是组合模式?或者它有另一个模式名称?有"界面装饰"这样的东西吗?

PowerSwitchDecorator.java

public class PowerSwitchDecorator {
    private PowerSwitch ps;

    public PowerSwitchDecorator(PowerSwitch ps) {
        this.ps = ps;
    }

    public void toggleOnOff(int millis) throws InterruptedException{
        powerOn();
        Thread.sleep(millis);
        powerOff();
    }

    public void toggleOnOff(){
    powerOn();
    powerOff();
    }

    public boolean powerOn() {
        return ps.powerOn();
    }

    public boolean powerOff() {
        return ps.powerOff();
    }

    public boolean isPowerOn() {
        return ps.isPowerOn();
    }
}
Run Code Online (Sandbox Code Playgroud)

Gya*_*uyn 7

实际上,任何想要使用toggleOnOff(int)toggleOnOff()方法的代码都需要一个实例PowerSwitchDecorator,而不是PowerSwitch.这种方式破坏了装饰者的目的,这对客户来说应该是透明的.

如果您希望所有实现都具有这些方法,则应将它们包含在PowerSwitch界面中.

然后,正如@Ani建议的那样,您可以修改上面的内容PowerSwitchDecorator以进行扩展,PowerSwitch这样您就可以这样做:

PowerSwitch switch = new PowerSwitchDecorator(new ConcretePowerSwitch());
switch.toggleOnOff();
Run Code Online (Sandbox Code Playgroud)

现在你有了一个PowerSwitch带有PowerSwitchDecorator功能的变量.

编辑:请注意,如果满足您的需求,您应该只使用已建立的模式.如果它适合您,您可以使用您显示的方法.无需将其鞋拔成特定图案.

你想传递什么类型的物体?你想在API中使用这样的方法:

void connect(PowerSwitch powerSwitch, Appliance appliance);
Run Code Online (Sandbox Code Playgroud)

或者像这样的方法:

void connect(PowerSwitchDecorator powerSwitch, Appliance appliance);
Run Code Online (Sandbox Code Playgroud)

(对不起,他们不是很好的例子)

如果你想要前者,那么每个人都必须手动"装饰"他们PowerSwitch只是为了获得一些方便的方法.现在对您来说可能很方便,但我认为对您的代码用户来说不方便,他们可能不会为此烦恼.如果你想要后者,你必须PowerSwitchDecorator在方法签名中使用类型,这往往意味着你总是处理PowerSwitchDecorators而不是原始PowerSwitches.


小智 3

如果您需要在运行时增强 PowerSwitch 实例,那么这是一个很好的做法。我建议您在装饰器中实现 PowerSwitch 接口。装饰器模式的另一个名称是代理模式。

您可以在扩展 PowerSwitch 接口的另一个接口中定义扩展方法。当需要调用这些扩展方法时,这将避免对装饰器的依赖。

当您需要在编译时增强或重新定义行为时,扩展类是一个很好的做法。