Skip to content

Commit 43cdea0

Browse files
Merge pull request #19 from darbyluv2code/feature/add-visitor-pattern
Add visitor pattern with course content inspection
2 parents 8a20f7e + 466048d commit 43cdea0

File tree

10 files changed

+360
-0
lines changed

10 files changed

+360
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.luv2code</groupId>
8+
<artifactId>java-design-patterns</artifactId>
9+
<version>1.0</version>
10+
11+
<properties>
12+
<maven.compiler.source>25</maven.compiler.source>
13+
<maven.compiler.target>25</maven.compiler.target>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
</properties>
16+
17+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.luv2code.designpatterns.behavioral.visitor;
2+
3+
/**
4+
* Role: Concrete Element
5+
*
6+
* Represents an assignment in the course.
7+
* Accepts a visitor and delegates to the correct visit method.
8+
*/
9+
public class Assignment implements CourseContent {
10+
11+
private String title;
12+
private int estimatedCompletionMinutes;
13+
14+
public Assignment(String title, int estimatedCompletionMinutes) {
15+
this.title = title;
16+
this.estimatedCompletionMinutes = estimatedCompletionMinutes;
17+
}
18+
19+
@Override
20+
public String getTitle() {
21+
return title;
22+
}
23+
24+
public int getEstimatedCompletionMinutes() {
25+
return estimatedCompletionMinutes;
26+
}
27+
28+
@Override
29+
public void accept(ContentVisitor visitor) {
30+
visitor.visit(this);
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.luv2code.designpatterns.behavioral.visitor;
2+
3+
/**
4+
* Role: Concrete Visitor
5+
*
6+
* Counts how many of each content type exist in the course.
7+
*/
8+
public class ContentCountVisitor implements ContentVisitor {
9+
10+
private int videoCount = 0;
11+
private int quizCount = 0;
12+
private int assignmentCount = 0;
13+
14+
@Override
15+
public void visit(VideoLesson videoLesson) {
16+
videoCount++;
17+
}
18+
19+
@Override
20+
public void visit(Quiz quiz) {
21+
quizCount++;
22+
}
23+
24+
@Override
25+
public void visit(Assignment assignment) {
26+
assignmentCount++;
27+
}
28+
29+
public int getVideoCount() {
30+
return videoCount;
31+
}
32+
33+
public int getQuizCount() {
34+
return quizCount;
35+
}
36+
37+
public int getAssignmentCount() {
38+
return assignmentCount;
39+
}
40+
}
41+
42+
43+
44+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.luv2code.designpatterns.behavioral.visitor;
2+
3+
/**
4+
* Role: Visitor
5+
*
6+
* Declares a visit method for each type of course content element.
7+
* Implement this interface to add a new operation to the course content.
8+
*/
9+
public interface ContentVisitor {
10+
11+
// One method per element type
12+
// Allows each visitor to handle each type differently
13+
14+
void visit(VideoLesson videoLesson);
15+
16+
void visit(Quiz quiz);
17+
18+
void visit(Assignment assignment);
19+
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.luv2code.designpatterns.behavioral.visitor;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
* Role: Object Structure
8+
*
9+
* Holds a collection of course content elements.
10+
* Applies a visitor to each element by calling accept().
11+
*/
12+
public class Course {
13+
14+
private String courseName;
15+
private List<CourseContent> contents;
16+
17+
public Course(String courseName) {
18+
this.courseName = courseName;
19+
this.contents = new ArrayList<>();
20+
}
21+
22+
public String getCourseName() {
23+
return courseName;
24+
}
25+
26+
public void addContent(CourseContent theContent) {
27+
contents.add(theContent);
28+
}
29+
30+
public void accept(ContentVisitor visitor) {
31+
32+
for (CourseContent theContent : contents) {
33+
theContent.accept(visitor); // each element then calls visitor.visit(this)
34+
}
35+
}
36+
}
37+
38+
39+
40+
41+
42+
43+
44+
45+
46+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.luv2code.designpatterns.behavioral.visitor;
2+
3+
/**
4+
* Role: Element
5+
*
6+
* Defines the contract for all course content elements.
7+
* Each element must accept a visitor.
8+
*/
9+
public interface CourseContent {
10+
11+
String getTitle();
12+
13+
void accept(ContentVisitor visitor);
14+
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.luv2code.designpatterns.behavioral.visitor;
2+
3+
/**
4+
* Role: Client
5+
*
6+
* Demonstrates the Visitor pattern through three teaching scenarios.
7+
* The course structure is built once and can accept any number of visitors.
8+
*/
9+
public class MainApp {
10+
11+
static void main() {
12+
13+
Course course = buildCourse();
14+
15+
System.out.println("--- Demo 1: Content Count Report ---");
16+
runContentCountDemo(course);
17+
18+
System.out.println("\n--- Demo 2: Study Time Report ---");
19+
runStudyTimeDemo(course);
20+
21+
System.out.println("\n--- Demo 3: Multiple Visitors on the Same Course ---");
22+
runMultipleVisitorsDemo(course);
23+
24+
}
25+
26+
private static void runMultipleVisitorsDemo(Course course) {
27+
28+
// New visitor instances are required because
29+
// each visitor accumulates state as it runs
30+
31+
ContentCountVisitor contentCountVisitor = new ContentCountVisitor();
32+
course.accept(contentCountVisitor);
33+
34+
System.out.println("Course: " + course.getCourseName());
35+
System.out.println("Videos: " + contentCountVisitor.getVideoCount());
36+
System.out.println("Quizzes: " + contentCountVisitor.getQuizCount());
37+
System.out.println("Assignments: " + contentCountVisitor.getAssignmentCount());
38+
39+
System.out.println();
40+
41+
TotalStudyTimeVisitor totalStudyTimeVisitor = new TotalStudyTimeVisitor();
42+
course.accept(totalStudyTimeVisitor);
43+
System.out.println("Study time: " + totalStudyTimeVisitor.getTotalMinutes() + " minutes");
44+
}
45+
46+
private static void runStudyTimeDemo(Course course) {
47+
48+
TotalStudyTimeVisitor totalStudyTimeVisitor = new TotalStudyTimeVisitor();
49+
course.accept(totalStudyTimeVisitor);
50+
51+
System.out.println("\nEstimated total study time: "
52+
+ totalStudyTimeVisitor.getTotalMinutes()
53+
+ " minutes");
54+
55+
}
56+
57+
private static void runContentCountDemo(Course course) {
58+
59+
ContentCountVisitor contentCountVisitor = new ContentCountVisitor();
60+
course.accept(contentCountVisitor);
61+
62+
System.out.println("Course: " + course.getCourseName());
63+
System.out.println("Videos: " + contentCountVisitor.getVideoCount());
64+
System.out.println("Quizzes: " + contentCountVisitor.getQuizCount());
65+
System.out.println("Assignments: " + contentCountVisitor.getAssignmentCount());
66+
}
67+
68+
private static Course buildCourse() {
69+
Course course = new Course("Master Java Design Patterns");
70+
71+
course.addContent(new VideoLesson("Visitor Pattern Overview", 12));
72+
course.addContent(new VideoLesson("Visitor Pattern Coding Example", 15));
73+
course.addContent(new Quiz("Visitor Pattern Quiz", 5));
74+
course.addContent(new Assignment("Build a Visitor Implementation", 30));
75+
76+
return course;
77+
}
78+
}
79+
80+
81+
82+
83+
84+
85+
86+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.luv2code.designpatterns.behavioral.visitor;
2+
3+
/**
4+
* Role: Concrete Element
5+
*
6+
* Represents a quiz in the course.
7+
* Accepts a visitor and delegates to the correct visit method.
8+
*/
9+
public class Quiz implements CourseContent {
10+
11+
private String title;
12+
private int numberOfQuestions;
13+
14+
public Quiz(String title, int numberOfQuestions) {
15+
this.title = title;
16+
this.numberOfQuestions = numberOfQuestions;
17+
}
18+
19+
@Override
20+
public String getTitle() {
21+
return title;
22+
}
23+
24+
public int getNumberOfQuestions() {
25+
return numberOfQuestions;
26+
}
27+
28+
@Override
29+
public void accept(ContentVisitor visitor) {
30+
visitor.visit(this);
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.luv2code.designpatterns.behavioral.visitor;
2+
3+
/**
4+
* Role: Concrete Visitor
5+
*
6+
* Estimates the total study time for the course by summing
7+
* the time for each content element.
8+
*/
9+
public class TotalStudyTimeVisitor implements ContentVisitor {
10+
11+
private static final int MINUTES_PER_QUESTION = 2;
12+
13+
private int totalMinutes = 0;
14+
15+
@Override
16+
public void visit(VideoLesson videoLesson) {
17+
System.out.println("Processing VideoLesson: " + videoLesson.getTitle());
18+
totalMinutes += videoLesson.getDurationInMinutes();
19+
}
20+
21+
@Override
22+
public void visit(Quiz quiz) {
23+
System.out.println("Processing Quiz: " + quiz.getTitle());
24+
totalMinutes += quiz.getNumberOfQuestions() * MINUTES_PER_QUESTION;
25+
}
26+
27+
@Override
28+
public void visit(Assignment assignment) {
29+
System.out.println("Processing Assignment: " + assignment.getTitle());
30+
totalMinutes += assignment.getEstimatedCompletionMinutes();
31+
}
32+
33+
public int getTotalMinutes() {
34+
return totalMinutes;
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.luv2code.designpatterns.behavioral.visitor;
2+
3+
/**
4+
* Role: Concrete Element
5+
*
6+
* Represents a video lesson in the course.
7+
* Accepts a visitor and delegates to the correct visit method.
8+
*/
9+
public class VideoLesson implements CourseContent {
10+
11+
private String title;
12+
private int durationInMinutes;
13+
14+
public VideoLesson(String title, int durationInMinutes) {
15+
this.title = title;
16+
this.durationInMinutes = durationInMinutes;
17+
}
18+
19+
@Override
20+
public String getTitle() {
21+
return title;
22+
}
23+
24+
public int getDurationInMinutes() {
25+
return durationInMinutes;
26+
}
27+
28+
@Override
29+
public void accept(ContentVisitor visitor) {
30+
visitor.visit(this);
31+
}
32+
}

0 commit comments

Comments
 (0)