在不破坏封装的情况下公开对象数据

时间:2012-02-05 22:34:10

标签: c# oop encapsulation

良好的面向对象设计表明对象不应暴露其内部。鉴于这种情况,显示数据的最佳方式是什么?

例如,在控制台应用程序中调用DoSomethingToData后,如何显示数据字段?

public class Foo {
    string data;

    public void DoSomethingToData(string someParam) {
        .....
    }
}

class Program {
    static void Main(string[] items) {
        var foo = new Foo();
        foo.DoSomethingToData("blah");
        ..... // how do we write data field to console without breaking encapsulation?
    }
}

更新 我认为保持封装的最佳方法是使用观察者模式(事件),但没有人提到它。这是一个比暴露属性或方法结果更好的解决方案吗?

5 个答案:

答案 0 :(得分:5)

取决于;

  • 如果值仅与方法相关,则将其设为方法的返回值
  • 如果值与对象相关,则通过属性
  • 公开它

我怀疑是后者,所以:

 public string Data { get { return data; } }

这只是一个访问器 - 例如,相当于java中的getData()。这不会暴露字段,但最终您的对象应该将某些 API公开给信息。这并不是一个完整的秘密。

答案 1 :(得分:3)

您可以添加ToString方法(或类似方法)以提供适合记录到控制台的字符串表示。

public class Foo
{
    private string data;

    public void DoSomethingToData(string someParam) {
        .....
    }

    public override string ToString()
    {
        return string.Format("Foo data: {0}", data);
    }
}

这使得您的类的客户端清楚地知道除了调试/日志记录之外,数据字段的内容不打算在类外使用。


或者你可以私有一个允许直接(只读)访问私有字符串的公共getter属性,但请注意以这种方式提供这样的属性可能会导致使用Data字段的类的客户端除了记录之外的更多一般用途。

public string Data { get { return data; } }

最后一个选项是使用自动实现的属性并完全删除该字段(自动实现的属性将使用自己的支持字段):

public string Data { get; private set; }

答案 2 :(得分:1)

一些常见的方法:

  • 覆盖ToString()以获取实例的一般文本表示(这可能反映您所需的内部数据,取决于详细信息和上下文)
  • 如果从某些特定内部数据执行计算,则公开方法
  • 公开吸气剂以不可避免地暴露内部数据
  • 如果您只需要在调试
  • 时检查内部行为,请在类实例上使用调试器和'监视'

答案 3 :(得分:0)

在Foo类中创建属性

    public string Data
    {
        get{return data;}
        set{data = value;}
    }

答案 4 :(得分:0)

将数据视为属性。数据是不需要按照分配方式存储的属性。可以从/向其后备存储转换获得/存储属性。可以通过转换私有存储变量的内部结构来获得多个属性。

private double booTheBackingStore;
private int myfactor;

public String data{
  get{
    return "<data>"+booTheBackingStore*booTheBackingStore+"</data>";
  }

  set{
    String boo = parselTheXml(value);
    double booger;
    Double.tryParse(boo, out booger);
    booTheBackingStore = Math.sqrt(booger);
  }
}


public double dada{
  get{
    return exoTransform(booTheBackingStore, myfactor);
  }
  set{
    booTheBackingStore = endoTransform(value, myfactor);
  }
}

更多信息:

假设您的课程是一个网页视图,它具有编辑,浏览,插入,删除模式。对于每种模式,您的视图都必须重新安排/重新排列小部件。此外,您还必须重新应用样式。

从MVP的角度来看,您需要将您的演示文稿与视图分离。视图需要在公共属性方面暴露自己。因此set / get mode属性将封装需要在UI上执行的所有内部。演示者不应该关心视图如何自我安排。并且视图不应该有任何进程或数据控制逻辑。

公共属性是促进封装的重要部分,以便仅公开视图和演示者之间的契约。

强大的UI设计将具有服务器端状态机,该状态机与客户端状态机通信,而状态机又对表示代理进行排序,而后者又要求展示UI-View属性。您的服务器根本不应直接与客户端视图联系。您的客户端也不应该使用状态机。您的演示者由客户端的状态指示,以满足UI-View的要求。演示者仅仅发出对编辑模式的需求。它不会干涉UI-View如何实现编辑模式。 UI-View不应该维护UI的状态。

这种解耦是为了便于单元测试,最重要的是,模块化交换组件。因此,在将浏览器UI与移动UI交换后,您的演示序列也可以正常工作。由于移动UI将实现与浏览器UI不同的各种模式。或桌面用户界面。

您需要进一步了解基于组件的设计和“封装”的概念。