【发布时间】:2018-08-04 19:53:43
【问题描述】:
我想问一下装饰器模式是否适合我的需求,是另一种让我的软件设计更好的方法吗?
以前我有一个始终开启的设备。在下面的代码中,这就是 Device 类。现在,为了节省一些电池寿命,我需要将其关闭然后再次打开。我创建了一个 DeviceWithOnOffDecorator 类。我使用了装饰器模式,我认为这有助于避免对 Device 类进行修改。但是每次操作都有On和Off,感觉代码不符合DRY原则。
namespace Decorator
{
interface IDevice
{
byte[] GetData();
void SendData();
}
class Device : IDevice
{
public byte[] GetData() {return new byte[] {1,2,3 }; }
public void SendData() {Console.WriteLine("Sending Data"); }
}
// new requirement, the device needs to be turned on and turned off
// after each operation to save some Battery Power
class DeviceWithOnOffDecorator:IDevice
{
IDevice mIdevice;
public DeviceWithOnOffDecorator(IDevice d)
{
this.mIdevice = d;
Off();
}
void Off() { Console.WriteLine("Off");}
void On() { Console.WriteLine("On"); }
public byte[] GetData()
{
On();
var b = mIdevice.GetData();
Off();
return b;
}
public void SendData()
{
On();
mIdevice.SendData();
Off();
}
}
class Program
{
static void Main(string[] args)
{
Device device = new Device();
DeviceWithOnOffDecorator devicewithOnOff = new DeviceWithOnOffDecorator(device);
IDevice iDevice = devicewithOnOff;
var data = iDevice.GetData();
iDevice.SendData();
}
}
}
在这个例子中:我只有 GetData 和 SendData 两个操作,但在实际的软件中涉及很多操作,我需要将每个操作都包含在内开和关,
void AnotherOperation1()
{
On();
// do all stuffs here
Off();
}
byte AnotherOperation2()
{
On();
byte b;
// do all stuffs here
Off();
return b;
}
我觉得每个函数都用 On 和 Off 括起来是重复的,有没有办法改进呢?
编辑:另外,原始代码是用 C++ 编写的。我只是在这里用 C# 写的,以便能够更清楚地显示问题。
【问题讨论】:
-
嗯。您正在寻找的是一种在您对
On()和Off()的调用之间自动委托Device类方法的方法。不幸的是,Java 不允许您动态添加方法,因此您无法“即时”构建修饰版本。如果您想深入了解虚拟机的内部,可以使用自定义类加载器来完成......但这不是一个实际的解决方案。相反,您可能想查看面向方面的编程。一个简短的搜索显示 Android 对 AspectJ 有一些支持。从概念上讲,方面让您“挂钩”类的方法。 -
您好,感谢您的评论。但是,我忘了提一下,我是在 C++ 中实现的。在这种情况下,我只是使用了 C#,以便能够以更清晰的方式显示问题。
-
好吧,总是有 AspectC++,或者你可以解析
Device类头并为修饰的子类生成代码(将调用从Device委托给On()和Off()之间的版本),或者您可以硬着头皮为Device上的每个方法添加一个通用的“钩子”接口。然后您的 On/Off 子类可以安装用于打开和关闭电源的挂钩。至少 Device 中的钩子是通用的(不耦合到开/关功能)
标签: oop design-patterns decorator