为其他开发人员设计用于java的类
我立即看到以下问题: -开发人员必须在getOutput之前先调用read。他无法凭直觉知道这一点,这可能是一个糟糕的设计 因此,我决定修复代码并编写如下内容为其他开发人员设计用于java的类,java,Java,我立即看到以下问题: -开发人员必须在getOutput之前先调用read。他无法凭直觉知道这一点,这可能是一个糟糕的设计 因此,我决定修复代码并编写如下内容 CSVReader reader = new CVSReader(new FileInputStream("test.csv"); reader.read(); read.getOutput(); 还是这个 public List<String> getOutput() { if(output==null) thro
CSVReader reader = new CVSReader(new FileInputStream("test.csv");
reader.read();
read.getOutput();
还是这个
public List<String> getOutput() {
if(output==null)
throw new IncompleteStateException("invoke read before getoutput()");
return Collections.unmodifiableList(output);
}
public CSVReader(InputStream input) {
read(); //throw runtime exception
}
public List read()引发IOException{
//读取并创建输出列表。
//返回列表
}
实现目标的好方法是什么?对象状态是否应始终定义良好从来没有一种状态是不定义“输出”的,所以我应该创建输出作为构造函数的一部分?或者,该类是否应该通过在发现未定义“输出”时调用“读取”并仅抛出运行时异常来确保创建的实例始终有效?这里的好方法/最佳实践是什么 我建议您将类尽可能小,同时删除
getOutput()
方法
其想法是让一个类读取CSV文件并返回一个表示结果的列表。为了实现这一点,您可以公开一个read()
方法,该方法将返回一个列表
比如:
public List<String> read() throws IOException {
//read and create output list.
// return list
}
公共类CSVReader{
私有最终输入流输入;
公共CSVReader(字符串文件名){
this.input=新文件输入流(文件名);
}
公共列表读取(){
//在此处执行实际读数
}
}
您有一个定义良好的类,需要维护一个小接口,CSVReader
的实例是不可变的。我建议您将类尽可能小,同时删除getOutput()
方法
其想法是让一个类读取CSV文件并返回一个表示结果的列表。为了实现这一点,您可以公开一个read()
方法,该方法将返回一个列表
比如:
public List<String> read() throws IOException {
//read and create output list.
// return list
}
公共类CSVReader{
私有最终输入流输入;
公共CSVReader(字符串文件名){
this.input=新文件输入流(文件名);
}
公共列表读取(){
//在此处执行实际读数
}
}
您有一个定义良好的类,需要维护一个小接口,CSVReader
的实例是不可变的
第一种方法剥夺了API的一些灵活性:在进行更改之前,用户可以在预期出现异常的上下文中调用read()
,然后调用getOutput()
exception free()
任意次数。您的更改强制用户在以前不需要的上下文中捕获选中的异常
第二种方法是首先应该如何做:因为调用read()
是调用getOutput()
的先决条件,所以当用户“忘记”调用read()
时,类有责任“捕获”用户
第三种方法隐藏了IOException
,这可能是要捕获的合法异常。没有办法让用户知道是否要抛出异常,这在设计运行时异常时是一种不好的做法
问题的根本原因是该类有两个相互正交的职责:
- 读取CSV,以及
- 存储读取的结果以供以后使用
如果您将这两项职责相互分离,您将得到一个更干净的设计,在该设计中,用户将不会对他们必须调用的内容和顺序产生混淆:
public class CSVReader {
private final InputStream input;
public CSVReader(String filename) {
this.input = new FileInputStream(filename);
}
public List<String> read() {
// perform the actual reading here
}
}
接口CSVData{
List getOutput();
}
CSVReader类{
公共静态CSVData读取(InputStream输入)引发IOException{
...
}
}
您可以使用工厂方法将这两个类组合成一个类:
interface CSVData {
List<String> getOutput();
}
class CSVReader {
public static CSVData read(InputStream input) throws IOException {
...
}
}
类CSVData{
私有CSVData(){//无用户实例化
}
//获取数据是无异常的
公共列表getOutput(){
...
}
//创建实例需要工厂调用
公共静态CSVData读取(InputStream输入)引发IOException{
...
}
}
第一种方法剥夺了API的一些灵活性:在进行更改之前,用户可以在预期出现异常的上下文中调用read()
,然后调用getOutput()
exception free()
任意次数。您的更改强制用户在以前不需要的上下文中捕获选中的异常
read()
是调用getOutput()
的先决条件,所以当用户“忘记”调用read()
时,类有责任“捕获”用户IOException
,这可能是要捕获的合法异常。没有办法让用户知道是否要抛出异常,这在设计运行时异常时是一种不好的做法- 读取CSV,以及
- 存储读取的结果以供以后使用
public class CSVReader {
private final InputStream input;
public CSVReader(String filename) {
this.input = new FileInputStream(filename);
}
public List<String> read() {
// perform the actual reading here
}
}
接口CSVData{
List getOutput();
}
CSVReader类{
公共静态CSVData读取(InputStream输入)引发IOException{
...
}
}
您可以使用工厂方法将这两个类组合成一个类:
interface CSVData {
List<String> getOutput();
}
class CSVReader {
public static CSVData read(InputStream input) throws IOException {
...
}
}
类CSVData{
私有CSVData(){//无用户实例化
}
//获取数据是无异常的
公共列表getOutput(){
...
}
//创建实例需要工厂调用
公共静态CSVData读取(InputStream输入)引发IOException{
...
}
}
拥有getOutputpublic List<String> getOutput() {
if (output == null) {
try {
output = read();
} catch (IOException) {
//here you either wrap into your own exception and then declare it in the signature of getOutput, or just not catch it and make getOutput `throws IOException`
}
}
return Collections.unmodifiableList(output);
}