在Martin Fowler在 Refactoring 中描述的气味Data Class
中,他建议如果我的班级中有一个收集字段,我应该封装它。
模式 Encapsulate Collection(208)表示我们应该添加以下方法:
并删除这些:
要确保此集合的任何更改都需要通过课程。
我应该重构每个具有此模式的集合字段的类吗?或者它取决于其他一些原因,如使用频率?
我现在在项目中使用C ++。
任何建议都会有所帮助。感谢。
答案 0 :(得分:2)
这些都是很好的问题,我的答案是:
我是否应该使用this重构具有集合字段的每个类 图案?
或者它取决于其他一些原因,如使用频率?
您可能已经预料到是/否答案,但这样的答案是不可能的。如上所述,使用您的常识并从上述观点来衡量您的解决方案。
我通常喜欢封装集合的想法。还将普通String
封装到命名的业务类中。当这些类在业务域中有意义时,我几乎总是。
我总是喜欢
public class People {
private final Collection<Man> people;
... // useful methods
}
当Collection<Man>
是业务类(域对象)时,通过普通Man
。或者我有时会这样做:
public class People implements Collection<Man> {
private final Collection<Man> people;
... // delegate methods, such as
@Override
public int size() {
return people.size();
}
@Override
public Man get(int index) {
// Here might also be some manipulation with the returned data etc.
return people.get(index);
}
@Override
public boolean add(Man man) {
// Decoration - added some validation
if (/* man does not match some criteria */) {
return false;
}
return people.add(man);
}
... // useful methods
}
或类似地我更喜欢
public class StreetAddress {
private final String value;
public String getTextValue() { return value; }
...
// later I may add more business logic, such as parsing the street address
// to street name and house number etc.
}
仅仅使用普通String streetAddress
- 因此我保持对未来任何基础逻辑变化的开放,并添加任何有用的方法。
但是,我不会在不需要时过度使用我的设计,因此我以及对普通集合和普通String
感到满意它更适合。
答案 1 :(得分:1)
我认为这取决于您正在开发的语言。因为已经存在只有C#和Java的接口。在C#中,我们有ICollection
,IEnumerable
,IList
。在Java Collection
,List
等
如果你的语言没有一个接口来引用一个集合,而不管它们的内部实现是什么,并且你需要拥有自己的那个类的抽象,那么这样做可能是个好主意。是的,你不应该直接修改集合,因为这完全违背了目的。
如果你告诉我们你正在开发哪种语言,那将会非常有帮助。当然,这是一种与语言无关的问题,但是那些熟悉该语言的人可能会向您推荐最佳实践,并且已经有了实现您所需要的方法。
答案 2 :(得分:1)
Encapsulate Collection背后的动机是减少集合所拥有的类与其客户的耦合。
每次重构都会尝试提高代码的可维护性,因此未来的更改会更容易。在这种情况下,例如,将集合类从向量更改为列表,更改所有客户端&#39;使用该类。如果使用此重构封装此内容,则可以更改集合而无需更改客户端。这遵循SOLID原则,dependency inversion principle:Depend upon Abstractions. Do not depend upon concretions.
您必须决定自己的代码库,这是否与您相关,这意味着您的代码库仍然在被更改并且必须进行维护(然后是,为每个类执行)或者不是(不,保留代码。)