简体   繁体   English

OOP设计问题:集装箱或集装箱的责任?

[英]OOP design problem: responsibility in containee or container?

I focus a lot on making my software design flexible and reliable, and one of the key concepts to achieve this is encapsulation. 我专注于使我的软件设计灵活可靠,实现这一目标的关键概念之一就是封装。 Lately I have faced a special design problem and I can't argue (with myself) what is the best solution. 最近我遇到了一个特殊的设计问题,我不能(和我一起)争论什么是最好的解决方案。

A concrete example illustrating the problem: A device has an address (on a bus). 说明问题的具体示例:设备具有地址(在总线上)。 The device has multiple registers. 该设备有多个寄存器。 A register also has an address (inside the device - aka. virtual address/mapped address), so for example to write to a register on the device, you have to write (registerAddress, value) to the address of the device. 寄存器还有一个地址(在设备内部 - 也就是虚拟地址/映射地址),因此例如要写入设备上的寄存器,您必须将(registerAddress,value)写入设备的地址。 I can't decide where to put the functionality of reading/writing registers: 我无法决定在哪里放置读/写寄存器的功能:

1) a register should be able to read write itself, meaning it needs to know about the communication channel between the device and itself. 1)寄存器应该能够自己读写,这意味着它需要知道设备和它自身之间的通信通道。 This seems strange/wrong somehow, I can't explain why though.. 这似乎有点奇怪/错误,我无法解释为什么虽然..

2) The device reads/writes to/from registers. 2)器件读/写寄存器。 A register is just a placeholder for information (data, access rights etc) that the device can query/alter. 寄存器只是设备可以查询/更改的信息(数据,访问权限等)的占位符。 This also seems wrong because the responsibility of reading/writing a register should really be in the register (like a file knows how to read/write itself). 这似乎也是错误的,因为读/写寄存器的责任应该在寄存器中(就像文件知道如何读/写本身一样)。

What solution makes most sense and why? 什么解决方案最有意义,为什么? Maybe there is a completely different solution that makes more sense? 也许有一个完全不同的解决方案更有意义?

Solution 1 解决方案1

class Device
{
    private CommChan chan;
    private Register register1;
    private Register register2;
    ...

    public Device(int deviceAddress)
    {
        chan = new CommChan(deviceAddress);
        register1 = new Register(0x01, chan);
        ...
    }

    public void DoSomething()
    {
        register1.Write(0x22);
        byte b = register1.Read();
    }
}

class Register
{
    private int address;

    ...

    public Read()
    {
        chan.InitTransfer(address)
        ... // Other setup
        return chan.Read(address);
    }

    public Write()
    {
        chan.InitTransfer(address)
        ... // Other setup
        chan.Write(value);
    }
}

Solution 2 解决方案2

class Device
{
    private CommChan chan;

    public Device(int address)
    {
        chan = new CommChan(address);
    }

    public void DoSomething()
    {
        WriteRegister(0x01, 0x22);
        byte b = ReadRegister(0x01);
    }

    private byte ReadRegister(int address)
    {
        chan.InitTransfer(address)
        ... // Other setup
        return chan.Read(address);
    }

    private void WriteRegister(int address, int value)
    {
        chan.InitTransfer(address)
        ... // Other setup
        chan.Write(value);
    }
}

Driven to the logical extreme, a bus is an object by itself. 驱动到逻辑极端,总线本身就是一个对象。 Reading or writing a register is a bus operation, different busses have different ways to access a register. 读取或写入寄存器是总线操作,不同的总线有不同的方式来访问寄存器。 Create a bus interface with methods ReadRegister and WriteRegister. 使用ReadRegister和WriteRegister方法创建总线接口。

Overdoing this is certainly a consideration, I imagine the odds that you'll ever run this code on another type of bus are small. 过度使用这当然是一个考虑因素,我想你在其他类型的总线上运行此代码的可能性很小。

The question is really about "should Register be a separate entity?". 问题实际上是“应该注册成为一个独立的实体吗?”。 Well it's up to you. 嗯,这取决于你。 You need to answer question: why it's necessary a Register to be a class? 你需要回答一个问题:为什么注册成为一个类是必要的?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM