java - 在类中创建实例或从外部获取对象,哪个是正确的?
问题描述
我研究了SOLID原理并为我提出了一个关于它的问题。你假设我们需要一个类中的Tea
对象Mug
,现在这比从类Tea
中创建一个实例Mug
或从外部通过Constructor
orsetter
方法传递更好。
哪个是真的?
例子:
class Mug {
private Tea tea;
public Mug(){
this.tea = new Tea();
}
public boolean isFull(){
return this.tea.value != 10;
}
}
或者
class Mug {
private Tea tea;
public Mug(Tea tea){
this.tea = tea;
}
// public void setTea(Tea tea){
// this.tea = tea;
// }
public boolean isFull(){
return this.team.value != 10;
}
}
利用:
public class Test {
static void main(String[] args){
Mug mug = new Mug();
//or
Mug mug = new Mug(new Tea());
}
}
哪一个更好?
注意:假设在我们的程序中Mug
只支持Tea
对象。
解决方案
你的两个案例都违反了 SOLID。
您的每个具体实现(具体类)应该只依赖于抽象。在您的情况下,茶不是抽象的。Mug 与 Tea 紧密耦合。下面是一种可能的编码方式。
public interface ITea{
//tea related methods which you think should be exposed to outside world. Also all implementation of ITea must support these method (L in SOLID)
}
public class Tea implements ITea{
// Implement the contract methods from ITea
}
public class Mug {
private ITea tea;
// Have constructor or setter to inject concrete implementation. Setter will provide you capability to modify behavioral at run time.
}
编辑: 1. 如果我们确定只有一种可能的茶实现。然后接口也更好,因为具体实现很难模拟,因此单元测试很困难。
- 避免使用枚举来设置类型。枚举注入 switch 案例,并且将来如果添加一个案例,所有这些 switch 案例都需要修改,从而导致违反 SOLID 中的 O。
如果添加案例,您必须修改现有代码,如果您忘记在某处添加案例,则会导致意外错误。(它违反了OCP。而不是枚举将逻辑放在特定的实现中,具有通用的接口和特定的实现)。此外,如果我们在枚举的各个实例中实现特定于案例的逻辑,那么枚举文件将变得巨大。相反,如果我们在实现公共接口的各个具体类中具有特定逻辑,则用户代码可以很容易,因为它可以以多态方式注入具体类。
ps这个答案是关于遵循原则的,并不总是可以这样做。违反原则是可以的,但我们必须知道我们正在违反它,并且有充分的理由这样做。
推荐阅读
- reactjs - redux - 如何在 [mapDispatchToProps] 中 [ref] 选择
- android - Android 检测您的应用程序是否在三星儿童模式下运行
- python - 在python中屏蔽(无效)断言
- java - MongoDB 一对多和多对一关系
- javascript - Firestore 用例:无法按主题标签和最新的优先搜索
- google-cloud-firestore - Cloud Firestore 上的写入速度
- powershell - Powershell - 仅当状态码 -ne 200 时,我将如何从 foreach 循环中返回 appname?
- r - 在增加和减少列的两个条件下对 r 中的数据框进行排序
- xml - 使用 Many2one 字段编写域
- masstransit - MassTransit Bus.Publish 调用 SendObserver