[英]Is this a decorator or a strategy pattern, or neither of the two?
我有以下界面。
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();
}
}
實際上,任何想要使用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
而不是原始PowerSwitch
es。
在運行時需要增強PowerSwitch實例的情況下,這是一個很好的做法。 我建議你在裝飾器中實現PowerSwitch接口。 裝飾器模式的另一個名稱是代理模式。
您可以在擴展PowerSwitch接口的另一個接口中定義擴展方法。 當需要調用這些擴展方法時,這將避免依賴於裝飾器。
當您需要在編譯時增強或重新定義行為時,擴展類是一種很好的做法。
您的PowerSwitchDecorator
類不是裝飾器。 即使命令類似於Command_pattern,您的實現也接近於Strategy_pattern
在Decorator
模式中, Decorator
實際上實現了接口(即Component
),而你的類卻沒有做同樣的事情。
看看班級圖
在上圖中, Component
是一個接口。 Decorator
實現了Component
接口,並包含了Composition
的接口。 查看成員變量 - component
。
請參閱以下問題以便更好地理解:
如果裝飾器也實現了PowerSwitch接口,它真的會是一個裝飾器。 我將其描述為對象聚合。
它既不是模式。
裝飾器旨在包裝對象並擴展已存在的功能,使得接口對客戶端透明。 BufferedInputstream就是一個例子。 請注意,Decorator應該實現與要包裝的Type相同的接口。
//Let Type be the interface that both the Decorator and DecoratedClass implements
Type yourInstance = new Decorator(new DecoratedClass());
請注意與Proxy-pattern的區別,其中主要目的是控制對對象的訪問,而不一定是通過包裝另一個對象。 在這種情況下,您還可以讓代理實現相同的接口。
幾種模式通常看起來相似,不同之處在於它們的使用意圖。 這是關於這個主題的更一般的主題: 何時以及如何應用策略模式而不是裝飾模式?
使用您的代碼,還沒有真正的區別。 它看起來像一個策略,因為PowerSwitchDecorator只是將工作(即算法)委托給PowerSwitch。 如果這是你的意圖,並且有不同的PowerSwitch以不同的方式切換,那么策略模式是你的選擇。
如果您有一組PowerSwitch,每個都以一種輕微的方式增強切換(裝飾切換)並且這些PowerSwitch可以嵌套,那么您正在實現一個decorater。 如前所述,在這種情況下,您還需要裝飾器作為類型層次結構的一部分。
我會說這不是模式。
裝飾圖案
裝飾器模式用於擴展現有實現的行為。 以圖形窗口為例,您可能希望有一個帶滾動條的窗口。 然后你可以有一個類
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();
...
}
}
閱讀以下鏈接以獲取更多信息:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.