مشروع شامل
هذا الدرس هو المشروع النهائي لدورة Java، يطبق جميع نقاط المعرفة.
نظرة عامة على المشروع
بناء تطبيق قائمة مهام يدعم:
- إضافة مهام
- عرض قائمة المهام
- وضع علامة مكتمل
- حذف المهام
- حفظ البيانات (في ملف)
- التصفية حسب الحالة/الأولوية
نموذج البيانات
JAVA
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Todo implements Serializable {
private static final long serialVersionUID = 1L;
public enum Priority { LOW, MEDIUM, HIGH }
public enum Status { PENDING, COMPLETED }
private int id;
private String title;
private String description;
private Priority priority;
private Status status;
private LocalDateTime createdAt;
private LocalDateTime completedAt;
public Todo(int id, String title, String description, Priority priority) {
this.id = id;
this.title = title;
this.description = description;
this.priority = priority;
this.status = Status.PENDING;
this.createdAt = LocalDateTime.now();
}
// Getters/Setters
public int getId() { return id; }
public String getTitle() { return title; }
public String getDescription() { return description; }
public Priority getPriority() { return priority; }
public Status getStatus() { return status; }
public LocalDateTime getCreatedAt() { return createdAt; }
public LocalDateTime getCompletedAt() { return completedAt; }
public void setStatus(Status status) {
this.status = status;
if (status == Status.COMPLETED) {
this.completedAt = LocalDateTime.now();
}
}
public boolean isCompleted() {
return status == Status.COMPLETED;
}
@Override
public String toString() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
String statusIcon = isCompleted() ? "✅" : "⬜";
String priorityIcon;
switch (priority) {
case HIGH: priorityIcon = "🔴"; break;
case MEDIUM: priorityIcon = "🟡"; break;
default: priorityIcon = "🟢"; break;
}
return String.format("%s %s [%d] %s (%s)",
statusIcon, priorityIcon, id, title, createdAt.format(formatter));
}
}
فئة المدير
JAVA
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
public class TodoManager {
private List<Todo> todos;
private int nextId;
private static final String FILE_NAME = "todos.dat";
public TodoManager() {
this.todos = new ArrayList<>();
this.nextId = 1;
loadFromFile();
}
// إضافة مهمة
public Todo addTodo(String title, String description, Todo.Priority priority) {
Todo todo = new Todo(nextId++, title, description, priority);
todos.add(todo);
saveToFile();
return todo;
}
// إكمال مهمة
public boolean completeTodo(int id) {
Todo todo = findById(id);
if (todo != null && !todo.isCompleted()) {
todo.setStatus(Todo.Status.COMPLETED);
saveToFile();
return true;
}
return false;
}
// حذف مهمة
public boolean deleteTodo(int id) {
Todo todo = findById(id);
if (todo != null) {
todos.remove(todo);
saveToFile();
return true;
}
return false;
}
// إيجاد مهمة
public Todo findById(int id) {
return todos.stream()
.filter(t -> t.getId() == id)
.findFirst()
.orElse(null);
}
// الحصول على جميع المهام
public List<Todo> getAllTodos() {
return new ArrayList<>(todos);
}
// الحصول على المهام المعلقة
public List<Todo> getPendingTodos() {
return todos.stream()
.filter(t -> !t.isCompleted())
.collect(Collectors.toList());
}
// الحصول على المهام المكتملة
public List<Todo> getCompletedTodos() {
return todos.stream()
.filter(Todo::isCompleted)
.collect(Collectors.toList());
}
// ترتيب حسب الأولوية
public List<Todo> sortByPriority() {
return todos.stream()
.sorted((a, b) -> {
int cmp = b.getPriority().compareTo(a.getPriority());
return cmp != 0 ? cmp : a.getId() - b.getId();
})
.collect(Collectors.toList());
}
// ترتيب حسب تاريخ الإنشاء
public List<Todo> sortByDate() {
return todos.stream()
.sorted(Comparator.comparing(Todo::getCreatedAt))
.collect(Collectors.toList());
}
// إحصائيات
public int getTotal() { return todos.size(); }
public int getPendingCount() { return (int) todos.stream().filter(t -> !t.isCompleted()).count(); }
public int getCompletedCount() { return (int) todos.stream().filter(Todo::isCompleted).count(); }
// حفظ في ملف
private void saveToFile() {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_NAME))) {
oos.writeObject(todos);
oos.writeInt(nextId);
} catch (IOException e) {
System.out.println("فشل الحفظ: " + e.getMessage());
}
}
// تحميل من ملف
@SuppressWarnings("unchecked")
private void loadFromFile() {
File file = new File(FILE_NAME);
if (!file.exists()) return;
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_NAME))) {
todos = (List<Todo>) ois.readObject();
nextId = ois.readInt();
} catch (IOException | ClassNotFoundException e) {
System.out.println("فشل التحميل: " + e.getMessage());
}
}
}
البرنامج الرئيسي
JAVA
import java.util.List;
import java.util.Scanner;
public class TodoApp {
private static TodoManager manager = new TodoManager();
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("=== قائمة المهام ===");
int choice;
do {
showMenu();
choice = getIntInput("أدخل اختيارك: ");
switch (choice) {
case 1: addTodo(); break;
case 2: listTodos(); break;
case 3: completeTodo(); break;
case 4: deleteTodo(); break;
case 5: showStatistics(); break;
case 6: listByPriority(); break;
case 0: System.out.println("شكراً!"); break;
default: System.out.println("خيار غير صالح");
}
} while (choice != 0);
scanner.close();
}
private static void showMenu() {
System.out.println("\n--- القائمة ---");
System.out.println("1. إضافة مهمة");
System.out.println("2. عرض جميع المهام");
System.out.println("3. وضع علامة مكتمل");
System.out.println("4. حذف مهمة");
System.out.println("5. إحصائيات");
System.out.println("6. ترتيب حسب الأولوية");
System.out.println("0. خروج");
}
private static void addTodo() {
System.out.print("العنوان: ");
String title = scanner.nextLine().trim();
if (title.isEmpty()) {
System.out.println("العنوان لا يمكن أن يكون فارغاً");
return;
}
System.out.print("الوصف: ");
String desc = scanner.nextLine().trim();
System.out.println("الأولوية: 1-منخفضة 2-متوسطة 3-عالية");
int p = getIntInput("الاختيار: ");
Todo.Priority priority;
switch (p) {
case 1: priority = Todo.Priority.LOW; break;
case 3: priority = Todo.Priority.HIGH; break;
default: priority = Todo.Priority.MEDIUM;
}
Todo todo = manager.addTodo(title, desc, priority);
System.out.println("أضيف: " + todo);
}
private static void listTodos() {
List<Todo> todos = manager.getAllTodos();
if (todos.isEmpty()) {
System.out.println("لا توجد مهام");
return;
}
System.out.println("\n--- قائمة المهام ---");
for (Todo todo : todos) {
System.out.println(todo);
}
System.out.printf("المجموع: %d (معلقة: %d، مكتملة: %d)%n",
manager.getTotal(), manager.getPendingCount(), manager.getCompletedCount());
}
private static void completeTodo() {
listTodos();
int id = getIntInput("أدخل المعرف للإكمال: ");
if (manager.completeTodo(id)) {
System.out.println("تم وضع علامة مكتمل");
} else {
System.out.println("معرف غير صالح أو مكتمل بالفعل");
}
}
private static void deleteTodo() {
listTodos();
int id = getIntInput("أدخل المعرف للحذف: ");
if (manager.deleteTodo(id)) {
System.out.println("تم الحذف");
} else {
System.out.println("معرف غير صالح");
}
}
private static void showStatistics() {
System.out.println("\n=== إحصائيات ===");
System.out.println("المجموع: " + manager.getTotal());
System.out.println("معلقة: " + manager.getPendingCount());
System.out.println("مكتملة: " + manager.getCompletedCount());
double rate = manager.getTotal() > 0 ?
(double) manager.getCompletedCount() / manager.getTotal() * 100 : 0;
System.out.printf("نسبة الإكمال: %.1f%%%n", rate);
}
private static void listByPriority() {
List<Todo> todos = manager.sortByPriority();
System.out.println("\n--- مرتبة حسب الأولوية ---");
for (Todo todo : todos) {
System.out.println(todo);
}
}
private static int getIntInput(String prompt) {
System.out.print(prompt);
while (!scanner.hasNextInt()) {
System.out.print("أدخل رقماً: ");
scanner.next();
}
int value = scanner.nextInt();
scanner.nextLine(); // استهلاك سطر جديد
return value;
}
}
مثال الناتج
TEXT
=== قائمة المهام ===
--- القائمة ---
1. إضافة مهمة
2. عرض جميع المهام
3. وضع علامة مكتمل
4. حذف مهمة
5. إحصائيات
6. ترتيب حسب الأولوية
0. خروج
أدخل اختيارك: 1
العنوان: تعلم Java
الوصف: إكمال درس 32 من دورة Java
الأولوية: 1-منخفضة 2-متوسطة 3-عالية
الاختيار: 3
أضيف: ⬜ 🔴 [1] تعلم Java (2026-06-25 14:30)
أدخل اختيارك: 2
--- قائمة المهام ---
⬜ 🔴 [1] تعلم Java (2026-06-25 14:30)
المجموع: 1 (معلقة: 1، مكتملة: 0)
ملخص المعرفة
| المعرفة | التطبيق |
|---|---|
| فئات وكائنات | تصميم فئات Todo و TodoManager |
| التغليف | حقول خاصة، getters/setters |
| Enums | Priority، Status |
| Collections | List للمهام، Stream |
| معالجة الاستثناءات | معالجة أخطاء IO |
| File IO | التسلسل للحفظ/التحميل |
| التاريخ/الوقت | LocalDateTime للتواريخ |
| Lambda | ترتيب، تصفية بال Stream |
| Generics | List |
ميزات موسعة
1. تصفية حسب التاريخ
JAVA
public List<Todo> getTodayTodos() {
LocalDate today = LocalDate.now();
return todos.stream()
.filter(t -> t.getCreatedAt().toLocalDate().equals(today))
.collect(Collectors.toList());
}
2. وظيفة البحث
JAVA
public List<Todo> search(String keyword) {
String lower = keyword.toLowerCase();
return todos.stream()
.filter(t -> t.getTitle().toLowerCase().contains(lower) ||
t.getDescription().toLowerCase().contains(lower))
.collect(Collectors.toList());
}
3. التصدير إلى نص
JAVA
public void exportToText(String filename) throws IOException {
try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
writer.println("=== تصدير قائمة المهام ===");
writer.println("وقت التصدير: " + LocalDateTime.now());
writer.println();
for (Todo todo : todos) {
writer.println(todo);
if (!todo.getDescription().isEmpty()) {
writer.println(" " + todo.getDescription());
}
writer.println();
}
}
}
❓ أسئلة شائعة
س كيف أوسع لتطبيق GUI؟
ج استخدم JavaFX أو Swing لتنفيذ واجهة رسومية.
س كيف أدعم عدة مستخدمين؟
ج كل مستخدم يحصل على ملف خاص به، أو استخدم قاعدة بيانات.
س كيف أضيف وظيفة التذكير؟
ج استخدم Timer/ScheduledExecutorService للتحقق من المهام المستحقة.
📖 ملخص
- تطبيق مفاهيم الفئات، Collections، الاستثناءات، IO، Lambda
- حفظ البيانات باستخدام التسلسل
- API Stream يبسط عمليات Collections
- Enums تحدد ثوابت ثابتة
📝 تمارين
- توسيع: أضف البحث والتصفية حسب التاريخ
- تصدير: ادعم التصدير بصيغة CSV
- GUI: نفذ واجهة رسومية بـ JavaFX
🎉 مبروك لإكمال دورة Java!
خلال 32 درس، لقد أتقنت:
- بنية جملة Java الأساسية
- البرمجة الكائنية
- إطار Collections
- معالجة الاستثناءات
- File IO
- التعبيرات النمطية ومعالجة JSON
الخطوات التالية للتعلم:
- إطار Spring Boot
- برمجة قواعد البيانات (JDBC/MyBatis)
- تطوير الويب
- أنماط التصميم



