我继承了一些代码,其中特定命名空间中的每个对象都包含模块中的其他对象作为数据字段。 通常,这些引用在创建对象时传递给构造函数。 这会导致很多对象包含对创建它们的对象的引用,并将它们存储为数据字段。
例如,有一个包装器对象包裹下层。此包装器对象包含上层设备对象的列表。但是每个上层设备对象都包含对包装器的引用,它需要将其传递给它创建的其他对象。 然后,这些其他对象使用包装器对象来调用较低层。
只有一个包装器对象,它在其他对象的构造函数中传递,但它不是正式的单例。
下面的(简化)代码概述了它的外观:
using System;
class UpperLayerManager
{
LowerLayerWrapper wrapperObject = new LowerLayerWrapper();
UpperLayerManager()
{
wrapperObject.ULM = this;
}
void GetDevices()
{
wrapperObject.GetDevices();
}
}
class UpperLayerDevice
{
LowerLayerWrapper wrapperObject;
UpperLayerOtherClass otherClass;
UpperLayerDevice(LowerLayerWrapper wrapper)
{
this.wrapperObject = wrapper;
this.otherClass = new UpperLayerOtherClass(wrapperObject);
}
//UpperLayerDevice currently doesn't make any calls into the lower layer
// - the UpperLayerManager makes all device-related
//calls via the LowerLayerWrapper.
}
class UpperLayerOtherClass
{
LowerLayerWrapper wrapperObject;
UpperLayerOtherClass(LowerLayerWrapper wrapper)
{
this.wrapperObject = wrapper;
}
void SomeOtherFunction()
{
this.wrapperObject.CallLowerLayer();
}
}
class LowerLayerWrapper
{
List<UpperLayerDevice> upperLayerDeviceList;
UpperLayerManager ULM
{
get;
set;
}
void GetDevices()
{
UpperLayerDevice dev = new UpperLayerDevice(this);
//some calls to the lower layer here....
upperLayerDeviceList.Add(dev);
}
void CallLowerLayer()
{
//here, some code that calls into the lower layer
}
}
我想整理这个命名空间中对象之间的当前耦合。
我现在想到的是:
1.在某些情况下,使用类似于Brady的this SO question解决方案的解决方案,例如,只能通过创建并保存它们的LowerLayerWrapper对象访问UpperLayerDevice对象。
或
2.使每个对象实现一个接口,供模块中的其他对象使用,而不是将它们全部包含在一起作为数据字段。看起来像是矫枉过正,通常我只是使用软件模块之间的接口
或
3.创建仅创建一次单例的对象,并让其他对象访问单例,而不是将引用传递给构造函数。这减少了需要传递的对象引用的数量,但是鼓励单身意大利面?
或
4.将类拆分为较小的类,例如拆分包装器并创建某种设备列表保持器对象,这样包装器对象就不需要被其他所有对象引用。我已经拆分了一些与包装器无关的包装器功能,从而减少了对包装器对象的调用次数。这实际上并没有减少需要传递的对象数量,但它确实可以防止到处弹出无处不在的对象。
或
5.什么都不做,去钓鱼(但是当每个物体相互依赖于其他物体时,我很难控制通过模块的信息流)。
显然,我需要使用当前的解决方案,而不是从头开始撕掉它。
前进的最佳方式是什么?非常感谢您的指导。
答案 0 :(得分:1)
解耦类有很多模式。在您的情况下,发布商订阅者模式可以解决问题。
考虑实施消息总线。这会破坏你当前的情况,但它会给你很好的解耦。
假设您要致电GetDevices
。您可以向消息总线发送消息(可能使用标识符作为参数),而不是调用实际的wrapperobject的GetDevices,并接收带响应的回调。
您可以使用“软”标识符(如整数或字符串)指向正确的对象(或图层),而不是将“硬”指针传递给接口。