Is it a decorator or a strategy template, or none of the two?

I have the following interface.

Powerswitch.java

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

The above interface should consist of a minimal set of methods from which any other functionality can be derived to make adding additional PowerSwitch implementations as simple as possible.

I would like to add functionality to the PowerSwitch interface at runtime (what decorators do) by creating a class that contains the composition of the PowerSwitch instance and adds new methods, such as the two toggleOnOff () methods below. Thus, I only need to implement two switching methods once, and this applies to all PowerSwitch implementations.

Is this considered good / bad practice? If bad, any other recommendations?

This does not match the style of the decorator as it adds additional methods. Is this a strategy template or composition template? Or does he have a different template name? Is there such a thing as an "interface decorator"?

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(); } } 
+8
java design-patterns decorator strategy-pattern
source share
7 answers

However, any code that wants to use the toggleOnOff(int) or toggleOnOff() methods will require an instance of PowerSwitchDecorator , not PowerSwitch . This view hits the decorator's goal, which should be transparent to the client.

If you want all implementations to have these methods, you must include them in the PowerSwitch interface.

Then, as @Ani suggests, you can modify the PowerSwitchDecorator above to extend PowerSwitch so you can do this:

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

You now have a variable of type PowerSwitch with the capabilities of PowerSwitchDecorator .

EDIT: Please note that you should only use the installed template if it meets your needs. You can use your approach if it works for you. There is no need to shoe it in a certain order.

What type of facility do you want to go through? You need these methods in your API:

 void connect(PowerSwitch powerSwitch, Appliance appliance); 

Or methods like this:

 void connect(PowerSwitchDecorator powerSwitch, Appliance appliance); 

(sorry, these are not very good examples)

If you want the first, then everyone will have to manually β€œdecorate” their PowerSwitch to get some convenient methods. It may be convenient for you now, but I think it will be inconvenient for users of your code, and they probably will not worry about it. If you want to use the latter, you must use the PowerSwitchDecorator type in your method signatures, which usually means that you always deal with PowerSwitchDecorator , not raw PowerSwitch es.

+7
source share

This is good practice when you need to upgrade your PowerSwitch instance at run time. I recommend that you implement the PowerSwitch interface in the decorator. Another name for the decorator pattern is the proxy pattern.

You can define advanced methods in another interface that extends your PowerSwitch interface. This avoids the dependency on the decorator when these advanced methods are needed to call.

Class extension is good practice when you need to improve or override compilation behavior.

+3
source share

It really would be a decorator if the decorator also implemented the PowerSwitch interface. I would describe this as an aggregation of objects.

0
source share

This is not one of the patterns.

The decorator intends to wrap the object and extend the existing functionality, making the interface transparent to the client. BufferedInputstream example. Note that Decorator must implement the same interface as the Type that you are wrapping.

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

Pay attention to the difference from the proxy template, where the main intention is to control access to the object, and not necessarily by transferring another object. In this case, you also allowed the proxy server to implement the same interface.

0
source share

Several templates often look the same, the difference is the intention to use them. Here's a more general thread on this topic: When and how can a strategy template be applied instead of a decorator template?

There is no real difference with your code yet. This seems like a strategy because PowerSwitchDecorator simply delegates the work (i.e. the algorithm) to PowerSwitch. If this is your intention and there are alternative PowerSwitches switches in different ways, the strategy template is your choice.

If instead you have a set of PowerSwitches, each of which slightly improves the switch (decorating the switch), and these PowerSwitches can be nested, then you implement a decorator. As already mentioned, in this case you also need decorators that will be part of the type hierarchy.

0
source share

I would say that this is not one of the patterns.

Decorator drawing

The decorator pattern is used to extend the behavior of an existing implementation. Take the graphic window as an example; you can have a window with scroll bars. Then you might have a class like

 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 } } 

Strategy Template

The strategy template is used to perform different actions depending on the chosen strategy. Say you make coffee. You might have something like:

 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(); } } 

and use it like

 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(); ... } } 

Read the following links for more information:

0
source share

Your PowerSwitchDecorator class PowerSwitchDecorator not a decorator. Your implementation is close to Strategy_pattern , although the commands resemble Command_pattern

In a Decorator template, Decorator actually implements an interface (i.e., Component ), and your class does not do the same.

Look at the class diagram

enter image description here

In the diagram above, Component is an interface. Decorator implements the Component interface and contains an interface with Composition . Look at the member variable - Component .

Refer to these questions for a better understanding:

Decorator drawing for IO

Real World Strategy Template Example

0
source share

All Articles