在不破坏封装的情况下公开对象数据
本文关键字:对象 数据 情况下 封装 | 更新日期: 2023-09-27 18:22:30
良好的面向对象设计表明对象不应该公开其内部。在这种情况下,显示数据的最佳方式是什么?
例如,在控制台应用程序中调用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?
}
}
更新:我认为维护封装的最好方法是使用观察者模式(事件),但没有人提到它。这是比公开属性或方法结果更好的解决方案吗?
这取决于;
- 如果该值仅与该方法相关,则将其作为该方法的返回值
- 如果值与对象相关,则通过属性公开它
我怀疑是后者,所以:
public string Data { get { return data; } }
它只是一个访问器——例如,相当于java中的getData()
。这不是公开字段,但最终您的对象应该向信息公开一些API。这并不是一个完全的秘密。
您可以添加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; }
一些常见的方法:
- 为实例的某些通用文本表示重写ToString()(这可能反映了您想要的内部数据,也可能不反映,取决于细节和上下文)
- 如果根据某些特定的内部数据进行计算,则公开方法
- 公开getter以不可变地公开内部数据
- 如果只需要在调试时检查内部行为,请对类实例使用调试器和"监视"
在Foo类中生成属性
public string Data
{
get{return data;}
set{data = value;}
}
将数据视为属性。数据是一种不需要按照分配方式存储的属性。属性可以通过从/到其后备存储的转换来获得/存储。通过对私有存储变量内部结构的转换组合,可以获得多个属性。
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模式属性将封装需要在UI上执行的所有内部。演示者不应该在意视图的排列方式。并且视图不应该有任何过程或数据控制逻辑。
公共属性是促进封装的重要部分,以便只公开视图和演示者之间的契约。
一个健壮的UI设计将有一个服务器端状态机,它与客户端状态机通信,客户端状态机又对表示代理进行排序,而表示代理又要求展示UI视图属性。您的服务器根本不应该直接访问客户端视图。你的客户端状态机也不应该。您的演示者受客户端状态的指导,对UI视图提出要求。演示者只是发出对EDIT模式的需求。它不会干涉UI视图如何实现编辑模式。UI视图不应维护UI的状态。
这种解耦是为了便于单元测试,最重要的是,便于组件的模块化交换。这样,在你将浏览器UI换成移动UI后,你的演示顺序也会同样有效。由于移动UI将实现不同于浏览器UI的各种模式。或者桌面UI。
您需要进一步了解基于组件的设计和"封装"的概念。