所以我得到了Address
课程:
class Address
{
private String streetAddress;
private int number;
private String postalCode;
private City city;
private State state;
private Country country;
}
我想让它的可读版本显示在网格列中。
实现这一目标的最佳和最简洁的方法是什么?
toString
内的Address
方法(我个人不喜欢这种方法,因为'toString'与地址没有直接关系)ReadableAddressFormatter
ReadableAddressFormatter
(Address
addressToFormat
)String getFormatted()
getFormmated
是静态的,接收Address
实例并返回字符串我正在寻找一个好的设计,专注于清洁代码,去耦和可维护性。
答案 0 :(得分:7)
所有这些方法都已被使用,并且没有办法提供“与上下文无关”的最佳实践。软件工程的最佳答案通常是“它取决于”。那就是说,让我们分析一下:
希望这会有所帮助,并且从一开始就考虑清洁代码,解耦和可维护性而感到荣幸。
有关行动原则#2的示例 - 使用Strategy Pattern,遵守Single Responsibility Principle,Open/Closed Principle并允许Inversion of Control via Dependency Injection - 比较以下内容方法(由@SteveJ慷慨提供):
public class Address {
private String streetAddress;
private int number;
private String postalCode;
private String city;
private String state;
private String country;
public String toLongFormat(){
return null; // stitch together your long format
}
public String toShortFormat(){
return null; // stitch together your short format
}
public String toMailingLabelFormat(){
return null; // stitch together your mailing label format
}
@Override
public String toString(){
return toShortFormat(); // your default format
}
}
}
使用这个(在“大多数正确的”Groovy中):
public interface AddressFormatter {
String format(Address toFormat)
}
public class LongAddressFormatter implements AddressFormatter {
@Override
public String format(Address toFormat){
return String.format("%sBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAH%n%s", toFormat.streetAddress, toFormat.postalCode)
}
}
public class ShortAddressFormatter implements AddressFormatter {
@Override
public String format(Address toFormat){
return String.format("%d", toFormat.number)
}
}
public class Address {
private String streetAddress;
private int number;
private String postalCode;
private String city;
private String state;
private String country;
public AddressFormatter formatter = new ShortAddressFormatter(); // just to avoid NPE
public void setFormatter(AddressFormatter fr) { this.formatter = fr; }
@Override
public String toString(){
return formatter.format(this); // your default format
}
}
def addrr = new Address(streetAddress:"1234 fun drive", postalCode:"11223", number:1)
addr.setFormatter(new LongAddressFormatter());
println "The address is ${addrr}"
addr.setFormatter(new ShortAddressFormatter());
println "The address is ${addrr}"
正如@SteveJ所观察到的那样:
“所以你有不同的格式”策略“,你可以切换 他们之间...我有这个想法,你会设置一次格式 并坚持下去...如果你想添加另一种格式 样式,你不必打开并重写地址类,但是 写一个新的单独样式,并在你想使用它时注入它。“
答案 1 :(得分:6)
.NET解决方案:
覆盖Object.ToString()
似乎是最合乎逻辑的解决方案。这样可以在以下情况下使用它:Console.WriteLine("Home Address: {0}", homeAddress);
如果您希望提供其他格式,则Address类应实现IFormattable
。
此外,您应该创建一个从IFormatProvider
和ICustomFormatter
实现的AddressFormatter类。
MSDN链接提供了非常好的放置示例(BinaryFormatter和AcctNumberFormat),但如果这些还不够,还要看一下这个好例子:PhoneFormatter
此外,如果你决定全力以赴并实现IFormattable和自定义IFormatProvider / ICustomFormatter,那么我建议让你的ToString()只使用默认提供者调用你的ToString(String格式,IFormatProvider formatProvider) 。这样你就可以解决本地化和地址类型(短,长等)等问题。
答案 2 :(得分:2)
使用toString
不需要在功能本身之外额外行李;似乎是最简单的解决方案。这是有原因的,对吗?
答案 3 :(得分:2)
通常我从数据层划分表示层。将它呈现给GUI在我看来与表示层有关,而不是数据层。
我建议你在表示层的某处放置一个函数,将地址转换为字符串。
数据的呈现与数据无关!
静态方法很好。 转换器类会更好,您可以为您的应用程序保留一个单独的实例,但如果您将应用程序从GUI移动到另一种格式的WEB,或者如果在一个窗口中您想要显示所有内容,则可以替换它或编写另一个实例另一个窗口,您只想显示以其他方式格式化的部分信息或信息。
您可以遵循几种模型,例如Microsoft WPF使用完全另一种方法,MVVM,模型视图视图模型,这将允许您从表示层划分业务逻辑中的数据层。
我通常在C#中覆盖ToString,在java中覆盖toString仅用于调试目的(提供可用于调试的字符串)或用于某种简单序列化到字符串,通常还在java中添加FromString(或fromString方法) 。一个例子是自定义类型,如Point,Vector,Matrix等。
谈论C#世界..
public class AddressToStringConverter
{
public virtual string ToString(Address address)
{
return address.Street + ", " + address.City
}
}
然后以你的形式(例如)。
AddressToStringConverter myConverter = new AddressToStringConverter();
public Address CurrentSelectedAddress { get { ... } }
public button1_click(object sender, EventArgs e)
{
button1.Text = myConverter.Convert(address);
}
如果您愿意,可以使用其他有用的界面,例如ITypeConverter
答案 4 :(得分:1)
toString()是最灵活和方便的,当您将Address类的对象与String组合时会被隐式调用,如System.out.println(“我的地址是”+ objectOfAddressClass)。
我可以想到不覆盖toString()的唯一原因是你需要改变格式。那么你需要不同的方法(如toMailingString()和toShortFormString()等)或参数化方法(如toMailingString(boolean useShortForm)或其他),但无论如何,toString()都不会删除它。 / p>
当然,你可以(并且应该)做到这两点。将toString()作为默认值,可能会调用您的一种特定格式方法,然后将其他辅助方法用于替代格式。
public class TestClass {
class City{};
class State{};
class Country{};
class Address {
private String streetAddress;
private int number;
private String postalCode;
private City city;
private State state;
private Country country;
public String toLongFormat(){
return null; // stitch together your long format
}
public String toShortFormat(){
return null; // stitch together your short format
}
public String toMailingLabelFormat(){
return null; // stitch together your mailing label format
}
@Override
public String toString(){
return toShortFormat(); // your default format
}
}
}
答案 5 :(得分:0)
我认为返回字符串的toString()
方法是最好的方法。如果你有一个地址实例,让我们说address
,那么address.toString()
显然是什么。 toString()
与Address
没有直接关联的事实并没有真正改变任何事情。
答案 6 :(得分:0)
您已使用Java标记了帖子,因此我将回答Java(更具体地说是Swing)。此任务通常是特定TableCellRenderer的任务。如果必须为其他可视组件使用相同的格式,我确实会在可实例化的类中提取格式(解决方案2)。这将允许子类在需要时自定义格式。