Skip to content

Commit 67bea43

Browse files
committed
refactor(oop): simplify customer communication generation and update factory method
Remove Template Patterns and use only Factory Patterns
1 parent ed6af1b commit 67bea43

File tree

6 files changed

+52
-135
lines changed

6 files changed

+52
-135
lines changed
Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,12 @@
11
public abstract class Customer {
2-
/**
3-
* Template method that defines the algorithm for creating a communications
4-
*
5-
* @return the communication
6-
*/
7-
public final String createCommunication() {
8-
StringBuilder communication = new StringBuilder();
9-
communication.append(createMail());
2+
public String generateCommunication() {
3+
String mail = createMail();
4+
String brochure = createBrochure();
105

11-
if (shouldIncludeBrochure()) {
12-
communication.append("\n").append(createBrochure());
13-
}
14-
return communication.toString();
6+
return brochure == null ? mail : mail + "\n" + brochure;
157
}
168

17-
/**
18-
* Abstract method to be implemented by concrete customer types for mail creation
19-
*/
209
protected abstract String createMail();
2110

22-
/**
23-
* Abstract method to be implemented by concrete customer types for brochure creation
24-
*/
2511
protected abstract String createBrochure();
26-
27-
/**
28-
* Hook method that can be overridden by subclasses to control brochure inclusion
29-
*/
30-
protected boolean shouldIncludeBrochure() {
31-
return true;
32-
}
3312
}
Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,9 @@
1-
import java.util.HashMap;
2-
import java.util.Map;
3-
import java.util.function.Supplier;
4-
51
public class CustomerFactory {
6-
private static final Map<String, Supplier<Customer>> CUSTOMER_TYPES = new HashMap<>();
7-
8-
static {
9-
CUSTOMER_TYPES.put("Regular", RegularCustomer::new);
10-
CUSTOMER_TYPES.put("Mountain", MountainCustomer::new);
11-
CUSTOMER_TYPES.put("Delinquent", DelinquentCustomer::new);
12-
}
13-
14-
/**
15-
* Factory method to create customer instances
16-
*
17-
* @param customerType the type of customer to create
18-
* @return Customer instance
19-
* @throws IllegalArgumentException if customer type is not supported
20-
*/
21-
public static Customer createCustomer(String customerType) {
22-
Supplier<Customer> supplier = CUSTOMER_TYPES.get(customerType);
23-
if (supplier == null) {
24-
throw new IllegalArgumentException("Unsupported customer type: " + customerType);
25-
}
26-
return supplier.get();
27-
}
28-
29-
/**
30-
* Register a new customer type
31-
*
32-
* @param type customer type identifier
33-
* @param supplier supplier function to create customer instance
34-
*/
35-
public static void registerCustomerType(String type, Supplier<Customer> supplier) {
36-
CUSTOMER_TYPES.put(type, supplier);
2+
public static Customer createCustomer(CustomerType type) {
3+
return switch (type) {
4+
case REGULAR -> new RegularCustomer();
5+
case MOUNTAIN -> new MountainCustomer();
6+
case DELINQUENT -> new DelinquentCustomer();
7+
};
378
}
389
}
Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,29 @@
1-
import java.util.Objects;
21
import java.util.Scanner;
32

43
public class CustomerMailApplication {
5-
private final Customer customer;
4+
private static final Scanner scanner = new Scanner(System.in);
65

7-
public CustomerMailApplication(Customer customer) {
8-
this.customer = Objects.requireNonNull(customer, "Customer cannot be null");
9-
}
10-
11-
public static String getCustomerTypeFromUser() {
12-
try (Scanner scanner = new Scanner(System.in)) {
13-
System.out.print("Please choose customer type 1. Regular, 2. Mountain, 3. Delinquent ");
14-
int type = scanner.nextInt();
15-
16-
return switch (type) {
17-
case 1 -> "Regular";
18-
case 2 -> "Mountain";
19-
case 3 -> "Delinquent";
20-
default -> throw new IllegalArgumentException("Invalid customer type: " + type);
21-
};
22-
}
23-
}
6+
private static CustomerType getCustomerTypeFromUser() {
7+
System.out.print("Please choose customer type 1. Regular, 2. Mountain, 3. Delinquent: ");
8+
int choice = scanner.nextInt();
249

25-
public String generateCommunication() {
26-
return customer.createCommunication();
10+
return switch (choice) {
11+
case 1 -> CustomerType.REGULAR;
12+
case 2 -> CustomerType.MOUNTAIN;
13+
case 3 -> CustomerType.DELINQUENT;
14+
default -> throw new IllegalArgumentException("Invalid choice");
15+
};
2716
}
2817

2918
public static void main(String[] args) {
3019
try {
31-
String customerType = getCustomerTypeFromUser();
32-
Customer customer = CustomerFactory.createCustomer(customerType);
33-
CustomerMailApplication app = new CustomerMailApplication(customer);
34-
System.out.println(app.generateCommunication());
35-
} catch (Exception e) {
36-
System.err.println("An error occurred: " + e.getMessage());
20+
CustomerType type = getCustomerTypeFromUser();
21+
Customer customer = CustomerFactory.createCustomer(type);
22+
System.out.println(customer.generateCommunication());
23+
} catch (IllegalArgumentException e) {
24+
System.out.println(e.getMessage());
25+
} finally {
26+
scanner.close();
3727
}
3828
}
3929
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public enum CustomerType {
2+
REGULAR, MOUNTAIN, DELINQUENT
3+
}

Design-Patterns-in-OOP/05-lab/customer-email-app/DelinquentCustomer.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ protected String createMail() {
66

77
@Override
88
protected String createBrochure() {
9-
return "Delinquent Customer Brochure";
10-
}
11-
12-
@Override
13-
protected boolean shouldIncludeBrochure() {
14-
return false; // Delinquent customers don't receive brochures
9+
return null; // Delinquent customers don't receive brochures
1510
}
1611
}
Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,39 @@
11
# Explaining the use of Design Patterns in customer emails
22

3-
## Design Patterns used in the system
3+
## Design Pattern used in the system
44

5-
### 1. Template Method Pattern
5+
### Factory Method Pattern
66

77
#### Usage
88

9-
Pattern นี้ถูกใช้ในคลาส `Customer` เพื่อกำหนดโครงสร้างการสร้างการสื่อสารกับลูกค้า
9+
Pattern นี้ถูกใช้ในการสร้างออบเจ็กต์ของ Customer แต่ละประเภท โดยแยกส่วนการสร้างออบเจ็กต์ออกจากส่วนที่ใช้งาน
1010

1111
#### Components
1212

13-
- **Template Method**: `createCommunication()` ในคลาส `Customer`
13+
- **Abstract Product**: `Customer` (Abstract Class)
1414

15-
- กำหนดลำดับขั้นตอนการทำงานหลัก
16-
- เรียกใช้ `createMail()` และ `createBrochure()`
17-
- ควบคุมการแสดงผลรวม
15+
- กำหนด abstract method `createMail()` ที่ลูกทุกคลาสต้องนำไป implement
1816

19-
- **Abstract Methods**:
17+
- **Concrete Products**:
2018

21-
- `createMail()` - เมธอดที่คลาสลูกต้องกำหนดวิธีการสร้างจดหมาย
22-
- `createBrochure()` - เมธอดที่คลาสลูกต้องกำหนดวิธีการสร้างโบรชัวร์
19+
- `RegularCustomer` - สำหรับลูกค้าทั่วไป
20+
- `MountainCustomer` - สำหรับลูกค้าแถบภูเขา
21+
- `DelinquentCustomer` - สำหรับลูกค้าที่ค้างชำระ
2322

24-
- **Hook Method**:
25-
- `shouldIncludeBrochure()` - ให้คลาสลูกควบคุมว่าจะรวมโบรชัวร์หรือไม่
26-
- ตัวอย่างการใช้: คลาส `DelinquentCustomer` override เพื่อไม่ส่งโบรชัวร์
23+
- **Factory Class**: `CustomerMailApplication`
24+
- มีเมธอด `getCustomerTypeFromUser()` สำหรับรับประเภทลูกค้าจากผู้ใช้
25+
- สร้างออบเจ็กต์ Customer ตามประเภทที่ผู้ใช้เลือก
2726

2827
#### Benefits
2928

30-
- แยกส่วนที่เหมือนกันไว้ใน parent class ลดการเขียนโค้ดซ้ำ
31-
- child class สามารถปรับเปลี่ยนเฉพาะส่วนที่ต้องการได้
32-
- รักษาโครงสร้างการทำงานหลักให้เหมือนกันทุกประเภทลูกค้า
29+
- แยกการสร้างออบเจ็กต์ออกจากส่วนที่ใช้งาน ทำให้โค้ดมีความยืดหยุ่น
30+
- สามารถเพิ่มประเภทลูกค้าใหม่ได้โดยไม่ต้องแก้ไขโค้ดเดิม
31+
- โค้ดส่วนที่ใช้งานไม่จำเป็นต้องรู้รายละเอียดการสร้างออบเจ็กต์
32+
- ทำให้ระบบรองรับการขยายตัวในอนาคตได้ง่าย
3333

34-
### 2. Factory Pattern
34+
#### How the system works
3535

36-
#### Usage
37-
38-
Pattern นี้ถูกใช้ในคลาส `CustomerFactory` เพื่อจัดการการสร้างอ็อบเจกต์ลูกค้าประเภทต่างๆ
39-
40-
#### Components
41-
42-
- **Factory Class**: `CustomerFactory`
43-
- มีเมธอด `createCustomer()` สำหรับสร้างอ็อบเจกต์ลูกค้า
44-
- ใช้ Map เก็บความสัมพันธ์ระหว่างประเภทลูกค้ากับวิธีการสร้าง
45-
- มีเมธอด `registerCustomerType()` สำหรับเพิ่มประเภทลูกค้าใหม่
46-
47-
#### Benefits
48-
49-
- แยกการสร้างอ็อบเจกต์ออกจาก Usage
50-
- รองรับการเพิ่มประเภทลูกค้าใหม่โดยไม่ต้องแก้ไขโค้ดเดิม
51-
- ลดการเชื่อมโยงระหว่างโค้ดที่ใช้งานกับคลาสลูกค้าแต่ละประเภท
52-
53-
## How Design Patterns work together
54-
55-
Design Patterns ทั้งสองทำงานร่วมกันดังนี้:
56-
57-
1. `CustomerFactory` สร้างอ็อบเจกต์ลูกค้าประเภทที่ต้องการ
58-
2. อ็อบเจกต์ที่สร้างขึ้นใช้ Template Method Pattern ในการสร้างการสื่อสาร
59-
3. แต่ละประเภทลูกค้ากำหนดรายละเอียดเฉพาะของตนเองผ่าน abstract methods
60-
4. การควบคุมพิเศษ (เช่น การไม่ส่งโบรชัวร์) ทำได้ผ่าน hook method
36+
1. ผู้ใช้เลือกประเภทลูกค้าผ่านเมธอด `getCustomerTypeFromUser()`
37+
2. ระบบสร้างออบเจ็กต์ Customer ตามประเภทที่เลือก
38+
3. เรียกใช้เมธอด `createMail()` เพื่อสร้างข้อความสำหรับลูกค้าแต่ละประเภท
39+
4. แสดงผลข้อความที่สร้างขึ้น

0 commit comments

Comments
 (0)