В последний день я прочитал много-много учебников и блогов о шаблоне MVC. Теперь я в значительной степени понимаю концепцию, но мне показалось, что в каждом учебнике была еще одна концепция для реализации этого шаблона в Java. Поэтому я решил написать свое собственное приложение, а затем попросить совета у более высококвалифицированных программистов. (Изучение - это что-то вроде моей вещи).
Поэтому я не хочу разглядывать много слов о своей первоначальной мысли, но я покажу вам свой код:
MainClass:
public class MainClass {enter code here
public static void main(String[] args){
MainController controller = new MainController();
controller.initView();
}
}
Класс контроллера:
public class MainController implements ActionListener{
private ExtractorStatics stat;
private MainView mainview;
private BusinessExtractor bExtractor;
private InfoboxTextPane infobox;
private BufferedImage logoGS;
public MainController(){
stat = new Statics();
model = new Model();
mainview = new MainView();
}
public void initView(){
if(mainview!=null){
mainview.setActionListener(this);
mainview.setItemListener(new ComboBoxItemListener(this));
mainview.setVisible(true);
}
}
@Override
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if(command.equalsIgnoreCase(stat.SCAN_ACTION_COMMAND)){
this.quickScanButtonAction();
}
}
private void quickScanButtonAction(){
infobox = mainview.getInfobox();
ProcessingInformation information = model.quickScan();
InputStream informationStream = information.getInformationStream();
BufferedReader infoReader = new BufferedReader(
new InputStreamReader(informationStream));
String line;
try {
while ((line = infoReader.readLine()) != null) {
infobox.appendLine(line);
}
infoReader.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("End reached");
}
else
infobox.appendLine("Bitte Eingabe überprüfen.");
}
public void comboBoxChanged() {
//do some fancy stuff
}
}
class ComboBoxItemListener implements ItemListener{
MainController mc;
public ComboBoxItemListener(MainController mc){
this.mc=mc;
}
@Override
public void itemStateChanged(ItemEvent e) {
mc.comboBoxChanged();
}
}
MainView Class:
public class MainView extends JFrame {
private static final long serialVersionUID = 559229524422932258L;
private JPanel contentPane;
private JTextField txt_stichwort,txt_loc;
private JButton btn_quickscan;
private JTable table;
private JLabel label;
public InfoboxTextPane txtpn_infobox;
private String lineSep;
private final JComboBox<String> combobox;
/**
* Create the frame.
*/
public MainView() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
lineSep=System.lineSeparator();
Statics stats=new Statics();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 800, 620);
contentPane = new JPanel();
contentPane.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
setContentPane(contentPane);
contentPane.setLayout(null);
txt_subject= new JTextField();
txt_stichwort.setBounds(88, 47, 318, 20);
pan_suche.add(txt_stichwort);
txt_stichwort.setColumns(10);
combobox = new JComboBox<String>();
combobox.setBounds(88, 16, 318, 20);
pan_suche.add(combobox);
combobox.setModel(new DefaultComboBoxModel(new String[] {"Item1", "Item2"}));
txt_loc = new JTextField();
txt_loc.setBounds(88, 79, 318, 20);
pan_suche.add(txt_loc);
txt_loc.setColumns(10);
btn_quickscan = new JButton("Quick Scan");
btn_quickscan.setActionCommand(stats.SCAN_ACTION_COMMAND);
btn_quickscan.setBounds(10, 23, 130, 30);
pan_dos.add(btn_quickscan);
//a few more buttons that have other action commands defined by statics
//more labels and other GUI components
}
public InfoboxTextPane getInfobox(){
return this.txtpn_infobox;
}
public String getSearchSubject(){
return this.txt_stichwort.getText();
}
public String getSearchLocation(){
return this.txt_loc.getText();
}
public String getSearchWebsite(){
return (String)this.combobox.getSelectedItem();
}
public JComboBox<String> getComboBox(){
return this.combobox;
}
public JLabel getLogoLabel(){
return this.label;
}
public void setActionListener(ActionListener al){
try {
btn_quickscan.addActionListener(al);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
public void setItemListener(ItemListener il){
this.combobox.addItemListener(il);
}
}
Модельный класс:
public class Model {
private ExecutorService exeService;
public Model(){
exeService =Executors.newCachedThreadPool();
}
public ProcessingInformation quickScan(){
QuickScanRoutine qs = new QuickScanRoutine();
Future<String> result = exeService.submit(qs);
return qs.getProcessingInformation();
}
}
Стандартный класс (по вызову):
public class QuickScanRoutine implements Callable<String> {
private ProcessingInformation pi;
private BufferedWriter writer;
public QuickScanRoutine(){
pi = new ProcessingInformation();
PipedOutputStream pos = new PipedOutputStream();
PipedInputStream pis;
writer = new BufferedWriter(new OutputStreamWriter(pos));
try {
pis = new PipedInputStream(pos);
pi.setInformationStream(pis);
} catch (IOException e) {
e.printStackTrace();
}
}
public ProcessingInformation getProcessingInformation(){
return this.pi;
}
@Override
public String call() throws Exception {
//ofcourse this isnt the real purpose of this Class but I want to 'demonstrate writing to the stream'
for(int i =0; i<100;i++){
writer.write("Hello");
writer.newLine();
writer.flush();
}
writer.close();
return "Routine has been executed sucessfully!";
}
}
Обработка информации:
public class ProcessingInformation {
PipedInputStream informationStream,resultDataStream;
public void setInformationStream(PipedInputStream info) {
this.informationStream = info;
}
public void setResultDataStream(PipedInputStream data){
//I will need this stream for further tasks
this.resultDataStream = data;
}
public InputStream getInformationStream(){
if(informationStream!=null){
return informationStream;
}
else
return null;
}
public InputStream getResultDataStream(){
if(informationStream!=null){
return informationStream;
}
else
return null;
}
}
Я попытался сократить код настолько, насколько это возможно, но попытался сохранить его в контексте, чтобы вы могли понять всю конструкцию. Мои главные вопросы:
Это будут мои основные вопросы, но я благодарен и открыт всем вашим советам.
Я согласен с ответом Абхи Беккерта на некоторые аспекты - как правило, следующее:
Кроме того, Контроллер должен знать что-либо о составе представления, поскольку это связано с контроллером и представлением. И эта связь будет означать, что вам нужно было изменить представление представления или, если на то пошло, предоставить пользователю выбор различных представлений данных, вам нужно было бы написать новый контроллер для каждого представления. Позвольте мне сделать это конкретным, указав пример.
Когда вы открываете документ Word в текстовом процессоре, таком как MS-Word, страница может иметь различные макеты, такие как "Портрет", "Пейзаж", "Печать" и "Html". В каждом из этих макетов видимые пользовательские элементы различны. Однако данные одинаковы. Следовательно, наиболее логичным способом решения этой проблемы было бы либо:
Я прошел через код, который вы публикуемые и определили, что ваш контроллер знает о содержании представления для например, MainController
называет в MainView.getinfobox()
.Based на объяснении выше, вы хотели бы изменить.
Что касается второго вопроса, связанного с отправкой данных с использованием PipedStream, я не вижу в этом ничего технически неправильного, поскольку поток также является контейнером данных. Но я лично не видел или не встречал до сих пор фрагмент кода или кода, который будет следовать этому шаблону.
Надеюсь это поможет
Я не программист на Java, но я хорошо знаю MVC:
Если мне кажется, что ваши классы моделей должны делать больше работы. Кажется, в вашем контроллере и в представлении есть какой-то код модели.
Кроме того, никогда не приемлемо, чтобы модель связывалась с чем угодно, кроме других частей модели.
То же самое касается представления - он должен только взаимодействовать с другими объектами представления.
Все коды связи поступают в контроллер позже. Модель и представление должны иметь произвольные обратные вызовы и т.д., Которые настраиваются и используются объектами в уровне контроллера.
Точка MVC должна сделать вашу модель и просматривать полностью независимо от остальной части вашего кода. Они должны иметь нулевые внешние зависимости.
Я думаю, что у меня что-то не так в моем понимании модельного класса. Теперь я думаю, что модель - это всего лишь данные, которые хотят представить представление. Но прежде, чем я подумал, что модель является бизнес-логикой моего приложения. Итак, теперь я понимаю:
Представление содержит все графические элементы и имеет экземпляр контроллера, поскольку представление должно реализовать контроллер в качестве слушателя для действий, выполняемых в форме. (Buttonclicks и т.д.). Но представление не должно содержать никакой логики, насколько это возможно.
Контроллер не должен содержать реальной логики, либо он просто обрабатывает действия в форме и вызывает методы в модели. Поэтому контроллер должен иметь экземпляр как представления, так и модели.
Модель содержит все данные, которые должны быть показаны в представлении, и вызывает методы бизнес-логики, чтобы манипулировать этими данными или выполнять другие внутренние процессы.
Я несколько других вопросов, что я ссылаюсь на шаблон MVC:
Я просмотрел код, который вы опубликовали, и определил, что ваш контроллер знает о содержимом представления, например, вызовы MainController в MainView.getinfobox(). Исходя из приведенного выше объяснения, вы хотели бы его изменить.
Означает ли это, что контроллер не должен манипулировать формой вообще? Теперь я думаю, что представление просто манипулирует собой данными, которые предоставляет модель, потому что представление "наблюдает" данные модели и чем само изменение. Это верно?