В чём разница между библиотекой, утилитой и компонентом
Библиотека — это набор классов, который позволяет выполнить полезные действия путём обращения к API этого набора.
Программная утилита — это библиотека + точка запуска, которая выполняет полезные действия путём обращения к API этой библиотеки.
Компонент — это библиотека + точка запуска, которая экспонирует API этой библиотеки.
Под программной утилитой здесь подразумевается не утилитарный java-класс, а программа, которая обычно вызывается в консоли. Примером такой утилиты может быть mvn.
Ниже рассмотрим три примера.
Библиотека:
public class Dice {
public int roll() {
return (int) (Math.random() * 6 + 1);
}
}
Библиотека состоит из одного класса Dice и позволяет бросать кубик. Метод roll составляет API библиотеки. Точка запуска, то есть метод main, отсутствует.
Программная утилита:
public class Launcher {
public static void main(String[] args) {
var dice = new Dice();
System.out.print(dice.roll());
}
}
public class Dice {
public int roll() {
return (int) (Math.random() * 6 + 1);
}
}
Класс Launcher содержит точку запуска — метод main, — которая обращается к API библиотеки, то есть к методу roll, и выводит результат в консоль. В отличие от библиотеки, которая предполагает только встраивание её в какой-то другой код, утилита предполагает наличие клиента — человека или другой программы, — который вызывает её ради получения результата.
Вызвать такую утилиту можно из консоли:
java -cp . Launcher
Чтобы бросить кубик ещё раз, утилиту нужно запускать заново.
Компонент:
import java.util.Scanner;
public class Launcher {
public static void main(String[] args) {
var dice = new Dice();
var in = new Scanner(System.in);
var out = System.out;
while (in.hasNextLine()) {
in.nextLine();
out.print(dice.roll()); // Exposing method `roll`
}
}
}
public class Dice {
public int roll() {
return (int) (Math.random() * 6 + 1);
}
}
Здесь точка запуска не вызывает API ради разового результата, а экспонирует его: программа разворачивается в памяти и делает бросок кубика доступным через стандартный протокол ввода-вывода. После запуска бросать кубик можно сколько угодно раз.
API библиотеки можно выставить и через транспортный протокол:
import java.util.Scanner;
import java.net.ServerSocket;
import java.io.PrintWriter;
import java.io.IOException;
public class Launcher {
public static void main(String[] args) throws IOException {
var server = new ServerSocket(5000); // Exposing the facade
var client = server.accept();
var dice = new Dice();
var in = new Scanner(client.getInputStream()); // Instead of System.in
var out = new PrintWriter(client.getOutputStream(), true); // Instead of System.out
while (in.hasNextLine()) {
in.nextLine();
out.print(dice.roll());
}
}
}
Код намеренно упрощён: за весь жизненный цикл к серверу может подключиться только один клиент, но в рамках этого подключения он может бросать кубик сколько угодно раз.
Опираясь на изложенную разницу, можно дать следующее определение компоненту. Компонент — это библиотека, у которой есть точка запуска, через которую другие компоненты могут получить доступ к её возможностям.