构建Java控制台程序的正确方法

时间:2014-11-14 15:55:14

标签: java oop language-concepts

我是80年代的老一辈程序员,精通C和Pascal。我对Java及其概念很陌生。在尝试使用OOP技术学习Java的新方法时,我对将应用程序放在一起的正确方法感到困惑。

我正在尝试使用以下规则构建基本程序。

一个组织拥有自己的内部图书馆。 Staff级是一般的,有姓名和电话。一些员工是图书管理员。其他人是成员。所以会员和图书管理员都是专门课程。我认为我们称之为在这种情况下继承或扩展。

现在我正在尝试构建输入等基本功能并打印成员记录。我正在尝试构建基于文本的菜单。也许以后我会考虑子菜单。现在它只是一个简单的菜单。

我不知道是否应该将菜单设为对象,但这就是我认为我会做的。

考虑到这一点,这就是我所做的。

我的主要计划:

public class Library extends Menus {
    public static void main(String[] args) {
        Menus Start = new Menus();
        Start.ShowMainMenu();

    }
}

StaffClass.java

public class StaffClass {
    private String Name;
    private String Phone;

    public void InputData() {
        Scanner UserInput = new Scanner(System.in);

        System.out.print("Enter staff name "); Name = UserInput.nextLine();
        System.out.print("Enter staff phone number "); Phone = UserInput.nextLine();

    }

    public void PrintData() {
        System.out.println("Name : " + Name);
        System.out.println("Phone : " + Phone);

    }
}//end StaffClass

Menus.java

public class Menus extends MemberClass {

    int c;
    public void ShowMainMenu() {
        Scanner ui = new Scanner(System.in);
        while(1==1) {
            System.out.println("Main menu");
            System.out.println("1. Add student");
            System.out.println("2. Display all");
            System.out.println("3. exit");
            System.out.print("Enter choice"); c = ui.nextInt();

            switch(c) {
                case 1 : getInputs(); /*System.out.println("option 1");*/ break;
                case 2 : ShowAllInfo(); break;
                case 3 : System.out.println("Leaving the program now..."); System.exit(0); break;
                default  : System.out.println("error.");
            }

        }

    }

}

MemberClass.java

public class MemberClass extends StaffClass {
    int TotalBooks;
    public void getInputs() {
        InputData();
        UpdateTotalBooks();
    }

    public void ShowAllInfo() {
        PrintData();
        System.out.println("total books taken = " + TotalBooks);
    }

    public void UpdateTotalBooks() {
        Scanner ui = new Scanner(System.in);

        System.out.print("Enter number of books "); TotalBooks = ui.nextInt();        

    }

}

这是我第一个将这么多课程放在一起的Java程序+菜单系统。

我的关键问题是,如果这是用Java组装程序的正确方法,还是有另一种方式。

请随时建议代码的最佳选项/更改。但我想保持概括和专业化的概念。

谢谢!

2 个答案:

答案 0 :(得分:3)

评论太长,但不是答案。

  1. 会有课程。希望他们中的很多人。
  2. 应遵循Java命名约定,例如,以小写字母开头的名称方法。
  3. StaffClass名称不佳,只需使用Staff
  4. 考虑以不同的方式为其提供输入:原样,Staff只能通过自己的输入方法填充。但是 数据如何进入Staff实例应该与Staff实际上完全无关。
  5. 没有"一种正确的方式"从其类中组装Java程序,甚至是一种正确的方法来分解责任。但Single Responsibility Principle很重要。同样重要的是,方法(以及可能的类)应始终在相同的抽象级别上运行。

答案 1 :(得分:2)

您过度使用类 - 类意味着表示数据类型,或者是静态方法(基本上只是函数)的持有者。但是,您正在使用类作为分发函数的方法,然后应用伪继承。此外,您继承了Menus 在同一个班级中设置Menus - 这没有任何意义。

换句话说,你不需要需要来使用继承和许多类。除了许多不称职的开发人员过度使用强制或建议过度使用类和继承的类之外,Java中没有任何东西。

功能,优选没有副作用/全局状态的功能,很多更容易推理和正确。而散布在父类链中的复杂状态变量是一个令人头痛的捷径。

我会使用简单的东西,例如:

public class Library {
    public static void main(final String[] args) {
        showMainMenu();
    }

    int totalBooks;

    public static void showMainMenu() {
        final Scanner ui = new Scanner(System.in);
        while (true) {
            System.out.println("Main menu");
            System.out.println("1. Add student");
            System.out.println("2. Display all");
            System.out.println("3. exit");
            System.out.print("Enter choice");

            switch (ui.nextInt()) {
                case 1:
                    getInputs();
                    /*System.out.println("option 1");*/
                    break;
                case 2:
                    showAllInfo();
                    break;
                case 3:
                    System.out.println("Leaving the program now...");
                    System.exit(0);
                    break;
                default:
                    System.out.println("error.");
            }
        }
    }

    public static void getInputs() {
        inputData();
        updateTotalBooks();
    }

    public static void showAllInfo() {
        printData();
        System.out.println("total books taken = " + totalBooks);
    }

    public static void updateTotalBooks() {
        System.out.print("Enter number of books ");
        totalBooks = new Scanner(System.in).nextInt();
    }
}

如果您需要在不同的模块中拆分它,请 NOT 使用继承。相反,创建类似StateDatabase类的东西,并在静态函数之间传递它,这些函数可以修改传入的数据,或者,如果你想要查看函数式编程和不可变数据结构的世界,返回数据的修改副本:

class State {
  // make these non-final if you want State to be mutable
  // (I'm too lazy to generate getters; and in Scala you don't have to)
  public final int totalBooks = 0;
  public final String someOtherState = "hello";

  public State(final int totalBooks, final String someOtherState) {
    this.totalBooks = totalBooks;
    this.someOtherState = someOtherState;
  }

  public State withTotalBooks(final int newValue) {
    return new State(newValue, someOtherState);
  }
  public State withSomeOtherState(final int newValue) {
    return new State(totalBooks, newValue);
  }
}

class App {
  public static void main(final String[] args) {
    State state = new State();
    // at the top-most level of the program, it's OK to use global state
    state = BookManager.updateNumBooks(state)
  }
}

class BookManager {
  public static State updateNumBooks(final State state) {
    return state.withTotalNumBooks(123);
  }

  // or, if State is mutable:
  public static void updateNumBooks(final State state) {
    // UI code here
    state.totalNumBooks = 123;
  }      
}

class HelloModule {
  public static State updateMsg(final State state) {
    // UI code
    return state.withSomeOtherState("hello world");
  }

  // or, if State is mutable:
  public static void updateMsg(final State state) {
    // UI code
    state.someOtherState = "hello world";
  }
}

// etc

并且,作为最后的评论:在Scala(甚至Frege)等简明的函数式编程JVM语言中,所有这些都会看起来很多更好。如果你必须留在Java上,至少要阅读一些关于Functional Programming的内容,以及如何从设计程序的方式中受益: