OO 设计建议 - toString
所以我得到了 Address
类:
class Address
{
private String streetAddress;
private int number;
private String postalCode;
private City city;
private State state;
private Country country;
}
我想获得它的可读版本,比如说,显示在网格列中。
实现此目的的最佳且简洁的方法是什么?
- 中的
toString
方法(我个人不喜欢这种方法,因为“toString”与地址不直接相关) Address
类 代码>ReadableAddressFormatterReadableAddressFormatter
(地址
addressToFormat
)- public
String getFormatted()
- 上一类,但
getFormmated< /code> 将是静态的,接收
Address
实例并返回字符串 - Other?请提出建议。
我正在寻找一个好的设计,同时关注干净的代码、解耦和可维护性。
So I got the Address
class:
class Address
{
private String streetAddress;
private int number;
private String postalCode;
private City city;
private State state;
private Country country;
}
And I want to get its readable version to, lets say, show in a grid column.
Whats the best and concise way to implement this?
toString
method inside classAddress
(I personally don't like this approach, as 'toString' is not directly related to an Address)- class
ReadableAddressFormatter
ReadableAddressFormatter
(Address
addressToFormat
)- public
String getFormatted()
- Previous class but
getFormmated
would be static, receiving theAddress
instance and returning the string - Other? Suggestions please.
I'm looking for a good design, focusing also in Clean Code, Decoupling and Maintainability.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
所有这些方法都已被使用,并且没有办法提供“上下文无关”的最佳实践。软件工程中的最佳答案通常是“视情况而定”。也就是说,让我们逐一分析:
希望这对您有所帮助,并感谢您从一开始就考虑了整洁代码、解耦和可维护性。
有关原则 2 实际应用的示例 - 使用策略模式,遵循单一职责原则,开放/封闭原则并允许通过依赖注入实现控制反转--比较以下方法(由 @SteveJ 慷慨提供):
与此方法(在“大部分正确”中) Groovy):
正如 @SteveJ 所观察到的:
All of these methods have been used, and there's no way to offer a "context independent" best practice. The best answer in Software Engineering is usually "it depends." That's said, let's analyze each:
Hope this helps, and kudos for thinking about Clean Code, Decoupling, and Maintainability from the beginning.
For an example of principle #2 in action--using the Strategy Pattern, adhering to the Single Responsibility Principle, the Open/Closed Principle and allowing for Inversion of Control via Dependency Injection-- compare the following approach (graciously provided by @SteveJ):
With this one (in "mostly correct" Groovy):
As @SteveJ has observed:
.NET 解决方案:
重写
Object.ToString()
似乎是最合乎逻辑的解决方案。这使得在以下情况下使用起来更加简洁:Console.WriteLine("Home Address: {0}", homeAddress);
如果您希望提供额外的格式,则地址类应实现
IFormattable
。另外,您应该创建一个从
IFormatProvider
和
ICustomFormatter
。MSDN 链接提供了很好的示例(BinaryFormatter 和 AcctNumberFormat),但如果这些还不够,还可以看看这个很好的示例:PhoneFormatter
此外,如果您决定全力以赴并实现 IFormattable 和自定义IFormatProvider/ICustomFormatter 那么我建议您的 ToString() 只需使用默认提供程序调用 ToString(String format, IFormatProvider formatProvider) 即可。这样您就可以考虑本地化和地址类型(短、长等)等问题。
.NET SOLUTION:
Overriding
Object.ToString()
seems to be the most logical solution. This makes it clean to use in situations such as:Console.WriteLine("Home Address: {0}", homeAddress);
If you wish to provide additional formatting, the Address class should implement
IFormattable
.Also, you should create an AddressFormatter class that implements from
IFormatProvider
andICustomFormatter
.The MSDN links provide very well put examples (a BinaryFormatter and a AcctNumberFormat), but if those aren't enough also look at this good example: PhoneFormatter
Additionally, if you do decide to go full out on this and implement IFormattable and a custom IFormatProvider/ICustomFormatter then I'd suggest having your ToString() simply call to your ToString(String format, IFormatProvider formatProvider) with a default provider. That way you can account for things like localization and types of addresses (short, long, etc).
使用 toString 不需要函数本身之外的额外负担;似乎是最简单的解决方案。它的存在是有原因的,对吧?
Using
toString
requires no additional baggage outside the function itself; seems like the simplest solution. It's there for a reason, right?通常我将表示层与数据层分开。在我看来,将其呈现给 GUI 似乎与表示层相关,而不是数据层。
我建议您在表示层中的某个位置放置一个函数,将地址转换为字符串。
数据的呈现与数据无关!
静态方法很好。
转换器类会更好,您可以为应用程序保留一个实例,但如果您要将应用程序从 GUI 移动到另一种格式的 WEB,或者如果您想在一个窗口中显示所有内容,则可以替换它或编写另一个实例。另一个窗口您只想显示部分信息或以其他方式格式化的信息。
您可以遵循多种模型,例如 Microsoft WPF 使用完全另一种方法,即 MVVM(模型视图视图模型),它允许您很好地将数据层、业务逻辑和表示层分开。
我通常会重写 C# 中的 ToString 或 java 中的 toString,仅用于调试目的(呈现可用于调试的字符串)或用于某种简单的字符串序列化,通常还会放置 FromString(或 java 中的 fromString 方法)。一个例子是自定义类型,如点、向量、矩阵等。
谈论 C# 世界..
然后以您的形式(例如)。
如果您愿意,您可以实现其他有用的接口,例如 ITypeConverter
Usually i divide presentation layer from data layer. Presenting it to a GUI seems to me something related to the presentation layer, not the data layer.
I would suggest you to put a function somewhere in your presentation layer that will convert the address to string.
Presentation of data is not related to data!
A static method is good.
A converter class would be better, you can keep one single instance for your application but you can replace it or write another if you are moving your application from GUI to WEB with another format, or if in one window you want to show everything and in another window you want to show only part of the informations or informations formatted in another way.
There are several model you can follow, for example Microsoft WPF uses totally another approach, the MVVM, Model View View Model, that will allow you to divide very well data layer from business logic from presentation layer.
I usually override ToString in C# or toString in java only for debugging purposes (presenting a string that i can use for debug) or for some kind of simple serialization to string, usually putting also a FromString (or fromString method in java). One example is custom types like Point, Vector, Matrix and so on.
Talking about C# world..
Then in your form (for example).
If you want you can imlpement other useful interfaces like for example ITypeConverter
toString() 是最灵活和方便的,当您将 Address 类的对象与 String 组合时,会隐式调用,如 System.out.println("My address is " + objectOfAddressClass)。
我能想到不重写 toString() 的唯一原因是如果您需要更改格式。然后,您将需要不同的方法(如 toMailingString() 和 toShortFormString() 等)或参数化方法(如 toMailingString(boolean useShortForm) 或其他),但无论哪种方式, toString() 都不会削减它。
当然,您可以(并且应该)两者都做。将 toString() 作为默认值,可能会调用您的特定格式方法之一,然后使用其他辅助方法来实现替代格式。
toString() is the most flexible and convenient, being implicitly called when you combine an object of the Address class with a String, as in System.out.println("My address is " + objectOfAddressClass).
The only reason I can think of to not override toString() is if you need to alter the formatting. Then you would need different methods (as in toMailingString() and toShortFormString() and so on) or a parameterized method (as in toMailingString(boolean useShortForm) or whatever), but either way, toString() won't cut it.
Of course, you can (and should) do both. Have toString() as your default, probably calling one of your specific format methods, and then have your other helper methods for alternate formats.
您已经用 Java 标记了您的帖子,所以我将回答 Java(更具体地说,是 Swing)。此任务通常是特定 TableCellRenderer 的任务。如果其他可视组件必须使用相同的格式,我确实会在可实例化的类中提取格式(解决方案 2)。这将允许子类根据需要自定义格式。
You've tagged your post with Java, so I'll answer for Java (and Swing, more specifically). This task is normally the task of a specific TableCellRenderer. If the same format must be used for other visual components, I would indeed extract the formatting inside an instantiatable class (solution 2). This would allow subclasses to customize the format if needed.
我认为返回字符串的
toString()
方法是最好的方法。如果您有一个 Address 实例,比如说address
,那么address.toString()
的作用就很明显了。toString()
与Address
不直接关联这一事实并没有真正改变任何东西。I think that a
toString()
method that returns a string is your best approach. If you have an Address instance, let's sayaddress
, then it is obvious whataddress.toString()
does. The fact thattoString()
isn't directly associated withAddress
doesn't really change anything.