Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.73/48: Рейтинг темы: голосов - 48, средняя оценка - 4.73
169 / 66 / 15
Регистрация: 24.03.2013
Сообщений: 467
Записей в блоге: 1

Правильное проектирование классов или как гуру это делают?!

06.10.2013, 21:49. Показов 9637. Ответов 50
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте форумчане, есть вопрос на который ввиду моей квалификации пока ответить не могу:

Есть вот такое задание
Кликните здесь для просмотра всего текста

Планировщик задач
Краткое описание
Написать программу, которая выполняет основные функции планировщика задач. Взаи-модействие с пользователем осуществляется через консоль.
Детальное описание
Планировщик задач состоит из журнала задач, пользовательского интерфейса для добав-ления и удаления задачи, а также системы оповещения пользователя о каком-то событии, т.е. в назаначенное в планировщике время должно происходить нечто, говорящее пользо-вателю о том, что у него запланирована некоторая задача (см. ниже).
Журнал задач должен храниться на диске и загружаться при запуске программы, а также сохраняться при выходе. Формат файла может быть произвольный, по желанию можно использовать XML.
В качестве пользовательского интерфейса выступает консоль. Определенными команда-ми пользователь может удалять запланированные задачи, добавлять новые с указанием необходимых параметров (см. пункт ниже).
Параметры планируемой задачи:
- название
- описание
- время (дата) оповещения
- контакты
Реализация планировщика должна быть выполнена по следующим принципам. Функцио-нал, реализующий работу с журналом задач, пользовательским интерфейсом и системой оповещения а также сам журнал задач, должен находиться в различных классах. Т.е. поль-зовательский интерфейс в отдельном классе, работа с журналом задач в отдельном, сам журнал тоже в отдельном и система оповещения в отдельном. Эти классы могут общаться между собой через интерфейсы, но при этом ни один из них не должен реализовывать ло-гику другого.
Требования
(* помечены обязательные требования)
1. Реализация Планировщика задач должна соответствовать указанным выше принци-пам.*
2. Интуитивно понятный интерфейс работы с пользователем.*
3. Наличие функций добавления и удаления задач с сохранением их в общий журнал за-дач на диск.* (+ доп баллы за использование формата XML)
4. Система оповещения пользователя.* (+ доп баллы за использование Swing, + доп бал-лы за доп. функциональность с «завершить» или «отложить» задачу)
5. Программный код должен удовлетворять Code Conventions и снабжен JavaDoc.
Модификации задания
1. Использование различных систем оповещения (базовая, звуковой сигнал + вывод в консоль, запуск другой программы, написанной на Java).
2. Формат хранения журнала задач на диске: текстовый файл, сериализованные объекты, XML, сжатый текстовый файл (zip).


Вопросов у меня достаточно, хотелось бы разобраться во всех вопросах

Просьба админам не банить , я понимаю, что один вопрос - одна тема, но все же это все разделять на подвопросы было бы глупо.

Вопрос номер 1:
Какие классы должны быть реализованы, и что в них должно храниться?

Вот мои соображения

Класс TaskManager
+main() void;
+serialize(Journal, File) void;
+deserialize(File) Journal;
-make(Operaion) void;

Класс Journal implements Serializable
+getTasks() List<Task>;
+getCountTask() int;
+addTask(Task) void;
+deleteTask(Task) void;
+loadTasksFromXML(File) void;
+saveTasksToXML(file) void;

Класс UserInterface
+showMessage(String message) void;
+showMenu() void;
+getOperations(Scanner) Operation;
+loadFromXmlFile(Journal, String path) void; - просто вызывается функция loadTasksFromXML у journal'a
+showAllTasks(List<Task>) void;
+deleteTask(List<Task>, Scanner) void;
+deleteAllTasks(List<Task) void;
+saveJournalToXML(Journal, String path) void;
+addTask(Journal, Scanner)
-getTask(Scanner) Task; - этот метод нужен для того, чтобы сформировать готовый Таск от введенных пользователем данных

Класс Task
+getName() String;
+getContacts() String;
+getDate() Date;
+getDescription() String;
+setName(String) void;
+setContacts(String) void ;
+setDate(Date) void ;
+setDescription(String) void ;
+Override toString() String;

Enum Operations
+convertFromInt(int i) Operations;
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public enum Operations {
    ShowAllTasks,
    AddTask,
    DeleteTask,
    DeleteAllTasks,
    Serialize,
    SaveToXML,
    SaveAs,
    LoadFromXmlFile,
    Exit;
 
    static Operations convertFromInt(int i){ 
        switch(i){
            case 1: return Operations.ShowAllTasks;
            case 2: return Operations.AddTask;
            case 3: return Operations.DeleteTask;
            case 4: return Operations.DeleteAllTasks;
            case 5: return Operations.Serialize;
            case 6: return Operations.SaveToXML;
            case 7: return Operations.SaveAs;
            case 8: return Operations.LoadFromXmlFile;
            case 0: return Operations.Exit;
 
            default:
                throw new IllegalArgumentException("Данного действия"
                            + " нет в списке");
        }
    }
};
Вопрос номер 2
Почему при сериализации в записываемый файл записывается намного больше информации чем фактически хранится в памяти?

Вопрос номер 3
Почему десериализация не работает, выкидывается ошибка "writing aborted. NotSerializableException". Сериализуемый класс же у меня имплементит интерфейс Serializable?

Вопрос номер 4 - холиварный
Как и где можно мой код улучшить (оптимизировать, подкорректировать, переписать)

Спасибо


Собственно мой код: Если кто хочет покритиковать мой код - буду только рад(хотелось бы еще рекомендации как можно это дело переписать)
TaskManager
Кликните здесь для просмотра всего текста

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package ru.junior_progger;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Scanner;
 
public class TaskScheduler {
    private static Journal journal = null;
    private static UserInterface ui = null;
    private static Scanner sc = new Scanner(System.in);
    private static String default_xml_file_name = "journal.xml";
    private static File default_tsf_file = null;
    
    public static void main(String[] args) {
        System.out.println("Планировщик задач");
 
        ui = new UserInterface();
        journal = new Journal();
        
        try{
            default_tsf_file = new File("E:\\journal.tsf");
            if(true == default_tsf_file.exists())
                journal = deserialization(default_tsf_file);
            if(false == default_tsf_file.exists())
                default_tsf_file.createNewFile();
            
        } catch(IOException e){
            ui.showMessage("Произошла ошибка\n" + e.getMessage());
        } catch(ClassNotFoundException e){
            ui.showMessage("Произошла ошибка\n" + e.getMessage());
        }
        
        ui.showMessage("В списке " + journal.getTasks().size() + " cобытий");
        
        Operations op = null;
        do
        {   
            ui.showMenu();
            op = ui.getOperation(sc);
            if(op == Operations.Exit){ 
                ui.exit();
                return;
            }
            make(op);
            
        } while(Operations.Exit != op);
    }
 
    private static void make(Operations operation){
        switch(operation){
            case AddTask : ui.addTask(sc, journal); break;
            case DeleteTask: ui.deleteTask(journal.getTasks(), sc); break;
            case DeleteAllTasks: ui.deleteAllTasks(journal); break;
            case SaveToXML: ui.saveJournalToXML(journal, default_xml_file_name); break;
            case Serialize : {
                ui.showMessage("Сохранение в файл формата программы ");
                try {
                    serialize(journal, default_tsf_file);
                } catch (IOException e) {
                    ui.showMessage("Произошла ошибка при сохранении файла\n"
                            + e.getMessage());
                }
            } break;
            case SaveAs: ui.saveAs(journal); break;
            case ShowAllTasks: ui.showAllTasks(journal.getTasks()); break;
            case LoadFromXmlFile: ui.loadFromXmlFile(journal, default_xml_file_name); break;
            case Exit : ui.exit();
            default:
                throw new IllegalArgumentException("Неизвестное действие");
        }
    }
    
    private static  void serialize(Journal journal, File file) throws IOException{
        FileOutputStream fos = new  FileOutputStream(file);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(journal);
        oos.flush();
        oos.close();
    }
   
    private static Journal deserialization(File file)
            throws IOException, ClassNotFoundException{
        if(file != null && true == file.exists()){
            FileInputStream fis = new FileInputStream(file);
            ObjectInputStream ois = new ObjectInputStream(fis);
            
            return (Journal) ois.readObject(); 
        } else
            throw new FileNotFoundException("Не удается найти указанный файл");
    }
}


Journal (xml - парсер не полностью реализован!)
Кликните здесь для просмотра всего текста

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package ru.junior_progger;
 
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
 
import org.xml.sax.SAXException;
 
public class Journal implements Serializable{
    private static final long serialVersionUID = 1L;
    private List<Task> tasks = null;
 
    public Journal(){
        this.tasks = new ArrayList<>();
    }
 
    public int getCountTasks(){
        return this.tasks.size();
    }
    
    /**
     * Данная функция добавляет переданную аргументом задачу в 
     * внутренний список задач. 
     * Событие произошедшее в прошлом или null значение в список 
     * не добавляется.
     * 
     * @param task - добавляемая задача
     */
    public void add(Task task) throws IllegalArgumentException {
 
        if(task == null)
            throw new NullPointerException();
 
        // Если событие уже прошло - добавление не происходит
        if(task.getTime().after(new Date()))
            this.tasks.add(task);
        else
            throw new IllegalArgumentException("Некорректное событие! "
                + "Событие уже произошло!");
    }
 
    /**
     * Данная функция удаляет переданную аргументом задачу из 
     * внутреннего списка задач.
     * Если удаляемой задачи в списке нет - удаление не происходит,
     * т.е. функция ничего не делает.
     * 
     * @param task - Задача которую нужно удалить
     */
    public void delete(Task task){
        if(task != null){
            this.tasks.remove(task);
        }
    }
 
    public List<Task> getTasks() {
        return tasks;
    }
 
    public void clear(){
        this.tasks.clear();
    }
   
    public void loadFromXML(String path)throws IOException, IllegalArgumentException,
        ParserConfigurationException, SAXException{
        File xmlFile = new File(path);
        if(xmlFile.exists()){
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser sp = spf.newSAXParser();
            SaxHandler handler = new SaxHandler();
            
            sp.parse(xmlFile, handler);
            
            this.tasks.addAll(handler.getTasks());
        }
    }
    
    public void saveToXML(String path) throws IOException {
        File file = new File(path);
        FileWriter fw = null;
        try{
            fw = new FileWriter(file);
            fw.write("<?xml version = \"1.0\"?>\n");
            fw.write("<journal>\n");
            fw.write("\t<tasks>\n");
            
            for(int i =0 ; i < this.tasks.size(); i++){
                StringBuilder sb = new StringBuilder();
                Task task = this.tasks.get(i);
                sb.append("\t\t<task>\n");
                
                sb.append("\t\t\t<name>");
                sb.append(task.getName());
                sb.append("</name>\n");
                
                sb.append("\t\t\t<description>");
                sb.append(task.getDescription());
                sb.append("</description>\n");
                
                
                sb.append("\t\t\t<contacts>");
                sb.append(task.getContacts());
                sb.append("</contacts>\n");
                
                sb.append("\t\t\t<date>");
                sb.append(task.getTime().toString());
                sb.append("</date>\n");
                
                sb.append("\t\t</task>\n");
 
                fw.write(sb.toString());
            }
            
            fw.write("\t</tasks>\n");
            fw.write("</journal>\n");
            
        } finally{
            if(fw != null){
                try{
                    fw.close();
                } catch(IOException e){
                    throw new IOException("Проблемы при закрытии файла");
                }
            }
        }
    }
}

Class UserInterface
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ru.junior_progger;
 
/**
 *
 * @author Almaz
 */
 
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Scanner;
 
import javax.xml.parsers.ParserConfigurationException;
 
import org.xml.sax.SAXException;
 
public class UserInterface {
    
    public void showMessage(String message){
        System.out.println(message);
    }
    
    public void showMenu(){
            System.out.println("1.  Показать все события");
            System.out.println("2.  Добавить событие");
            System.out.println("3.  Удалить  событие");
            System.out.println("4.  Удалить  все события");
            System.out.println("5.  Сохранить serialization");
            System.out.println("6.  Сохранить в  xml-файла");
            System.out.println("7.  Сохранить в отдельный файл");
            System.out.println("8.  Загрузить из xml-файла");
            System.out.println("0.  Выход");
            
    }
 
    public Operations getOperation(Scanner sc){
        do{
            System.out.print("Введите номер операции\n->  ");
 
            try{
                    int oper = Integer.parseInt(sc.nextLine());
                    return Operations.convertFromInt(oper);
            } catch(NumberFormatException e){
                    System.out.println("Произошла ошибка при вводе, пожалуйста,"
                            + " повторите ввод\nНе удалось преобразовать входную "
                            + "строку!");
            } catch(IllegalArgumentException e){
                    System.out.println("Произошла ошибка при вводе, пожалуйста,"
                            + " повторите ввод\n" + e.getMessage());
            }
        }while(true);
    }
    
    @Deprecated
    public void loadFromXmlFile(Journal journal, String path ){
        
        if(journal != null){
            System.out.println("Считывание из xml-файла");
            try {
                journal.loadFromXML(path);
                
            } catch(IOException e){
                System.out.println("Произошла ошибка при чтении из " +
                        "xml-файла\n" + e.getMessage());
            } catch(IllegalArgumentException e){
                System.out.println("Произошла ошибка при чтении из " +
                    "xml-файла\n" + e.getMessage());
                
            } catch (ParserConfigurationException e) {
                System.out.println("Произошла ошибка при чтении из " +
                        "xml-файла\n" + e.getMessage());
            } catch (SAXException e) {
                System.out.println("Произошла ошибка при чтении из " +
                        "xml-файла\n" + e.getMessage());
            }
        } else
            throw new NullPointerException();
        
    }
    
    public void showAllTasks(List<Task> tasks){
        if(tasks != null && false == tasks.isEmpty()){
            System.out.println("Всего " + tasks.size() + " событий!");
            for(int i = 0; i < tasks.size(); i++)
                System.out.println((i + 1 ) +  ".  " + tasks.get(i).toString());
            
            
            System.out.println();
        } else{
            System.out.println("В списке нет задач");
        }
    }
    
    public void deleteTask(List<Task> tasks, Scanner sc){
        try{
            if(tasks.size() != 0){
                System.out.println("Удаление события из списка");
                
                this.showAllTasks(tasks);
                
                int result = getNumber(sc, "Введите номер события");
                if(tasks.size() >= result){
                    tasks.remove(result - 1);
                }
                System.out.println("Удаление события прошло успешно!");
            } else{
                System.out.println("В списке нет событий");
            }
            
            
        } catch(IllegalArgumentException e){
            System.out.println("Произошла ошибка при удаления события\n" + e.getMessage());
        }
        
    }
    
    
    public void deleteAllTasks(Journal journal) {
        System.out.println("Удаление всех событий с журнала");
        journal.clear();
        System.out.println("Все события удалены!");
    }
    
    public void saveJournalToXML(Journal journal, String fileName){
        try{
            System.out.println("Сохранение в xml - файл");
            
            StringBuilder sb = new StringBuilder();
            sb.append("E:\\");
            sb.append(fileName);
            
            journal.saveToXML(sb.toString());
            System.out.println("Сохранение прошло успешно");
            
        } catch(IOException e){
            System.out.println("Произошла ошибка при сохранении файла\n"
                    + e.getMessage());
        }
    }
    
    @Deprecated
    public void saveAs(Journal journal) {
        
    }
    
    public void exit(){
        System.out.println("Завершение программы");
        System.exit(0);
    }
    
    public void addTask(Scanner sc, Journal journal){
        try{
        System.out.println("Добавить новое событие");
        Task tsk = getTask(sc);
        journal.add(tsk);
        System.out.println("Добавление события успешно завершено!");
        } catch(IllegalArgumentException e){
            System.out.println("Произошла ошибка при добавления события\n" + e.getMessage());
        }
        
    }
    
    @Deprecated
    private Task getTask(Scanner sc){
        String name = getTaskName(sc);
        String desc = getTaskDescription(sc);
        Date date= getTaskTime(sc);
        String contacts = getTaskContacts(sc);
 
        return new Task(name, desc, date, contacts);
    }
    
    private String getTaskName(Scanner sc){
        String result;
        do{
            System.out.println("Введите название мероприятия");
            result = sc.nextLine();
 
            if(true == result.isEmpty() || result.length() < 4)
                System.out.println("Введите корректное название события, "
                        + "название должно состоять не менее из 4 букв");
            else
                return result;
 
        } while(true);
    }
 
    private Date getTaskTime(Scanner sc){
        do{
            System.out.println("Ввод даты события");
            int year = getNumber(sc, "год");
            int month = getNumber(sc, "месяц");
            int day = getNumber(sc, "день");
            int hour = getNumber(sc, "час");
            int minute = getNumber(sc, "минут");
 
            return new Date(year, month, day, hour, minute, 0);
        } while(true);
    }
 
    private int getNumber(Scanner sc, String text){
        while(true){
            try{
                System.out.print("Введите " + text + ": ");
                int result = Integer.parseInt(sc.nextLine());
                if(result < 0 ){
                    System.out.println("Введено некорректное число!\nПопробуйте "
                            + "ввести заново");
                    continue;
                }
                return result;
            } catch(NumberFormatException e){
                System.out.println("Произошла ошибка при вводе, пожалуйста,"
                    + " повторите ввод\nНе удалось преобразовать входную "
                    + "строку!");
            }
        } 
    }
    
    private  String getTaskDescription(Scanner sc){
        String result;
        do{
            System.out.println("Введите описание мероприятия");
            result = sc.nextLine();
 
            if(true == result.isEmpty() || result.length() < 4)
                System.out.println("Введите корректное описание события, "
                        + "название должно состоять не менее из 4 букв");
            else
                return result;
 
        } while(true);
    }
 
    private  String getTaskContacts(Scanner sc){
        String result;
        do{
            System.out.println("Введите место мероприятия");
            result = sc.nextLine();
 
            if(true == result.isEmpty() || result.length() < 4)
                System.out.println("Введите корректные контакты, "
                        + "текст должен состоять не менее из 4 букв");
            else
                return result;
 
        } while(true);
    }
}

Enum Operations
Кликните здесь для просмотра всего текста

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package ru.junior_progger;
 
/**
 *
 * @author Almaz
 */
 
public enum Operations {
    ShowAllTasks,
    AddTask,
    DeleteTask,
    DeleteAllTasks,
    Serialize,
    SaveToXML,
    SaveAs,
    LoadFromXmlFile,
    Exit;
 
    static Operations convertFromInt(int i){ 
        switch(i){
            case 1: return Operations.ShowAllTasks;
            case 2: return Operations.AddTask;
            case 3: return Operations.DeleteTask;
            case 4: return Operations.DeleteAllTasks;
            case 5: return Operations.Serialize;
            case 6: return Operations.SaveToXML;
            case 7: return Operations.SaveAs;
            case 8: return Operations.LoadFromXmlFile;
            case 0: return Operations.Exit;
 
            default:
                throw new IllegalArgumentException("Данного действия"
                            + " нет в списке");
        }
    }
};



Class Task
Кликните здесь для просмотра всего текста

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package ru.junior_progger;
 
/**
 *
 * @author Almaz
 */
 
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
 
public final class Task {
    private String name;
    private String description;
    private Date time;
    private String contacts;
 
    public Task(String name, String description, 
            Date time, String contacts){
        this.setName(name);
        this.setContacts(contacts);
        this.setDescription(description);
        this.setTime(time);
    }
 
    public String getName() {
            return name;
    }
    public void setName(String name) {
            if(!name.isEmpty())
                    this.name = name;
            else
                    throw new IllegalArgumentException("Введите корректное " +
                                    "название события");
    }
    public String getDescription() {
            return description;
    }
    public void setDescription(String description) {
            this.description = description;
    }
    public Date getTime() {
            return time;
    }
    public void setTime(Date time) {
            this.time = time;
    }
    public String getContacts() {
            return contacts;
    }
    public void setContacts(String contacts) {
            this.contacts = contacts;
    }
 
    @Override
    public String toString(){
            StringBuilder sb = new StringBuilder();
            sb.append(this.getName());
            sb.append("  ");
            sb.append(this.getDescription());
            sb.append("  ");
            sb.append(this.getContacts());
            sb.append("  ");
            DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
            String date = df.format(this.getTime());
            sb.append(date);
            return sb.toString();
    }
}


Добавлено через 31 минуту
Вопрос номер 2 - снят

В результирующий файл записывается не только поля самого объекта(кроме полей transient - которые в сериализации не участвуют), плюс к этому записывается алгоритм сериализации\десериализации.

Из-за этого если объект класса содержит всего 2 интовских поля - это не значит, что размер выходного файла будет 8 бит, размер этого файла может быть и все 80, или все 800 бит.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
06.10.2013, 21:49
Ответы с готовыми решениями:

Это говнокод или так и делают ?
Пишу программу в которой пользователь должен угадывать столицы стран мира в Windows Form. И вот у меня вопрос: мне теперь каждую страну и...

Есть ли справочник, где можно понять, что делают методы или свойства классов?
захожу на сайт майкросовта, но яснее пока не становится. не подскажете справочник, где кратко и понятно? еще не поможете с коментариями к...

Как они это делают?
Вот меня всегда волновал вопрос. Почему когда я что-то ищу я попадают вот на такие страницы: результат поиска страница результат поиска на...

50
169 / 66 / 15
Регистрация: 24.03.2013
Сообщений: 467
Записей в блоге: 1
07.10.2013, 15:24  [ТС]
Студворк — интернет-сервис помощи студентам
Вопрос номер 1 - решен
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public synchronized void save(View view) {
        if (tasks.size() == 0) {
            view.showMessage("В журнале нет задач для сохранения!");
        } else {
            view.showMessage("В журнале " + this.tasks.size()
                    + " задач для записи");
 
            view.showMessage("Сохранение в xml - файл");
 
            try {
                DocumentBuilderFactory factory = DocumentBuilderFactory
                        .newInstance();
                DocumentBuilder builder = factory.newDocumentBuilder();
 
                Document doc = builder.newDocument();
 
                // root element
                Element root = doc.createElement("journal");
                doc.appendChild(root);
 
                // element tasks
                Element tasks = doc.createElement("tasks");
                root.appendChild(tasks);
                for (int i = 0; i < this.tasks.size(); i++) {
                    Task tsk = this.tasks.get(i);
                    // element task
                    Element task = doc.createElement("task");
                    tasks.appendChild(task);
 
                    // element name
                    Element name = doc.createElement("name");
                    name.appendChild(doc.createTextNode(tsk.getName()));
                    task.appendChild(name);
 
                    // element description
                    Element desc = doc.createElement("description");
                    desc.appendChild(doc.createTextNode(tsk.getDescription()));
                    task.appendChild(desc);
 
                    // element contacts
                    Element contacts = doc.createElement("contacts");
                    contacts.appendChild(doc.createTextNode(tsk.getContacts()));
                    task.appendChild(contacts);
 
                    // element date
                    Element date = doc.createElement("date");
                    date.appendChild(doc.createTextNode(tsk.getTime()
                            .toString()));
                    task.appendChild(date);
                }
 
                TransformerFactory transformerFactory = TransformerFactory
                        .newInstance();
                Transformer transformer = transformerFactory.newTransformer();
                DOMSource source = new DOMSource(doc);
                StreamResult result = new StreamResult(this.default_path);
 
                transformer.transform(source, result);
                
                view.showMessage("Сохранение в xml-файл успешно завершено!");
 
            } catch (TransformerConfigurationException e) {
                view.showMessage("Произошла ошибка при записи xml-файла\n" + e.getMessage()); 
            } catch(TransformerException e){
                view.showMessage("Произошла ошибка при записи xml-файла\n" + e.getMessage());
            } catch(ParserConfigurationException e){
                view.showMessage("Произошла ошибка при записи xml-файла\n" + e.getMessage());
            }
 
        }
    }
0
78 / 78 / 9
Регистрация: 28.10.2011
Сообщений: 219
07.10.2013, 15:33
Цитата Сообщение от Almaz_1993 Посмотреть сообщение
private Object lock = new Object();
А это кстати зачем ? и чего по нему идёт синхронизация ???
1
169 / 66 / 15
Регистрация: 24.03.2013
Сообщений: 467
Записей в блоге: 1
07.10.2013, 15:47  [ТС]
Цитата Сообщение от warloc69 Посмотреть сообщение
А это кстати зачем ? и чего по нему идёт синхронизация ???
Признаюсь, этот момент в синхронизации не очень я понимаю, но я знаю, что есть некий монитор - который захватывает этот объект(lock), и пока этот lock не освободится - другие потоки не смогут захватить этот объект, тем самым можно добиться поочередности выполнения потоков - вполне верятно что-то я здесь путаю.
0
78 / 78 / 9
Регистрация: 28.10.2011
Сообщений: 219
07.10.2013, 17:11
Цитата Сообщение от Almaz_1993 Посмотреть сообщение
есть некий монитор - который захватывает этот объект(lock), и пока этот lock не освободится - другие потоки не смогут захватить этот объект, тем самым можно добиться поочередности выполнения потоков
Это правильно, вопрос в том, нафига Вы создаёте объект lock , которые нигде не используется?? Вам нужно лочить только те объекты к которым может быть доступ из разных потоков (с возможным их изменением в паралельных потоках).

Добавлено через 4 минуты
Та и вообще , я бы сделал модел по патерну Синглтон, в нём сделал некую очередь команд которую система будет получать от контроллера и последовательно их выполнять.
Благодаря этому вам не нужно будет заморачиватся с синхронизацией.

Добавлено через 42 секунды
Вас наверно от слова Паттерн уже колбасить начинает
1
169 / 66 / 15
Регистрация: 24.03.2013
Сообщений: 467
Записей в блоге: 1
08.10.2013, 01:07  [ТС]
Все таки я думаю надо поступать здесь следующим образом:

В контролере создать метод start(),который запускает еще один поток, а этот поток через каждые пол минуты обращается к методу модели, который возвращает таск который нужно сейчас выполнить или null - если таковых не имеется. Ну соответственно, если результат не null - то этот результат передаем view'у для отображения,
Как вам идея такая?

Вот такая вот реализация

Таск менеджер - с точкой входу в программу
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package ru.junior_progger;
 
import java.util.Scanner;
 
public class TaskManager {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Model model = new Model();
        Controler controler = new Controler();
        View view = new View(sc);
        
        controler.start(model, view);
        
        while(true){
            view.showMainMenu();
            Operation op = view.getOperation();
            int result = controler.make(op, model, view);
            
            if(result == -1){
                view.showMessage("Программа закончила свою работу!");
                return;
            }
        }
    }
}


Здесь функции, добавленные в модел
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public Task[] getTasksToPerform(Date time) {
        synchronized(this.tasks){
            List<Task> result = new ArrayList<>();
            
            for(Task tsk : this.tasks){
                if(isEqualsTime(tsk.getTime(), time)){
                    result.add(tsk);
                }
            }
            
            if(result.size() != 0){
                return convertListToArrayTask(result);
            } else 
                return null;
        }
    }
    
    @SuppressWarnings("deprecation")
    private boolean isEqualsTime(Date d1, Date d2) {
        return d1.getYear() == d2.getYear() && d1.getMonth() == d2.getMonth()
                && d1.getDay() == d2.getDay() && d1.getHours() == d2.getHours()
                && d1.getMinutes() == d2.getMinutes();
    }
 
    private Task[] convertListToArrayTask(List<Task> tasks){
        Task[] result = new Task[tasks.size()]; 
        for(int i = 0; i < tasks.size(); i++)
            result[i] = tasks.get(i);
        return result;
    }


Метод старт в контролере
[SPOILER]
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public void start(final Model model, final View view) {
        Thread th = new Thread(new Runnable(){ 
            public void run(){
                while(true){
                    try {
                        Task[] tsk = model.getTasksToPerform(
                                Calendar.getInstance().getTime());
                        
                        if(tsk != null){
                            for(Task t : tsk){
                                if(false == t.isDone()){
                                    view.showTaskToPerform(t);
                                    t.setDone(true);
                                }
                            }
                        }
                        Thread.sleep(50);
                        
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        
        th.setDaemon(true);
        th.start();
    }
Вроде все работает.
Какие есть замечания?

Вопрос номер 1
Java
1
2
3
4
5
6
7
8
Thread th = new Thread(new Runnable(){ 
      public void run(){
      // что-то делаем и  засыпаем
       Thread.sleep(50);
      }
});
th.setDaemon(true);
th.start();
- какой поток засыпает, поток th же должен засыпать? Просто не видно из этого кода - почему поток th должен засыпать, а скажем не какой-нибудь другой. Какой принцип работы у Thread.sleed() ?
0
78 / 78 / 9
Регистрация: 28.10.2011
Сообщений: 219
08.10.2013, 10:22
Цитата Сообщение от Almaz_1993 Посмотреть сообщение
В контролере создать метод start(),который запускает еще один поток, а этот поток через каждые пол минуты обращается к методу модели, который возвращает таск который нужно сейчас выполнить или null - если таковых не имеется. Ну соответственно, если результат не null - то этот результат передаем view'у для отображения
С архитектурной точки зрения , это нарушает MVC
Контроллер, контролирует только валидность данных и всё. В чём фишка MVC? в том что вы можете спокойно создать несколько вьюшек и они будут выполнять различные функции (один - отображать пользователю на экран, второй распечатывать на принтер, третий отправлять куда-то в сеть и тд... Но при этом уведомление о наступлении таски может быть необходимо только одном, если реализациия будет в контроллере , то это затронет все вью. ), так же можно реализовать нескоклько контроллеров и моделей. (Поэтому в мвц обязательно наличие интерфейсов )

Цитата Сообщение от Almaz_1993 Посмотреть сообщение
Thread.sleed()
усыпляет поток и передаёт управлению менеджеру потоков, который берёт и будет другой поток.
th - это ваш класс потоков который вы реализуете в без имянном классе.

Вопрос , как Ваш поток завершится???
1
169 / 66 / 15
Регистрация: 24.03.2013
Сообщений: 467
Записей в блоге: 1
08.10.2013, 10:41  [ТС]
Цитата Сообщение от warloc69 Посмотреть сообщение
Это правильно, вопрос в том, нафига Вы создаёте объект lock , которые нигде не используется?? Вам нужно лочить только те объекты к которым может быть доступ из разных потоков (с возможным их изменением в паралельных потоках).
- да, здесь разобрался. Можно было лочить только список тасков, поскольку работа идет только с тасками.

Добавлено через 9 минут
Цитата Сообщение от warloc69 Посмотреть сообщение
усыпляет поток и передаёт управлению менеджеру потоков, который берёт и будет другой поток.
Как происходит в общем случае запуск потока:
Создается объект класса Thread, в конструктор которого передается объект, грубо говоря, у которого есть метод run(). Далее у созданного объекта Thread вызвается метод start(), который в свою очередь вызывает метод run у объекта, переданного в конструктор. - Я правильно понимаю?
Цитата Сообщение от warloc69 Посмотреть сообщение
th - это ваш класс потоков который вы реализуете в без имянном классе.
Вопрос , как Ваш поток завершится???
- не очень понял в чем суть вопроса.

Вопрос , как Ваш поток завершится???
- поскольку у моего объекта (th) класса Thread установлено свойство
Java
1
th.setDaemon(true);
- т.е. поток является демоном, то я надеюсь, что после того как главный маин поток завершится - завершится и поток th.
0
78 / 78 / 9
Регистрация: 28.10.2011
Сообщений: 219
08.10.2013, 11:31
Цитата Сообщение от Almaz_1993 Посмотреть сообщение
в конструктор которого передается объект, грубо говоря, у которого есть метод run()
Верно на половину. Можно создать в любом классе метод run , но это не значет, что класс Thread приймёт объект этого класса без ругательств со стороны кампилятора.

Что бы Thread съел объект класса, нужно что бы :
1) ИЛИ класс был наследником Thread ! ИЛИ 2) класс имлементировал интерфейс Runnable. (это относится к старым версиям java, в новых версиях жавы (кажись с 1.6 или 1.5), работа с потоками и синхронизацией немного по другому организована)

Добавлено через 3 минуты
Цитата Сообщение от Almaz_1993 Посмотреть сообщение
т.е. поток является демоном, то я надеюсь, что после того как главный маин поток завершится - завершится и поток th.
Надеятся на это конечно можно, но такое закрытие потоков - не управляемое (и предназначено для аварийного завершения программы). Привыкайте делать некоее условие которое позволит закрыть поток "правильно" (тоесть по выходу с метода run,) у Вас же поток по сути закроется только когда грохнется главный поток (что не всегда есть хорошо)

Добавлено через 1 минуту
У меня такое чувство что вы досих пор не поняли зачем нужны интерфейсы
1
169 / 66 / 15
Регистрация: 24.03.2013
Сообщений: 467
Записей в блоге: 1
08.10.2013, 11:58  [ТС]
Цитата Сообщение от warloc69 Посмотреть сообщение
У меня такое чувство что вы досих пор не поняли зачем нужны интерфейсы
В данном случае - да, я не знаю куда и зачем здесь делать интерфейсы.
0
78 / 78 / 9
Регистрация: 28.10.2011
Сообщений: 219
08.10.2013, 12:09
в данном случае конечно можно и без них. Но если это первая лабораторка, то дальше будет вторая в которой нада будет всё на бины переделать... И тогда вам прийдётся переписывать большую часть кода, а с использованием интерфейсов вам особо препеисывать не нада будет, просто реализовать другой тип модели через существующие интерфейсы.

Не по теме:

Ну эт моя точка зрения которая может быть далека от реальности , так как я не знаю как мыслит тот кто ваше задание будет проверять :)

1
169 / 66 / 15
Регистрация: 24.03.2013
Сообщений: 467
Записей в блоге: 1
08.10.2013, 12:26  [ТС]
Ну если с интерфейсами, то как я вижу это можно сделать:

Вся суть интерфейсов будет заключаться в том, что, к примеру, метод контролера - будет получать не сам объект View, а какой-то интерфейс Viewable, в свою очередь View имплементит этот Viewable. Тоже самое с модел, и контрол.

Не по теме:


Как будут называться эти интерфейсы
View - viewable
Controller - Controllerable
Model - Modelable, так чтоль :D

0
78 / 78 / 9
Регистрация: 28.10.2011
Сообщений: 219
08.10.2013, 12:53
Цитата Сообщение от Almaz_1993 Посмотреть сообщение
Вся суть интерфейсов будет заключаться в том, что, к примеру, метод контролера - будет получать не сам объект View, а какой-то интерфейс Viewable, в свою очередь View имплементит этот Viewable. Тоже самое с модел, и контрол.
Маладца Станеш великим девом ) Быстро схватываеш.

Называют обычно так :
IView или View - интерфейс
ViewImpl, ViewByConsoleImpl, ViewByGuiImpl, - класc реализация

Добавлено через 10 минут
Вообще именование особой тут роли не играет, Главное что бы было понятно, что это интерфейс - а это его класс реализация.
1
169 / 66 / 15
Регистрация: 24.03.2013
Сообщений: 467
Записей в блоге: 1
08.10.2013, 13:40  [ТС]
Цитата Сообщение от warloc69 Посмотреть сообщение
Вообще именование особой тут роли не играет, Главное что бы было понятно, что это интерфейс - а это его класс реализация.
- просто хочу соблюсти Code Convention
0
78 / 78 / 9
Регистрация: 28.10.2011
Сообщений: 219
08.10.2013, 14:00
Цитата Сообщение от Almaz_1993 Посмотреть сообщение
просто хочу соблюсти Code Convention
Из конвеншинов:

Classes Class names should be nouns, in mixed case with the first letter of each internal word capitalized. Try to keep your class names simple
and descriptive. Use whole words—avoid acronyms and abbreviations (unless the abbreviation is much more widely used than the long form, such as URL or HTML).

class Raster;
class ImageSprite;

Interfaces
Interface names should be capitalized like class names.

interface RasterDelegate;
interface Storing;
1
169 / 66 / 15
Регистрация: 24.03.2013
Сообщений: 467
Записей в блоге: 1
08.10.2013, 16:07  [ТС]
Вот у меня что в итоге получилось

Вот такая иерархия


Ну соответственно интерфейсы
IController
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
package ru.junior_progger.controller;
 
import ru.junior_progger.main.Operation;
import ru.junior_progger.model.IModel;
import ru.junior_progger.view.IView;
 
public interface IController {
    public void start(final IModel model, final IView view);
    public int make(Operation operation, IModel model, IView view);
}


IView
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
package ru.junior_progger.view;
 
import ru.junior_progger.main.Operation;
import ru.junior_progger.main.Task;
 
public interface IView {
    public void showMessage(String text);
    public Task getTask();
    public int getNumber(String s);
    public void showMainMenu();
    public Operation getOperation();
    public void showTaskToPerform(Task tsk);
}


Ну и IModel - просьба не переводить
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package ru.junior_progger.model;
 
import java.util.Date;
 
import ru.junior_progger.main.Task;
import ru.junior_progger.view.IView;
 
public interface IModel {
    public void showAllTasks(IView view);
    public void deleteAllTasks(IView view);
    public void deleteTask(IView view);
    public void addTask(IView view);
    public Task[] getTasksToPerform(Date time);
    public void save(IView view);
    public void load(IView view);
}


В реализациях методов всех классов - ничего не изменилось, изменились только входные параметры. Теперь методы получают не сами объекты, а просто их интерфейсы.
0
78 / 78 / 9
Регистрация: 28.10.2011
Сообщений: 219
08.10.2013, 16:28
Как то так) хоть контроллер я бы переделал. Но как для первого раза - пойдёт )))
1
169 / 66 / 15
Регистрация: 24.03.2013
Сообщений: 467
Записей в блоге: 1
09.10.2013, 10:54  [ТС]
Какие замечания я в итоге получил от своего куратора, большинство из этих замечаний легко исправляются - буду исправлять.

Скриншоты от скайпа


Первый обзац - здесь надо либо с кодировкой разбираться либо еще чем-то. Просто я писал это дело в Eclipse, а мой куратор смотрел это в IntelliJIDEA - да, действительно в этом IDEA - вместо русских символов отображаются ромбики.
Второй обзац - fixed - глупо было так писать))
Третий обзац - наверное имеется ввиду вот этот участок кода в таскменеджере
Java
1
2
3
4
5
6
7
8
9
10
 while(true){
            view.showMainMenu();
            Operation op = view.getOperation();
            int result = controler.make(op, model, view);
            
            if(result == -1){
                view.showMessage("Программа закончила свою работу!");
                return;
            }
        }
Четвертый обзац - про вывод сообщений в модели и контролере. Да здесь был прав warloc69, который сразу мне и советовал это, но я не очень четко понимаю как передавать результат работы метода Model сначала в Controller, потом и в View - причем корректно. Придется здесь еще разобраться.



0
169 / 66 / 15
Регистрация: 24.03.2013
Сообщений: 467
Записей в блоге: 1
09.10.2013, 10:58  [ТС]
"и вообще было бы круто, если бы настройки программы лежали в каком-то конфиге, а не зашиты в программу private String default_path = "E:\\journal.xml";" - это еще один файлик формата, скажем, xml - с которого будет считываться начальные настройки программы?
0
78 / 78 / 9
Регистрация: 28.10.2011
Сообщений: 219
09.10.2013, 11:45
Цитата Сообщение от Almaz_1993 Посмотреть сообщение
это еще один файлик формата, скажем, xml
лучше файл пропертей. Для работы с ними в жаве даже есть коллекция Properties

ну а про интерфейсы и свои иксепшины я вам уже давно говорил
1
78 / 78 / 9
Регистрация: 28.10.2011
Сообщений: 219
09.10.2013, 11:50
Вот вам пример :

На Bridge можете не смотреть, так как прога под базу данных проектировалась.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
09.10.2013, 11:50

Уважаемые гуру! Объясните плиз как это работает?
Собственно говоря есть вот такая схема, как я понимаю из разряда стабилизаторов . На входе меняется ток от 3мА в минимуме до 12 мА в макс....

Как это делают - распределение аккаунтов по машинам?
У меня есть сервер, пока один. На нем сидят клиенты, работают в своих аккаунтах. Сейчас проектирую горизонтальное масштабирование, где...

Захват содержимого экрана. Как они это делают?
Всем привет. Подскажите, плиз... вот так у меня захватывается экран: tv := getdc(0); w := GetDeviceCaps(tv, HORZRES); h :=...

Запрос к веб странице, так как это делают браузеры
Есть сайт и есть скрипт (скример бот). Скрипт через file_get_content отвращается к странице и получает содержимое для дельнейшей...

Как реализовать правильное наследование классов
Здравствуйте, столкнулся с такой проблемой. Имеется базовый класс Writers и нужно создать классы Book, Genre, Country. В классе Writer...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru