2012-01-24 66 views
8

我有以下界面。这是一个装饰者还是战略模式,或者两者都不是?

PowerSwitch.java

public interface PowerSwitch { 
    public boolean powerOn(); 
    public boolean powerOff(); 
    public boolean isPowerOn(); 
} 

上述接口应包括的最小集合的其中的任何其它功能可以衍生自方法,使之尽可能容易增加附加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(); 
    } 
} 
+5

为什么不PowerSwitchDecorator实现PowerSwitch的界面?它当然可以... – Ani

回答

3

这就是你需要在运行,以提高你的PowerSwitch实例的情况下,一个很好的做法。我建议你在装饰器中实现PowerSwitch接口。装饰者模式的另一个名称是代理模式。

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

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

+0

谢谢!我将让装饰器实现PowerSwitch接口 – etxalpo

0

如果装饰者也实现了PowerSwitch接口,那真是一个装饰者。我会将其描述为对象聚合。

7

正因为如此,想要使用的toggleOnOff(int)toggleOnOff()方法的任何代码将需要的PowerSwitchDecorator,不PowerSwitch一个实例。这种做法违背了应该对客户透明的装饰器的目的。

如果您希望所有实现都具有这些方法,则应将其包含在PowerSwitch接口中。

然后,@Ani建议,你可以修改上面PowerSwitchDecorator延长PowerSwitch所以你可以这样做:

PowerSwitch switch = new PowerSwitchDecorator(new ConcretePowerSwitch()); 
switch.toggleOnOff(); 

现在你有PowerSwitch类型与PowerSwitchDecorator的能力的变量。

编辑:请注意,您只应使用已建立的模式,如果它满足您的需求。如果它适合你,你可以使用你显示的方法。不需要将它变成特定的模式。

你想传递什么类型的对象?你想你的API在这样的方法:

void connect(PowerSwitch powerSwitch, Appliance appliance); 

或方法是这样的:

void connect(PowerSwitchDecorator powerSwitch, Appliance appliance); 

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

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

+1

但是,这不意味着我需要在所有电源开关实现中实施虚拟方法(toggleOnOff)吗?另外,如果我想在Decorator中稍后添加一个新方法(比如说toggleOffOn),那么我需要将它添加到PowerSwitch接口中并更新所有当前的PowerSwitch实现(因为它们不再编译)?也可能是我无法访问所有powerSwitch实现(可能是服务提供者接口的一部分)的情况。 – etxalpo

+1

作为etxalpo,我不同意。通过使装饰器实现装饰性界面,它仍然很有用,因为PowerSwitch的所有客户端都可以使用PowerSwitchDecorator。就像读者的所有客户端都可以透明地使用BufferedReader一样。这并不妨碍BufferedReader添加自己的方法(例如readLine()),并且这种模式非常有用。 –

+0

是的,没错。你可能会想要一个带有基本切换方法的抽象类,所有的实现都继承它。然后,如果你想要一个特定的方式来切换你可以装饰它。我编辑了我的答案,希望它有帮助;) –

0

它既不是模式。

装饰器有打算包装一个对象并扩展现有的功能使界面对客户端透明。一个BufferedInputstream就是一个例子。请注意,修饰器应该实现与您要打包的类型相同的接口。

//Let Type be the interface that both the Decorator and DecoratedClass implements 
Type yourInstance = new Decorator(new DecoratedClass()); 

注意从代理模式,其中主要意图是控制的对象的访问,而不必通过包裹另一个对象的差异。在这种情况下,您还可以让代理实现相同的界面。

+0

当你说“不是那个...”和“没有区别......”时,你的意思是“注意......”和“注意不同......”吗? –

+0

是的,对于错字感到抱歉。谢谢! –

0

几种模式通常看起来很相似,区别在于它们用法的意图。这里是关于这个主题的更一般的线索:When and How Strategy pattern can be applied instead of decorator pattern?

用你的代码,没有真正的区别呢。它看起来像一个策略,因为PowerSwitchDecorator只是将工作(即算法)委托给PowerSwitch。如果这是您的意图,并且有不同的方式切换PowerSwitches,则策略模式是您的选择。

如果你有一组PowerSwitch,每一个都可以嵌套,然后你实现一个装饰器,每个PowerSwitches都可以稍微加强切换(装饰切换)和这些PowerSwitch。如前所述,在这种情况下,您还需要装饰器成为类型层次结构的一部分。

0

我会说这不是模式。

装饰模式

该装饰图案被用于扩展现有的实现的行为。以图形窗口为例,您可能想要一个具有滚动条的窗口。然后你就可以有一个像

public class ScrollBarsWindow : Window 
{ 
    private Window windowToDecorate; 
    public ScrollBarsWindow(Window windowToDecorate) 
    { 
     this.windowToDecorate = windowToDecorate; 
    } 

    public void Draw() 
    { 
     windowToDecorate.Draw(); 
     DrawScrollBars(); 
    } 

    public void DrawScrollBars() 
    { Draw the scroll bars } 
} 

策略模式是用来做取决于所选择的策略不同事物的策略模式

类。假设你在煮咖啡。在你可以有这样的:

public interface IMakeCoffeeStrategy 
{ 
    public Coffee MakeCoffee(); 
} 

public class CappuccinoStrategy : IMakeCoffeeStrategy 
{ 
    public Coffee MakeCoffee { make your cappuccion } 
} 

public class LatteStrategy : IMakeCoffeeStrategy 
{ 
    public Coffee MakeCoffee { make your latte } 
} 

public class Context 
{ 
    private IMakeCoffeeStrategy strategy; 
    public Context(IMakeCoffeeStrategy strategy) 
    { 
     this.strategy = strategy; 
    } 

    public Coffee MakeSomeCoffee() 
    { 
     return strategy.MakeCoffee(); 
    } 
} 

,并使用它像

public class MyCoffeeMachine 
{ 
    public Coffee MakeCoffee(CoffeeType coffeeType) 
    { 
     if(coffeeType == CoffeeType.Latte) 
      return new Context(new LatteStrategy()).MakeSomeCoffee(); 
     else if(coffeeType == CoffeeType.Cappuccino) 
      return new Context(new CappuccinoStrategy()).MakeSomeCoffee(); 

     ... 
    } 
} 

阅读下面的链接,了解更多信息:

0

你的PowerSwitchDecorator类不是装饰者。你的实现是接近Strategy_pattern即使命令类似Command_pattern

Decorator模式,Decorator实际实现的接口(即Component)和你的类没有这样做。

看一看类图

enter image description here

在上述图中,Component是一个接口。 Decorator实现了Component接口并包含与Composition的接口。看看成员变量 - component

参考这些问题的更好的理解:

Decorator Pattern for IO

Real World Example of the Strategy Pattern

相关问题