Gil*_*ian 6 java design-patterns software-design
我的程序从外部源获取信息(可以是文件,数据库或我将来可能决定的任何其他内容).
我想定义一个具有我所有数据需求的接口,以及实现它的类(例如,一个用于从文件获取数据的类,另一个用于DB的数据等).
我希望我的项目的其余部分不关心数据的来源,也不需要创建任何对象来获取数据,例如调用"DataSource.getSomething();"
为此,我需要DataSource包含接口类型的变量,并使用其中一个具体实现对其进行初始化,并将其所有方法(来自接口)公开为静态方法.
因此,假设接口名称为K,具体实现为A,B,C.
我今天这样做的方式是:
public class DataSource {
private static K myVar = new B();
// For **every** method in K I do something like this:
public static String getSomething() {
return myVar.doSomething();
}
...
}
Run Code Online (Sandbox Code Playgroud)
这是非常糟糕的,因为我需要复制接口的所有方法并使它们静态,因此我可以将它委托给myVar,以及许多其他明显的原因.
这样做的正确方法是什么?(也许它有一个设计模式?)
**注意 - 因为这将是许多其他项目的支柱,我将使用来自数千(如果不是数万)代码行的这些调用,我坚持像"DataSource.getSomething();"那样保持简单,我不要像"DataSource.getInstance().getSomething();"**
编辑:我在这里提供使用像Guice这样的DI框架,这是否意味着我需要在我的所有项目中的每个入口点(即"主"方法)中添加DI代码,或者有一种方法可以执行一次所有项目?
使用数据源的类应该通过接口访问它,并在构造时提供给类的正确实例.
所以首先要做DataSource一个界面:
public interface DataSource {
String getSomething();
}
Run Code Online (Sandbox Code Playgroud)
现在具体实现:
public class B implements DataSource {
public String getSomething() {
//read a file, call a database whatever..
}
}
Run Code Online (Sandbox Code Playgroud)
然后你的调用类看起来像这样:
public class MyThingThatNeedsData {
private DataSource ds;
public MyThingThatNeedsData(DataSource ds) {
this.ds = ds;
}
public doSomethingRequiringData() {
String something = ds.getSomething();
//do whatever with the data
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在代码中的其他位置实例化此类:
public class Program {
public static void main(String[] args) {
DataSource ds = new B(); //Here we've picked the concrete implementation
MyThingThatNeedsData thing = new MyThingThatNeedsData(ds); //And we pass it in
String result = thing.doSomethingThatRequiresData();
}
}
Run Code Online (Sandbox Code Playgroud)
如果你想获得花哨的话,你可以使用像Spring或Guice这样的依赖注入框架来完成最后一步.
加分点:在您的单元测试中,您可以提供DataSource的模拟/存根实现,而您的客户端类将更加明智!