Factory: Notification Sender
Problem
Each input line is a channel (email, sms or push) and a message. Print the message with a prefix: Email: , SMS: or Push: . For any other channel print Unknown channel: followed by the channel name. Use a factory that creates the right sender object.
Constraints
- 1 <= lines <= 10^4
Examples
Input
email hello world fax hi
Output
Email: hello world Unknown channel: fax
Solutions
The loop never says new EmailSender(). When a new channel is added, only the factory changes.
/*
* Problem : Process lines.
* Input : Several lines.
* Output : One line per message.
* Approach: Factory returns objects.
* Time : O(n)
* Space : O(n)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: Every sender has the same method, so the caller does not need to know the real class.
interface Sender {
String send(String message);
}
static class EmailSender implements Sender {
public String send(String message) {
return "Email: " + message;
}
}
static class SmsSender implements Sender {
public String send(String message) {
return "SMS: " + message;
}
}
static class PushSender implements Sender {
public String send(String message) {
return "Push: " + message;
}
}
// Step 2: The factory method chooses the class. It returns null for an unknown channel.
static Sender create(String channel) {
switch (channel) {
case "email":
return new EmailSender();
case "sms":
return new SmsSender();
case "push":
return new PushSender();
default:
return null;
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(String[] lines) {
String[] output = new String[lines.length];
for (int i = 0; i < lines.length; i++) {
// Step 3: Split at the first space. The channel is the first word. The message is the rest.
String[] parts = lines[i].split(" ", 2);
// Step 4: Ask the factory for a sender. We use the sender without knowing its class.
Sender sender = create(parts[0]);
output[i] = sender == null ? "Unknown channel: " + parts[0] : sender.send(parts[1]);
}
return output;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
all.add(line);
}
}
String[] lines = all.toArray(new String[0]);
System.out.println(String.join("\n", solve(lines)));
}
}
Hints (1)
- Which part of the program knows the concrete classes?