From c2f03c2c2878be0a610039e2025f60656a0fb7a0 Mon Sep 17 00:00:00 2001 From: Alexander Shvets Date: Mon, 7 Feb 2022 17:39:40 +0200 Subject: [PATCH 01/45] Content fixes. --- .../facade/example/facade/VideoConversionFacade.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java b/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java index 6fd94cb..5ae11d0 100644 --- a/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java +++ b/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java @@ -11,9 +11,9 @@ public File convertVideo(String fileName, String format) { Codec sourceCodec = CodecFactory.extract(file); Codec destinationCodec; if (format.equals("mp4")) { - destinationCodec = new OggCompressionCodec(); - } else { destinationCodec = new MPEG4CompressionCodec(); + } else { + destinationCodec = new OggCompressionCodec(); } VideoFile buffer = BitrateReader.read(file, sourceCodec); VideoFile intermediateResult = BitrateReader.convert(buffer, destinationCodec); From 71fe14bddb601ba5d9c02403992a96b3845e25aa Mon Sep 17 00:00:00 2001 From: Alexander Shvets Date: Tue, 19 Jul 2022 19:11:17 +0200 Subject: [PATCH 02/45] Content update. --- .../chain_of_responsibility/example/Demo.java | 8 +++++--- .../chain_of_responsibility/example/OutputDemo.txt | 13 +++++++++---- .../example/middleware/Middleware.java | 10 +++++++--- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/refactoring_guru/chain_of_responsibility/example/Demo.java b/src/refactoring_guru/chain_of_responsibility/example/Demo.java index c81522b..1934e61 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/Demo.java +++ b/src/refactoring_guru/chain_of_responsibility/example/Demo.java @@ -29,9 +29,11 @@ private static void init() { // // RU: Проверки связаны в одну цепь. Клиент может строить различные // цепи, используя одни и те же компоненты. - Middleware middleware = new ThrottlingMiddleware(2); - middleware.linkWith(new UserExistsMiddleware(server)) - .linkWith(new RoleCheckMiddleware()); + Middleware middleware = Middleware.link( + new ThrottlingMiddleware(2), + new UserExistsMiddleware(server), + new RoleCheckMiddleware() + ); // EN: Server gets a chain from client code. // diff --git a/src/refactoring_guru/chain_of_responsibility/example/OutputDemo.txt b/src/refactoring_guru/chain_of_responsibility/example/OutputDemo.txt index 2dad162..bda8f06 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/OutputDemo.txt +++ b/src/refactoring_guru/chain_of_responsibility/example/OutputDemo.txt @@ -4,7 +4,12 @@ Hello, admin! Authorization have been successful! -Enter email: user@example.com -Input password: user_pass -Hello, user! -Authorization have been successful! \ No newline at end of file +Enter email: wrong@example.com +Input password: wrong_pass +This email is not registered! +Enter email: wrong@example.com +Input password: wrong_pass +This email is not registered! +Enter email: wrong@example.com +Input password: wrong_pass +Request limit exceeded! \ No newline at end of file diff --git a/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java b/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java index e3ac1a7..bd4d7bf 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java +++ b/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java @@ -13,9 +13,13 @@ public abstract class Middleware { * * RU: Помогает строить цепь из объектов-проверок. */ - public Middleware linkWith(Middleware next) { - this.next = next; - return next; + public static Middleware link(Middleware first, Middleware... chain) { + Middleware head = first; + for (Middleware nextInChain: chain) { + head.next = nextInChain; + head = nextInChain; + } + return first; } /** From 9cb5c49694b90a6ce8901a3c27c1e03b73645dc5 Mon Sep 17 00:00:00 2001 From: ayush-m Date: Sun, 7 Aug 2022 16:19:56 +0530 Subject: [PATCH 03/45] Refractored Application Creation --- src/refactoring_guru/abstract_factory/example/Demo.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/refactoring_guru/abstract_factory/example/Demo.java b/src/refactoring_guru/abstract_factory/example/Demo.java index b3587da..e732848 100644 --- a/src/refactoring_guru/abstract_factory/example/Demo.java +++ b/src/refactoring_guru/abstract_factory/example/Demo.java @@ -26,11 +26,10 @@ private static Application configureApplication() { String osName = System.getProperty("os.name").toLowerCase(); if (osName.contains("mac")) { factory = new MacOSFactory(); - app = new Application(factory); } else { factory = new WindowsFactory(); - app = new Application(factory); } + app = new Application(factory); return app; } From f2d312243c9fb1d465860b37c42ff253bbd1f2db Mon Sep 17 00:00:00 2001 From: Nurmukhammed <76807326+nuromirzak@users.noreply.github.com> Date: Mon, 14 Nov 2022 22:27:47 +0600 Subject: [PATCH 04/45] fix: remove redundant package name before class Since "Shape" is a public interface, we don't need to explicitly specify the package name before the class. I think this will make the code a little cleaner. --- .../composite/example/shapes/CompoundShape.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/refactoring_guru/composite/example/shapes/CompoundShape.java b/src/refactoring_guru/composite/example/shapes/CompoundShape.java index fd84982..ee9562a 100644 --- a/src/refactoring_guru/composite/example/shapes/CompoundShape.java +++ b/src/refactoring_guru/composite/example/shapes/CompoundShape.java @@ -132,7 +132,7 @@ public void paint(Graphics graphics) { disableSelectionStyle(graphics); } - for (refactoring_guru.composite.example.shapes.Shape child : children) { + for (Shape child : children) { child.paint(graphics); } } From f4992cbc05ffab9d527b1e8fb4649ae7673a5920 Mon Sep 17 00:00:00 2001 From: Nurmukhammed <76807326+nuromirzak@users.noreply.github.com> Date: Mon, 14 Nov 2022 23:35:27 +0600 Subject: [PATCH 05/45] remove the C-style array declaration --- src/refactoring_guru/composite/example/shapes/BaseShape.java | 2 +- src/refactoring_guru/memento/example/shapes/BaseShape.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/refactoring_guru/composite/example/shapes/BaseShape.java b/src/refactoring_guru/composite/example/shapes/BaseShape.java index bd5921a..f0f5552 100644 --- a/src/refactoring_guru/composite/example/shapes/BaseShape.java +++ b/src/refactoring_guru/composite/example/shapes/BaseShape.java @@ -65,7 +65,7 @@ void enableSelectionStyle(Graphics graphics) { graphics.setColor(Color.LIGHT_GRAY); Graphics2D g2 = (Graphics2D) graphics; - float dash1[] = {2.0f}; + float[] dash1 = {2.0f}; g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, diff --git a/src/refactoring_guru/memento/example/shapes/BaseShape.java b/src/refactoring_guru/memento/example/shapes/BaseShape.java index 4214765..3433329 100644 --- a/src/refactoring_guru/memento/example/shapes/BaseShape.java +++ b/src/refactoring_guru/memento/example/shapes/BaseShape.java @@ -93,7 +93,7 @@ void enableSelectionStyle(Graphics graphics) { graphics.setColor(Color.LIGHT_GRAY); Graphics2D g2 = (Graphics2D) graphics; - float dash1[] = {2.0f}; + float[] dash1 = {2.0f}; g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, From a6e49c3d60b4ac572233447f0fb91672c51e309c Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Mon, 25 Sep 2023 14:31:27 +0300 Subject: [PATCH 06/45] reformatted code to adhere to Java standards & fixed static access for "EXIT_ON_CLOSE" --- .../factory_method/example/Demo.java | 62 +++++++++---------- .../example/buttons/Button.java | 7 ++- .../example/buttons/HtmlButton.java | 16 ++--- .../example/buttons/WindowsButton.java | 58 ++++++++--------- .../example/factory/Dialog.java | 32 +++++----- .../example/factory/HtmlDialog.java | 10 +-- .../example/factory/WindowsDialog.java | 10 +-- 7 files changed, 96 insertions(+), 99 deletions(-) diff --git a/src/refactoring_guru/factory_method/example/Demo.java b/src/refactoring_guru/factory_method/example/Demo.java index dde90cf..0b4ed7a 100644 --- a/src/refactoring_guru/factory_method/example/Demo.java +++ b/src/refactoring_guru/factory_method/example/Demo.java @@ -6,42 +6,42 @@ /** * EN: Demo class. Everything comes together here. - * + *

* RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - private static Dialog dialog; + private static Dialog dialog; - public static void main(String[] args) { - configure(); - runBusinessLogic(); - } + public static void main(String[] args) { + configure(); + runBusinessLogic(); + } - /** - * EN: The concrete factory is usually chosen depending on configuration or - * environment options. - * - * RU: Приложение создаёт определённую фабрику в зависимости от конфигурации - * или окружения. - */ - static void configure() { - if (System.getProperty("os.name").equals("Windows 10")) { - dialog = new WindowsDialog(); - } else { - dialog = new HtmlDialog(); - } + /** + * EN: The concrete factory is usually chosen depending on configuration or + * environment options. + *

+ * RU: Приложение создаёт определённую фабрику в зависимости от конфигурации + * или окружения. + */ + static void configure() { + if (System.getProperty("os.name").equals("Windows 10")) { + dialog = new WindowsDialog(); + } else { + dialog = new HtmlDialog(); } + } - /** - * EN: All of the client code should work with factories and products - * through abstract interfaces. This way it does not care which factory it - * works with and what kind of product it returns. - * - * RU: Весь остальной клиентский код работает с фабрикой и продуктами только - * через общий интерфейс, поэтому для него неважно какая фабрика была - * создана. - */ - static void runBusinessLogic() { - dialog.renderWindow(); - } + /** + * EN: All of the client code should work with factories and products + * through abstract interfaces. This way it does not care which factory it + * works with and what kind of product it returns. + *

+ * RU: Весь остальной клиентский код работает с фабрикой и продуктами только + * через общий интерфейс, поэтому для него неважно какая фабрика была + * создана. + */ + static void runBusinessLogic() { + dialog.renderWindow(); + } } diff --git a/src/refactoring_guru/factory_method/example/buttons/Button.java b/src/refactoring_guru/factory_method/example/buttons/Button.java index 02bef0f..1ae0454 100644 --- a/src/refactoring_guru/factory_method/example/buttons/Button.java +++ b/src/refactoring_guru/factory_method/example/buttons/Button.java @@ -2,10 +2,11 @@ /** * EN: Common interface for all buttons. - * + *

* RU: Общий интерфейс для всех продуктов. */ public interface Button { - void render(); - void onClick(); + void render(); + + void onClick(); } diff --git a/src/refactoring_guru/factory_method/example/buttons/HtmlButton.java b/src/refactoring_guru/factory_method/example/buttons/HtmlButton.java index ee44f0b..e5d480f 100644 --- a/src/refactoring_guru/factory_method/example/buttons/HtmlButton.java +++ b/src/refactoring_guru/factory_method/example/buttons/HtmlButton.java @@ -2,17 +2,17 @@ /** * EN: HTML button implementation. - * + *

* RU: Реализация HTML кнопок. */ public class HtmlButton implements Button { - public void render() { - System.out.println(""); - onClick(); - } + public void render() { + System.out.println(""); + onClick(); + } - public void onClick() { - System.out.println("Click! Button says - 'Hello World!'"); - } + public void onClick() { + System.out.println("Click! Button says - 'Hello World!'"); + } } diff --git a/src/refactoring_guru/factory_method/example/buttons/WindowsButton.java b/src/refactoring_guru/factory_method/example/buttons/WindowsButton.java index 5ad5a03..347946b 100644 --- a/src/refactoring_guru/factory_method/example/buttons/WindowsButton.java +++ b/src/refactoring_guru/factory_method/example/buttons/WindowsButton.java @@ -2,44 +2,40 @@ import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; /** * EN: Windows button implementation. - * + *

* RU: Реализация нативных кнопок операционной системы. */ public class WindowsButton implements Button { - JPanel panel = new JPanel(); - JFrame frame = new JFrame(); - JButton button; + JPanel panel = new JPanel(); + JFrame frame = new JFrame(); + JButton button; - public void render() { - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - JLabel label = new JLabel("Hello World!"); - label.setOpaque(true); - label.setBackground(new Color(235, 233, 126)); - label.setFont(new Font("Dialog", Font.BOLD, 44)); - label.setHorizontalAlignment(SwingConstants.CENTER); - panel.setLayout(new FlowLayout(FlowLayout.CENTER)); - frame.getContentPane().add(panel); - panel.add(label); - onClick(); - panel.add(button); + public void render() { + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + JLabel label = new JLabel("Hello World!"); + label.setOpaque(true); + label.setBackground(new Color(235, 233, 126)); + label.setFont(new Font("Dialog", Font.BOLD, 44)); + label.setHorizontalAlignment(SwingConstants.CENTER); + panel.setLayout(new FlowLayout(FlowLayout.CENTER)); + frame.getContentPane().add(panel); + panel.add(label); + onClick(); + panel.add(button); - frame.setSize(320, 200); - frame.setVisible(true); - onClick(); - } + frame.setSize(320, 200); + frame.setVisible(true); + onClick(); + } - public void onClick() { - button = new JButton("Exit"); - button.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - frame.setVisible(false); - System.exit(0); - } - }); - } + public void onClick() { + button = new JButton("Exit"); + button.addActionListener(e -> { + frame.setVisible(false); + System.exit(0); + }); + } } diff --git a/src/refactoring_guru/factory_method/example/factory/Dialog.java b/src/refactoring_guru/factory_method/example/factory/Dialog.java index 3e6fcc3..33bcd4f 100644 --- a/src/refactoring_guru/factory_method/example/factory/Dialog.java +++ b/src/refactoring_guru/factory_method/example/factory/Dialog.java @@ -6,28 +6,28 @@ * EN: Base factory class. Note that "factory" is merely a role for the class. * It should have some core business logic which needs different products to be * created. - * + *

* RU: Базовый класс фабрики. Заметьте, что "фабрика" – это всего лишь * дополнительная роль для класса. Он уже имеет какую-то бизнес-логику, в * которой требуется создание разнообразных продуктов. */ public abstract class Dialog { - public void renderWindow() { - // EN: ... other code ... - // - // RU: ... остальной код диалога ... + public void renderWindow() { + // EN: ... other code ... + // + // RU: ... остальной код диалога ... - Button okButton = createButton(); - okButton.render(); - } + Button okButton = createButton(); + okButton.render(); + } - /** - * EN: Subclasses will override this method in order to create specific - * button objects. - * - * RU: Подклассы будут переопределять этот метод, чтобы создавать конкретные - * объекты продуктов, разные для каждой фабрики. - */ - public abstract Button createButton(); + /** + * EN: Subclasses will override this method in order to create specific + * button objects. + *

+ * RU: Подклассы будут переопределять этот метод, чтобы создавать конкретные + * объекты продуктов, разные для каждой фабрики. + */ + public abstract Button createButton(); } diff --git a/src/refactoring_guru/factory_method/example/factory/HtmlDialog.java b/src/refactoring_guru/factory_method/example/factory/HtmlDialog.java index ceaac8b..0983611 100644 --- a/src/refactoring_guru/factory_method/example/factory/HtmlDialog.java +++ b/src/refactoring_guru/factory_method/example/factory/HtmlDialog.java @@ -5,13 +5,13 @@ /** * EN: HTML Dialog will produce HTML buttons. - * + *

* RU: HTML-диалог. */ public class HtmlDialog extends Dialog { - @Override - public Button createButton() { - return new HtmlButton(); - } + @Override + public Button createButton() { + return new HtmlButton(); + } } diff --git a/src/refactoring_guru/factory_method/example/factory/WindowsDialog.java b/src/refactoring_guru/factory_method/example/factory/WindowsDialog.java index 3dd8f51..c6defc1 100644 --- a/src/refactoring_guru/factory_method/example/factory/WindowsDialog.java +++ b/src/refactoring_guru/factory_method/example/factory/WindowsDialog.java @@ -5,13 +5,13 @@ /** * EN: Windows Dialog will produce Windows buttons. - * + *

* RU: Диалог на элементах операционной системы. */ public class WindowsDialog extends Dialog { - @Override - public Button createButton() { - return new WindowsButton(); - } + @Override + public Button createButton() { + return new WindowsButton(); + } } From 34008a0c44c370344091dd4fea85bf4e9284b516 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Mon, 25 Sep 2023 14:42:30 +0300 Subject: [PATCH 07/45] fixed some issues in README.md --- README.md | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 25603de..b91f891 100644 --- a/README.md +++ b/README.md @@ -34,16 +34,14 @@ Here's a style guide which might help you to keep your changes consistent with o 1. All code should meet the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html) -2. Try to hard wrap the code at 80th's character. It helps to list the code on the website without scrollbars. +2. Try to wrap the code at 80th's character. It helps to list the code on the website without scrollbars. -3. Examples should match following package convention: refactoring_guru.{pattern}.{example_name}. Example: +3. Examples should match the following package convention: refactoring_guru.{pattern}.{example_name}. Example: ```java package refactoring_guru.factory_method.ui_example.buttons; - class Button { - ... - ``` + class Button { ... } 4. Places classes into separate files. @@ -52,29 +50,25 @@ Here's a style guide which might help you to keep your changes consistent with o ```java package refactoring_guru.factory_method.example.buttons; - class Button { - ... - ``` - - ```java + class Button { ... } + + ```java package refactoring_guru.factory_method.example.factories; import Button; - class Factory { - ... - ``` + class Factory { ... } 6. Comments may or may not have language tags in them, such as this: ```java /** * EN: All products families have the same varieties (MacOS/Windows). - * + *

* This is a MacOS variant of a button. - * + *

* RU: Все семейства продуктов имеют одни и те же вариации (MacOS/Windows). - * + *

* Это вариант кнопки под MacOS. */ ``` From cff8687b9a482f008cd7661ab116df7b7b4c12e5 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Mon, 25 Sep 2023 16:33:09 +0300 Subject: [PATCH 08/45] fixed some issue in README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index b91f891..332d61d 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,6 @@ Here's a style guide which might help you to keep your changes consistent with o class Button { ... } - ```java package refactoring_guru.factory_method.example.factories; import Button; From 04e6bf88d9999f6fa070839337ea5647faa12caa Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Tue, 26 Sep 2023 10:50:11 +0300 Subject: [PATCH 09/45] simplified print method --- .../builder/example/cars/Manual.java | 60 ++++++++----------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/src/refactoring_guru/builder/example/cars/Manual.java b/src/refactoring_guru/builder/example/cars/Manual.java index 466ea8d..236366e 100644 --- a/src/refactoring_guru/builder/example/cars/Manual.java +++ b/src/refactoring_guru/builder/example/cars/Manual.java @@ -8,44 +8,36 @@ /** * EN: Car manual is another product. Note that it does not have the same * ancestor as a Car. They are not related. - * + *

* RU: Руководство автомобиля — это второй продукт. Заметьте, что руководство и * сам автомобиль не имеют общего родительского класса. По сути, они независимы. */ public class Manual { - private final CarType carType; - private final int seats; - private final Engine engine; - private final Transmission transmission; - private final TripComputer tripComputer; - private final GPSNavigator gpsNavigator; + private final CarType carType; + private final int seats; + private final Engine engine; + private final Transmission transmission; + private final TripComputer tripComputer; + private final GPSNavigator gpsNavigator; - public Manual(CarType carType, int seats, Engine engine, Transmission transmission, - TripComputer tripComputer, GPSNavigator gpsNavigator) { - this.carType = carType; - this.seats = seats; - this.engine = engine; - this.transmission = transmission; - this.tripComputer = tripComputer; - this.gpsNavigator = gpsNavigator; - } + public Manual(CarType carType, int seats, Engine engine, Transmission transmission, + TripComputer tripComputer, GPSNavigator gpsNavigator) { + this.carType = carType; + this.seats = seats; + this.engine = engine; + this.transmission = transmission; + this.tripComputer = tripComputer; + this.gpsNavigator = gpsNavigator; + } - public String print() { - String info = ""; - info += "Type of car: " + carType + "\n"; - info += "Count of seats: " + seats + "\n"; - info += "Engine: volume - " + engine.getVolume() + "; mileage - " + engine.getMileage() + "\n"; - info += "Transmission: " + transmission + "\n"; - if (this.tripComputer != null) { - info += "Trip Computer: Functional" + "\n"; - } else { - info += "Trip Computer: N/A" + "\n"; - } - if (this.gpsNavigator != null) { - info += "GPS Navigator: Functional" + "\n"; - } else { - info += "GPS Navigator: N/A" + "\n"; - } - return info; - } + public String print() { + return String.join("\n", + "Type of car: " + carType, + "Count of seats: " + seats, + "Engine: volume - " + engine.getVolume() + "; mileage - " + engine.getMileage(), + "Transmission: " + transmission, + "Trip Computer: " + (tripComputer != null ? "Functional" : "N/A"), + "GPS Navigator: " + (gpsNavigator != null ? "Functional" : "N/A") + ); + } } From f30659d99710b7e827aa2fde18553061395771dd Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Sun, 1 Oct 2023 11:37:25 +0300 Subject: [PATCH 10/45] some minor updates of abstract factory --- .../abstract_factory/example/Demo.java | 44 +++++++++++-------- .../example/app/Application.java | 22 +++++----- .../example/buttons/Button.java | 8 ++-- .../example/buttons/MacOSButton.java | 14 +++--- .../example/buttons/WindowsButton.java | 14 +++--- .../example/checkboxes/Checkbox.java | 4 +- .../example/checkboxes/MacOSCheckbox.java | 14 +++--- .../example/checkboxes/WindowsCheckbox.java | 14 +++--- .../example/factories/GUIFactory.java | 7 +-- .../example/factories/MacOSFactory.java | 18 ++++---- .../example/factories/WindowsFactory.java | 18 ++++---- 11 files changed, 92 insertions(+), 85 deletions(-) diff --git a/src/refactoring_guru/abstract_factory/example/Demo.java b/src/refactoring_guru/abstract_factory/example/Demo.java index e732848..bbecf84 100644 --- a/src/refactoring_guru/abstract_factory/example/Demo.java +++ b/src/refactoring_guru/abstract_factory/example/Demo.java @@ -7,34 +7,40 @@ /** * EN: Demo class. Everything comes together here. - * + *

* RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { + public static void main(String[] args) { + Application app = configureApplication(); + app.paint(); + } /** - * EN: Application picks the factory type and creates it in run time - * (usually at initialization stage), depending on the configuration or - * environment variables. + * EN: Configures the application with the appropriate GUI factory based on the OS. + * Dynamically selects the factory type depending on the current system configuration. + *

+ * RU: Конфигурирует приложение с соответствующей фабрикой GUI на основе ОС. + * Динамически выбирает тип фабрики в зависимости от текущей системной конфигурации. * - * RU: Приложение выбирает тип и создаёт конкретные фабрики динамически - * исходя из конфигурации или окружения. + * @return An instance of the Application configured with the appropriate GUI factory. */ private static Application configureApplication() { - Application app; - GUIFactory factory; - String osName = System.getProperty("os.name").toLowerCase(); - if (osName.contains("mac")) { - factory = new MacOSFactory(); - } else { - factory = new WindowsFactory(); - } - app = new Application(factory); - return app; + GUIFactory factory = getOSGUIFactory(); + return new Application(factory); } - public static void main(String[] args) { - Application app = configureApplication(); - app.paint(); + /** + * EN: Determines the appropriate GUI factory based on the operating system. + * Checks the current system's OS property to decide which factory to instantiate. + *

+ * RU: Определяет соответствующую фабрику GUI на основе операционной системы. + * Проверяет свойство OS текущей системы, чтобы решить, какую фабрику создать. + * + * @return The GUIFactory instance corresponding to the detected operating system. + */ + private static GUIFactory getOSGUIFactory() { + String osName = System.getProperty("os.name").toLowerCase(); + return osName.contains("mac") ? new MacOSFactory() : new WindowsFactory(); } } diff --git a/src/refactoring_guru/abstract_factory/example/app/Application.java b/src/refactoring_guru/abstract_factory/example/app/Application.java index 06db4e9..1a4e7a7 100644 --- a/src/refactoring_guru/abstract_factory/example/app/Application.java +++ b/src/refactoring_guru/abstract_factory/example/app/Application.java @@ -7,22 +7,22 @@ /** * EN: Factory users don't care which concrete factory they use since they work * with factories and products through abstract interfaces. - * + *

* RU: Код, использующий фабрику, не волнует с какой конкретно фабрикой он * работает. Все получатели продуктов работают с продуктами через абстрактный * интерфейс. */ public class Application { - private Button button; - private Checkbox checkbox; + private final Button button; + private final Checkbox checkbox; - public Application(GUIFactory factory) { - button = factory.createButton(); - checkbox = factory.createCheckbox(); - } + public Application(GUIFactory factory) { + button = factory.createButton(); + checkbox = factory.createCheckbox(); + } - public void paint() { - button.paint(); - checkbox.paint(); - } + public void paint() { + button.paint(); + checkbox.paint(); + } } diff --git a/src/refactoring_guru/abstract_factory/example/buttons/Button.java b/src/refactoring_guru/abstract_factory/example/buttons/Button.java index ce81a4f..1fb126d 100644 --- a/src/refactoring_guru/abstract_factory/example/buttons/Button.java +++ b/src/refactoring_guru/abstract_factory/example/buttons/Button.java @@ -4,15 +4,15 @@ * EN: Abstract Factory assumes that you have several families of products, * structured into separate class hierarchies (Button/Checkbox). All products of * the same family have the common interface. - * + *

* This is the common interface for buttons family. - * + *

* RU: Паттерн предполагает, что у вас есть несколько семейств продуктов, * находящихся в отдельных иерархиях классов (Button/Checkbox). Продукты одного * семейства должны иметь общий интерфейс. - * + *

* Это — общий интерфейс для семейства продуктов кнопок. */ public interface Button { - void paint(); + void paint(); } diff --git a/src/refactoring_guru/abstract_factory/example/buttons/MacOSButton.java b/src/refactoring_guru/abstract_factory/example/buttons/MacOSButton.java index 23734f4..3f8e61b 100644 --- a/src/refactoring_guru/abstract_factory/example/buttons/MacOSButton.java +++ b/src/refactoring_guru/abstract_factory/example/buttons/MacOSButton.java @@ -2,17 +2,17 @@ /** * EN: All products families have the same varieties (MacOS/Windows). - * + *

* This is a MacOS variant of a button. - * + *

* RU: Все семейства продуктов имеют одни и те же вариации (MacOS/Windows). - * + *

* Это вариант кнопки под MacOS. */ public class MacOSButton implements Button { - @Override - public void paint() { - System.out.println("You have created MacOSButton."); - } + @Override + public void paint() { + System.out.println("You have created MacOSButton."); + } } diff --git a/src/refactoring_guru/abstract_factory/example/buttons/WindowsButton.java b/src/refactoring_guru/abstract_factory/example/buttons/WindowsButton.java index 00a8990..93b7c77 100644 --- a/src/refactoring_guru/abstract_factory/example/buttons/WindowsButton.java +++ b/src/refactoring_guru/abstract_factory/example/buttons/WindowsButton.java @@ -2,17 +2,17 @@ /** * EN: All products families have the same varieties (MacOS/Windows). - * + *

* This is another variant of a button. - * + *

* RU: Все семейства продуктов имеют одни и те же вариации (MacOS/Windows). - * + *

* Это вариант кнопки под Windows. */ public class WindowsButton implements Button { - @Override - public void paint() { - System.out.println("You have created WindowsButton."); - } + @Override + public void paint() { + System.out.println("You have created WindowsButton."); + } } diff --git a/src/refactoring_guru/abstract_factory/example/checkboxes/Checkbox.java b/src/refactoring_guru/abstract_factory/example/checkboxes/Checkbox.java index df6853a..89938b4 100644 --- a/src/refactoring_guru/abstract_factory/example/checkboxes/Checkbox.java +++ b/src/refactoring_guru/abstract_factory/example/checkboxes/Checkbox.java @@ -3,10 +3,10 @@ /** * EN: Checkboxes is the second product family. It has the same variants as * buttons. - * + *

* RU: Чекбоксы — это второе семейство продуктов. Оно имеет те же вариации, что * и кнопки. */ public interface Checkbox { - void paint(); + void paint(); } diff --git a/src/refactoring_guru/abstract_factory/example/checkboxes/MacOSCheckbox.java b/src/refactoring_guru/abstract_factory/example/checkboxes/MacOSCheckbox.java index 22d5445..59c86ca 100644 --- a/src/refactoring_guru/abstract_factory/example/checkboxes/MacOSCheckbox.java +++ b/src/refactoring_guru/abstract_factory/example/checkboxes/MacOSCheckbox.java @@ -2,17 +2,17 @@ /** * EN: All products families have the same varieties (MacOS/Windows). - * + *

* This is a variant of a checkbox. - * + *

* RU: Все семейства продуктов имеют одинаковые вариации (MacOS/Windows). - * + *

* Вариация чекбокса под MacOS. */ public class MacOSCheckbox implements Checkbox { - @Override - public void paint() { - System.out.println("You have created MacOSCheckbox."); - } + @Override + public void paint() { + System.out.println("You have created MacOSCheckbox."); + } } diff --git a/src/refactoring_guru/abstract_factory/example/checkboxes/WindowsCheckbox.java b/src/refactoring_guru/abstract_factory/example/checkboxes/WindowsCheckbox.java index e5387b4..cef39c6 100644 --- a/src/refactoring_guru/abstract_factory/example/checkboxes/WindowsCheckbox.java +++ b/src/refactoring_guru/abstract_factory/example/checkboxes/WindowsCheckbox.java @@ -2,17 +2,17 @@ /** * EN: All products families have the same varieties (MacOS/Windows). - * + *

* This is another variant of a checkbox. - * + *

* RU: Все семейства продуктов имеют одинаковые вариации (MacOS/Windows). - * + *

* Вариация чекбокса под Windows. */ public class WindowsCheckbox implements Checkbox { - @Override - public void paint() { - System.out.println("You have created WindowsCheckbox."); - } + @Override + public void paint() { + System.out.println("You have created WindowsCheckbox."); + } } diff --git a/src/refactoring_guru/abstract_factory/example/factories/GUIFactory.java b/src/refactoring_guru/abstract_factory/example/factories/GUIFactory.java index 80708ef..4bbbe7d 100644 --- a/src/refactoring_guru/abstract_factory/example/factories/GUIFactory.java +++ b/src/refactoring_guru/abstract_factory/example/factories/GUIFactory.java @@ -5,10 +5,11 @@ /** * EN: Abstract factory knows about all (abstract) product types. - * + *

* RU: Абстрактная фабрика знает обо всех (абстрактных) типах продуктов. */ public interface GUIFactory { - Button createButton(); - Checkbox createCheckbox(); + Button createButton(); + + Checkbox createCheckbox(); } diff --git a/src/refactoring_guru/abstract_factory/example/factories/MacOSFactory.java b/src/refactoring_guru/abstract_factory/example/factories/MacOSFactory.java index 2b957ec..a3d1cf7 100644 --- a/src/refactoring_guru/abstract_factory/example/factories/MacOSFactory.java +++ b/src/refactoring_guru/abstract_factory/example/factories/MacOSFactory.java @@ -8,18 +8,18 @@ /** * EN: Each concrete factory extends basic factory and responsible for creating * products of a single variety. - * + *

* RU: Каждая конкретная фабрика знает и создаёт только продукты своей вариации. */ public class MacOSFactory implements GUIFactory { - @Override - public Button createButton() { - return new MacOSButton(); - } + @Override + public Button createButton() { + return new MacOSButton(); + } - @Override - public Checkbox createCheckbox() { - return new MacOSCheckbox(); - } + @Override + public Checkbox createCheckbox() { + return new MacOSCheckbox(); + } } diff --git a/src/refactoring_guru/abstract_factory/example/factories/WindowsFactory.java b/src/refactoring_guru/abstract_factory/example/factories/WindowsFactory.java index d3475b3..f6d9403 100644 --- a/src/refactoring_guru/abstract_factory/example/factories/WindowsFactory.java +++ b/src/refactoring_guru/abstract_factory/example/factories/WindowsFactory.java @@ -8,18 +8,18 @@ /** * EN: Each concrete factory extends basic factory and responsible for creating * products of a single variety. - * + *

* RU: Каждая конкретная фабрика знает и создаёт только продукты своей вариации. */ public class WindowsFactory implements GUIFactory { - @Override - public Button createButton() { - return new WindowsButton(); - } + @Override + public Button createButton() { + return new WindowsButton(); + } - @Override - public Checkbox createCheckbox() { - return new WindowsCheckbox(); - } + @Override + public Checkbox createCheckbox() { + return new WindowsCheckbox(); + } } From 858ba3ef6e4902407b246d1cd5098bf2db05c955 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Tue, 3 Oct 2023 13:45:30 +0300 Subject: [PATCH 11/45] improve getRadius method --- .../example/adapters/SquarePegAdapter.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/refactoring_guru/adapter/example/adapters/SquarePegAdapter.java b/src/refactoring_guru/adapter/example/adapters/SquarePegAdapter.java index 7f9dfff..df6df48 100644 --- a/src/refactoring_guru/adapter/example/adapters/SquarePegAdapter.java +++ b/src/refactoring_guru/adapter/example/adapters/SquarePegAdapter.java @@ -5,24 +5,25 @@ /** * EN: Adapter allows fitting square pegs into round holes. - * + *

* RU: Адаптер позволяет использовать КвадратныеКолышки и КруглыеОтверстия * вместе. */ public class SquarePegAdapter extends RoundPeg { - private SquarePeg peg; + private final SquarePeg squarePeg; - public SquarePegAdapter(SquarePeg peg) { - this.peg = peg; - } + public SquarePegAdapter(SquarePeg peg) { + this.squarePeg = peg; + } - @Override - public double getRadius() { - double result; - // EN: Calculate a minimum circle radius, which can fit this peg. - // - // RU: Рассчитываем минимальный радиус, в который пролезет этот колышек. - result = (Math.sqrt(Math.pow((peg.getWidth() / 2), 2) * 2)); - return result; - } + /** + * Calculate a minimum circle radius, which can fit this square peg + *

+ * Рассчитываем минимальный радиус, в который пролезет этот колышек. + * @return result of computation + */ + @Override + public double getRadius() { + return (Math.sqrt(Math.pow((squarePeg.width() / 2), 2) * 2)); + } } From 29f9844b3b88c8d22363e18f03a03c19c7ea8951 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Tue, 3 Oct 2023 13:46:03 +0300 Subject: [PATCH 12/45] minor update --- .../adapter/example/round/RoundPeg.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/refactoring_guru/adapter/example/round/RoundPeg.java b/src/refactoring_guru/adapter/example/round/RoundPeg.java index d103827..50565a0 100644 --- a/src/refactoring_guru/adapter/example/round/RoundPeg.java +++ b/src/refactoring_guru/adapter/example/round/RoundPeg.java @@ -2,19 +2,20 @@ /** * EN: RoundPegs are compatible with RoundHoles. - * + *

* RU: КруглыеКолышки совместимы с КруглымиОтверстиями. */ public class RoundPeg { - private double radius; + private double radius; - public RoundPeg() {} + public RoundPeg() { + } - public RoundPeg(double radius) { - this.radius = radius; - } + public RoundPeg(double radius) { + this.radius = radius; + } - public double getRadius() { - return radius; - } + public double getRadius() { + return radius; + } } From 29ad7b429d7db5107541c691e74ed956bcd7e856 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Tue, 3 Oct 2023 13:47:17 +0300 Subject: [PATCH 13/45] convert to a record --- .../adapter/example/round/RoundHole.java | 23 ++++++------------- .../adapter/example/square/SquarePeg.java | 23 ++++++------------- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/src/refactoring_guru/adapter/example/round/RoundHole.java b/src/refactoring_guru/adapter/example/round/RoundHole.java index 35b2025..00d573e 100644 --- a/src/refactoring_guru/adapter/example/round/RoundHole.java +++ b/src/refactoring_guru/adapter/example/round/RoundHole.java @@ -2,23 +2,14 @@ /** * EN: RoundHoles are compatible with RoundPegs. - * + *

* RU: КруглоеОтверстие совместимо с КруглымиКолышками. */ -public class RoundHole { - private double radius; +public record RoundHole(double radius) { - public RoundHole(double radius) { - this.radius = radius; - } - - public double getRadius() { - return radius; - } - - public boolean fits(RoundPeg peg) { - boolean result; - result = (this.getRadius() >= peg.getRadius()); - return result; - } + public boolean fits(RoundPeg peg) { + boolean result; + result = (this.radius() >= peg.getRadius()); + return result; + } } diff --git a/src/refactoring_guru/adapter/example/square/SquarePeg.java b/src/refactoring_guru/adapter/example/square/SquarePeg.java index 57221a2..033639b 100644 --- a/src/refactoring_guru/adapter/example/square/SquarePeg.java +++ b/src/refactoring_guru/adapter/example/square/SquarePeg.java @@ -3,25 +3,16 @@ /** * EN: SquarePegs are not compatible with RoundHoles (they were implemented by * previous development team). But we have to integrate them into our program. - * + *

* RU: КвадратныеКолышки несовместимы с КруглымиОтверстиями (они остались в * проекте после бывших разработчиков). Но мы должны как-то интегрировать их в * нашу систему. */ -public class SquarePeg { - private double width; +public record SquarePeg(double width) { - public SquarePeg(double width) { - this.width = width; - } - - public double getWidth() { - return width; - } - - public double getSquare() { - double result; - result = Math.pow(this.width, 2); - return result; - } + public double getSquare() { + double result; + result = Math.pow(this.width, 2); + return result; + } } From c3d9c0ee8aa74e097d7e5731f30b531992d59235 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Tue, 3 Oct 2023 22:33:59 +0300 Subject: [PATCH 14/45] update adapter demo class --- .../adapter/example/Demo.java | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/refactoring_guru/adapter/example/Demo.java b/src/refactoring_guru/adapter/example/Demo.java index e886891..762bb38 100644 --- a/src/refactoring_guru/adapter/example/Demo.java +++ b/src/refactoring_guru/adapter/example/Demo.java @@ -7,36 +7,37 @@ /** * EN: Somewhere in client code... - * + *

* RU: Где-то в клиентском коде... */ public class Demo { - public static void main(String[] args) { - // EN: Round fits round, no surprise. - // - // RU: Круглое к круглому — всё работает. - RoundHole hole = new RoundHole(5); - RoundPeg rpeg = new RoundPeg(5); - if (hole.fits(rpeg)) { - System.out.println("Round peg r5 fits round hole r5."); - } + public static void main(String[] args) { + demonstrateRoundPegAndHole(); + demonstrateAdapterForSquarePeg(); + } - SquarePeg smallSqPeg = new SquarePeg(2); - SquarePeg largeSqPeg = new SquarePeg(20); - // EN: hole.fits(smallSqPeg); // Won't compile. - // - // RU: hole.fits(smallSqPeg); // Не скомпилируется. + private static void demonstrateRoundPegAndHole() { + RoundHole roundHole = new RoundHole(5); + RoundPeg roundPeg = new RoundPeg(5); - // EN: Adapter solves the problem. - // - // RU: Адаптер решит проблему. - SquarePegAdapter smallSqPegAdapter = new SquarePegAdapter(smallSqPeg); - SquarePegAdapter largeSqPegAdapter = new SquarePegAdapter(largeSqPeg); - if (hole.fits(smallSqPegAdapter)) { - System.out.println("Square peg w2 fits round hole r5."); - } - if (!hole.fits(largeSqPegAdapter)) { - System.out.println("Square peg w20 does not fit into round hole r5."); - } + if (roundHole.fits(roundPeg)) { + System.out.println("Round peg r5 fits round hole r5."); } + } + + private static void demonstrateAdapterForSquarePeg() { + RoundHole roundHole = new RoundHole(5); + + SquarePeg smallSqPeg = new SquarePeg(2); + SquarePegAdapter smallSqPegAdapter = new SquarePegAdapter(smallSqPeg); + if (roundHole.fits(smallSqPegAdapter)) { + System.out.println("Square peg w2 fits round hole r5."); + } + + SquarePeg largeSqPeg = new SquarePeg(20); + SquarePegAdapter largeSqPegAdapter = new SquarePegAdapter(largeSqPeg); + if (!roundHole.fits(largeSqPegAdapter)) { + System.out.println("Square peg w20 does not fit into round hole r5."); + } + } } From d7dbdba1835b2005f7f80574b22f8659ec47a250 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Tue, 3 Oct 2023 22:35:08 +0300 Subject: [PATCH 15/45] minor update --- src/refactoring_guru/bridge/example/Demo.java | 30 ++--- .../bridge/example/devices/Device.java | 16 +-- .../bridge/example/devices/Radio.java | 104 +++++++++--------- .../bridge/example/devices/Tv.java | 104 +++++++++--------- .../example/remotes/AdvancedRemote.java | 16 +-- .../bridge/example/remotes/BasicRemote.java | 81 +++++++------- .../bridge/example/remotes/Remote.java | 10 +- 7 files changed, 177 insertions(+), 184 deletions(-) diff --git a/src/refactoring_guru/bridge/example/Demo.java b/src/refactoring_guru/bridge/example/Demo.java index 6ce44d0..081bf00 100644 --- a/src/refactoring_guru/bridge/example/Demo.java +++ b/src/refactoring_guru/bridge/example/Demo.java @@ -7,21 +7,21 @@ import refactoring_guru.bridge.example.remotes.BasicRemote; public class Demo { - public static void main(String[] args) { - testDevice(new Tv()); - testDevice(new Radio()); - } + public static void main(String[] args) { + testDevice(new Tv()); + testDevice(new Radio()); + } - public static void testDevice(Device device) { - System.out.println("Tests with basic remote."); - BasicRemote basicRemote = new BasicRemote(device); - basicRemote.power(); - device.printStatus(); + public static void testDevice(Device device) { + System.out.println("Tests with basic remote."); + BasicRemote basicRemote = new BasicRemote(device); + basicRemote.power(); + device.printStatus(); - System.out.println("Tests with advanced remote."); - AdvancedRemote advancedRemote = new AdvancedRemote(device); - advancedRemote.power(); - advancedRemote.mute(); - device.printStatus(); - } + System.out.println("Tests with advanced remote."); + AdvancedRemote advancedRemote = new AdvancedRemote(device); + advancedRemote.power(); + advancedRemote.mute(); + device.printStatus(); + } } diff --git a/src/refactoring_guru/bridge/example/devices/Device.java b/src/refactoring_guru/bridge/example/devices/Device.java index 1520dd3..f693e99 100644 --- a/src/refactoring_guru/bridge/example/devices/Device.java +++ b/src/refactoring_guru/bridge/example/devices/Device.java @@ -1,19 +1,19 @@ package refactoring_guru.bridge.example.devices; public interface Device { - boolean isEnabled(); + boolean isEnabled(); - void enable(); + void enable(); - void disable(); + void disable(); - int getVolume(); + int getVolume(); - void setVolume(int percent); + void setVolume(int percent); - int getChannel(); + int getChannel(); - void setChannel(int channel); + void setChannel(int channel); - void printStatus(); + void printStatus(); } diff --git a/src/refactoring_guru/bridge/example/devices/Radio.java b/src/refactoring_guru/bridge/example/devices/Radio.java index b0b227a..0b53929 100644 --- a/src/refactoring_guru/bridge/example/devices/Radio.java +++ b/src/refactoring_guru/bridge/example/devices/Radio.java @@ -1,58 +1,54 @@ package refactoring_guru.bridge.example.devices; public class Radio implements Device { - private boolean on = false; - private int volume = 30; - private int channel = 1; - - @Override - public boolean isEnabled() { - return on; - } - - @Override - public void enable() { - on = true; - } - - @Override - public void disable() { - on = false; - } - - @Override - public int getVolume() { - return volume; - } - - @Override - public void setVolume(int volume) { - if (volume > 100) { - this.volume = 100; - } else if (volume < 0) { - this.volume = 0; - } else { - this.volume = volume; - } - } - - @Override - public int getChannel() { - return channel; - } - - @Override - public void setChannel(int channel) { - this.channel = channel; - } - - @Override - public void printStatus() { - System.out.println("------------------------------------"); - System.out.println("| I'm radio."); - System.out.println("| I'm " + (on ? "enabled" : "disabled")); - System.out.println("| Current volume is " + volume + "%"); - System.out.println("| Current channel is " + channel); - System.out.println("------------------------------------\n"); - } + private boolean on = false; + private int volume = 30; + private int channel = 1; + + @Override + public boolean isEnabled() { + return on; + } + + @Override + public void enable() { + on = true; + } + + @Override + public void disable() { + on = false; + } + + @Override + public int getVolume() { + return volume; + } + + @Override + public void setVolume(int volume) { + if (volume > 100) { + this.volume = 100; + } else this.volume = Math.max(volume, 0); + } + + @Override + public int getChannel() { + return channel; + } + + @Override + public void setChannel(int channel) { + this.channel = channel; + } + + @Override + public void printStatus() { + System.out.println("------------------------------------"); + System.out.println("| I'm radio."); + System.out.println("| I'm " + (on ? "enabled" : "disabled")); + System.out.println("| Current volume is " + volume + "%"); + System.out.println("| Current channel is " + channel); + System.out.println("------------------------------------\n"); + } } diff --git a/src/refactoring_guru/bridge/example/devices/Tv.java b/src/refactoring_guru/bridge/example/devices/Tv.java index b3705cd..9477463 100644 --- a/src/refactoring_guru/bridge/example/devices/Tv.java +++ b/src/refactoring_guru/bridge/example/devices/Tv.java @@ -1,58 +1,54 @@ package refactoring_guru.bridge.example.devices; public class Tv implements Device { - private boolean on = false; - private int volume = 30; - private int channel = 1; - - @Override - public boolean isEnabled() { - return on; - } - - @Override - public void enable() { - on = true; - } - - @Override - public void disable() { - on = false; - } - - @Override - public int getVolume() { - return volume; - } - - @Override - public void setVolume(int volume) { - if (volume > 100) { - this.volume = 100; - } else if (volume < 0) { - this.volume = 0; - } else { - this.volume = volume; - } - } - - @Override - public int getChannel() { - return channel; - } - - @Override - public void setChannel(int channel) { - this.channel = channel; - } - - @Override - public void printStatus() { - System.out.println("------------------------------------"); - System.out.println("| I'm TV set."); - System.out.println("| I'm " + (on ? "enabled" : "disabled")); - System.out.println("| Current volume is " + volume + "%"); - System.out.println("| Current channel is " + channel); - System.out.println("------------------------------------\n"); - } + private boolean on = false; + private int volume = 30; + private int channel = 1; + + @Override + public boolean isEnabled() { + return on; + } + + @Override + public void enable() { + on = true; + } + + @Override + public void disable() { + on = false; + } + + @Override + public int getVolume() { + return volume; + } + + @Override + public void setVolume(int volume) { + if (volume > 100) { + this.volume = 100; + } else this.volume = Math.max(volume, 0); + } + + @Override + public int getChannel() { + return channel; + } + + @Override + public void setChannel(int channel) { + this.channel = channel; + } + + @Override + public void printStatus() { + System.out.println("------------------------------------"); + System.out.println("| I'm TV set."); + System.out.println("| I'm " + (on ? "enabled" : "disabled")); + System.out.println("| Current volume is " + volume + "%"); + System.out.println("| Current channel is " + channel); + System.out.println("------------------------------------\n"); + } } diff --git a/src/refactoring_guru/bridge/example/remotes/AdvancedRemote.java b/src/refactoring_guru/bridge/example/remotes/AdvancedRemote.java index 17c7155..437fadf 100644 --- a/src/refactoring_guru/bridge/example/remotes/AdvancedRemote.java +++ b/src/refactoring_guru/bridge/example/remotes/AdvancedRemote.java @@ -4,12 +4,12 @@ public class AdvancedRemote extends BasicRemote { - public AdvancedRemote(Device device) { - super.device = device; - } - - public void mute() { - System.out.println("Remote: mute"); - device.setVolume(0); - } + public AdvancedRemote(Device device) { + super.device = device; + } + + public void mute() { + System.out.println("Remote: mute"); + device.setVolume(0); + } } diff --git a/src/refactoring_guru/bridge/example/remotes/BasicRemote.java b/src/refactoring_guru/bridge/example/remotes/BasicRemote.java index 5f9dcb4..c0016d8 100644 --- a/src/refactoring_guru/bridge/example/remotes/BasicRemote.java +++ b/src/refactoring_guru/bridge/example/remotes/BasicRemote.java @@ -3,45 +3,46 @@ import refactoring_guru.bridge.example.devices.Device; public class BasicRemote implements Remote { - protected Device device; - - public BasicRemote() {} - - public BasicRemote(Device device) { - this.device = device; - } - - @Override - public void power() { - System.out.println("Remote: power toggle"); - if (device.isEnabled()) { - device.disable(); - } else { - device.enable(); - } - } - - @Override - public void volumeDown() { - System.out.println("Remote: volume down"); - device.setVolume(device.getVolume() - 10); - } - - @Override - public void volumeUp() { - System.out.println("Remote: volume up"); - device.setVolume(device.getVolume() + 10); - } - - @Override - public void channelDown() { - System.out.println("Remote: channel down"); - device.setChannel(device.getChannel() - 1); - } - - @Override - public void channelUp() { - System.out.println("Remote: channel up"); - device.setChannel(device.getChannel() + 1); + protected Device device; + + public BasicRemote() { + } + + public BasicRemote(Device device) { + this.device = device; + } + + @Override + public void power() { + System.out.println("Remote: power toggle"); + if (device.isEnabled()) { + device.disable(); + } else { + device.enable(); } + } + + @Override + public void volumeDown() { + System.out.println("Remote: volume down"); + device.setVolume(device.getVolume() - 10); + } + + @Override + public void volumeUp() { + System.out.println("Remote: volume up"); + device.setVolume(device.getVolume() + 10); + } + + @Override + public void channelDown() { + System.out.println("Remote: channel down"); + device.setChannel(device.getChannel() - 1); + } + + @Override + public void channelUp() { + System.out.println("Remote: channel up"); + device.setChannel(device.getChannel() + 1); + } } diff --git a/src/refactoring_guru/bridge/example/remotes/Remote.java b/src/refactoring_guru/bridge/example/remotes/Remote.java index 0f5e78b..dd7288d 100644 --- a/src/refactoring_guru/bridge/example/remotes/Remote.java +++ b/src/refactoring_guru/bridge/example/remotes/Remote.java @@ -1,13 +1,13 @@ package refactoring_guru.bridge.example.remotes; public interface Remote { - void power(); + void power(); - void volumeDown(); + void volumeDown(); - void volumeUp(); + void volumeUp(); - void channelDown(); + void channelDown(); - void channelUp(); + void channelUp(); } From 4a3db0a2f61bb3df1aaadcc3476a3ee008462b59 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Tue, 3 Oct 2023 22:38:20 +0300 Subject: [PATCH 16/45] minor update --- .../builder/example/Demo.java | 48 ++++------- .../builder/example/builders/Builder.java | 19 ++-- .../builder/example/builders/CarBuilder.java | 80 ++++++++--------- .../example/builders/CarManualBuilder.java | 76 ++++++++-------- .../builder/example/cars/Car.java | 86 +++++++++---------- .../builder/example/cars/CarType.java | 2 +- .../builder/example/components/Engine.java | 68 +++++++-------- .../example/components/GPSNavigator.java | 22 ++--- .../example/components/Transmission.java | 4 +- .../example/components/TripComputer.java | 28 +++--- .../builder/example/director/Director.java | 48 +++++------ 11 files changed, 237 insertions(+), 244 deletions(-) diff --git a/src/refactoring_guru/builder/example/Demo.java b/src/refactoring_guru/builder/example/Demo.java index 6d3f348..f68799f 100644 --- a/src/refactoring_guru/builder/example/Demo.java +++ b/src/refactoring_guru/builder/example/Demo.java @@ -8,42 +8,30 @@ /** * EN: Demo class. Everything comes together here. - * + * EN: Director gets the concrete builder object from the client + * (application code). That's because the application knows better which + * builder to use to get a specific product. + *

* RU: Демо-класс. Здесь всё сводится воедино. + * RU: Директор получает объект конкретного строителя от клиента + * (приложения). Приложение само знает какой строитель использовать, + * чтобы получить нужный продукт. */ public class Demo { - public static void main(String[] args) { - Director director = new Director(); + public static void main(String[] args) { + Director director = new Director(); - // EN: Director gets the concrete builder object from the client - // (application code). That's because application knows better which - // builder to use to get a specific product. - // - // RU: Директор получает объект конкретного строителя от клиента - // (приложения). Приложение само знает какой строитель использовать, - // чтобы получить нужный продукт. - CarBuilder builder = new CarBuilder(); - director.constructSportsCar(builder); + CarBuilder builder = new CarBuilder(); + director.constructSportsCar(builder); - // EN: The final product is often retrieved from a builder object, since - // Director is not aware and not dependent on concrete builders and - // products. - // - // RU: Готовый продукт возвращает строитель, так как Директор чаще всего - // не знает и не зависит от конкретных классов строителей и продуктов. - Car car = builder.getResult(); - System.out.println("Car built:\n" + car.getCarType()); + Car car = builder.getResult(); + System.out.println("Car built:\n" + car.getCarType()); - CarManualBuilder manualBuilder = new CarManualBuilder(); - - // EN: Director may know several building recipes. - // - // RU: Директор может знать больше одного рецепта строительства. - director.constructSportsCar(manualBuilder); - Manual carManual = manualBuilder.getResult(); - System.out.println("\nCar manual built:\n" + carManual.print()); - } - + CarManualBuilder manualBuilder = new CarManualBuilder(); + director.constructSportsCar(manualBuilder); + Manual carManual = manualBuilder.getResult(); + System.out.println("\nCar manual built:\n" + carManual.print()); + } } diff --git a/src/refactoring_guru/builder/example/builders/Builder.java b/src/refactoring_guru/builder/example/builders/Builder.java index f81dd60..33770da 100644 --- a/src/refactoring_guru/builder/example/builders/Builder.java +++ b/src/refactoring_guru/builder/example/builders/Builder.java @@ -8,15 +8,20 @@ /** * EN: Builder interface defines all possible ways to configure a product. - * + *

* RU: Интерфейс Строителя объявляет все возможные этапы и шаги конфигурации * продукта. */ public interface Builder { - void setCarType(CarType type); - void setSeats(int seats); - void setEngine(Engine engine); - void setTransmission(Transmission transmission); - void setTripComputer(TripComputer tripComputer); - void setGPSNavigator(GPSNavigator gpsNavigator); + void setCarType(CarType type); + + void setSeats(int seats); + + void setEngine(Engine engine); + + void setTransmission(Transmission transmission); + + void setTripComputer(TripComputer tripComputer); + + void setGPSNavigator(GPSNavigator gpsNavigator); } diff --git a/src/refactoring_guru/builder/example/builders/CarBuilder.java b/src/refactoring_guru/builder/example/builders/CarBuilder.java index 2f618f3..ed3c4e9 100644 --- a/src/refactoring_guru/builder/example/builders/CarBuilder.java +++ b/src/refactoring_guru/builder/example/builders/CarBuilder.java @@ -9,47 +9,47 @@ /** * EN: Concrete builders implement steps defined in the common interface. - * + *

* RU: Конкретные строители реализуют шаги, объявленные в общем интерфейсе. */ public class CarBuilder implements Builder { - private CarType type; - private int seats; - private Engine engine; - private Transmission transmission; - private TripComputer tripComputer; - private GPSNavigator gpsNavigator; - - public void setCarType(CarType type) { - this.type = type; - } - - @Override - public void setSeats(int seats) { - this.seats = seats; - } - - @Override - public void setEngine(Engine engine) { - this.engine = engine; - } - - @Override - public void setTransmission(Transmission transmission) { - this.transmission = transmission; - } - - @Override - public void setTripComputer(TripComputer tripComputer) { - this.tripComputer = tripComputer; - } - - @Override - public void setGPSNavigator(GPSNavigator gpsNavigator) { - this.gpsNavigator = gpsNavigator; - } - - public Car getResult() { - return new Car(type, seats, engine, transmission, tripComputer, gpsNavigator); - } + private CarType type; + private int seats; + private Engine engine; + private Transmission transmission; + private TripComputer tripComputer; + private GPSNavigator gpsNavigator; + + public void setCarType(CarType type) { + this.type = type; + } + + @Override + public void setSeats(int seats) { + this.seats = seats; + } + + @Override + public void setEngine(Engine engine) { + this.engine = engine; + } + + @Override + public void setTransmission(Transmission transmission) { + this.transmission = transmission; + } + + @Override + public void setTripComputer(TripComputer tripComputer) { + this.tripComputer = tripComputer; + } + + @Override + public void setGPSNavigator(GPSNavigator gpsNavigator) { + this.gpsNavigator = gpsNavigator; + } + + public Car getResult() { + return new Car(type, seats, engine, transmission, tripComputer, gpsNavigator); + } } diff --git a/src/refactoring_guru/builder/example/builders/CarManualBuilder.java b/src/refactoring_guru/builder/example/builders/CarManualBuilder.java index 48ad164..11083bd 100644 --- a/src/refactoring_guru/builder/example/builders/CarManualBuilder.java +++ b/src/refactoring_guru/builder/example/builders/CarManualBuilder.java @@ -8,59 +8,59 @@ import refactoring_guru.builder.example.components.TripComputer; /** - * EN: Unlike other creational patterns, Builder can construct unrelated + * EN: Unlike other creation patterns, Builder can construct unrelated * products, which don't have the common interface. - * + *

* In this case we build a user manual for a car, using the same steps as we * built a car. This allows to produce manuals for specific car models, * configured with different features. - * + *

* RU: В отличие от других создающих паттернов, Строители могут создавать * совершенно разные продукты, не имеющие общего интерфейса. - * + *

* В данном случае мы производим руководство пользователя автомобиля с помощью * тех же шагов, что и сами автомобили. Это устройство позволит создавать * руководства под конкретные модели автомобилей, содержащие те или иные фичи. */ -public class CarManualBuilder implements Builder{ - private CarType type; - private int seats; - private Engine engine; - private Transmission transmission; - private TripComputer tripComputer; - private GPSNavigator gpsNavigator; +public class CarManualBuilder implements Builder { + private CarType type; + private int seats; + private Engine engine; + private Transmission transmission; + private TripComputer tripComputer; + private GPSNavigator gpsNavigator; - @Override - public void setCarType(CarType type) { - this.type = type; - } + @Override + public void setCarType(CarType type) { + this.type = type; + } - @Override - public void setSeats(int seats) { - this.seats = seats; - } + @Override + public void setSeats(int seats) { + this.seats = seats; + } - @Override - public void setEngine(Engine engine) { - this.engine = engine; - } + @Override + public void setEngine(Engine engine) { + this.engine = engine; + } - @Override - public void setTransmission(Transmission transmission) { - this.transmission = transmission; - } + @Override + public void setTransmission(Transmission transmission) { + this.transmission = transmission; + } - @Override - public void setTripComputer(TripComputer tripComputer) { - this.tripComputer = tripComputer; - } + @Override + public void setTripComputer(TripComputer tripComputer) { + this.tripComputer = tripComputer; + } - @Override - public void setGPSNavigator(GPSNavigator gpsNavigator) { - this.gpsNavigator = gpsNavigator; - } + @Override + public void setGPSNavigator(GPSNavigator gpsNavigator) { + this.gpsNavigator = gpsNavigator; + } - public Manual getResult() { - return new Manual(type, seats, engine, transmission, tripComputer, gpsNavigator); - } + public Manual getResult() { + return new Manual(type, seats, engine, transmission, tripComputer, gpsNavigator); + } } diff --git a/src/refactoring_guru/builder/example/cars/Car.java b/src/refactoring_guru/builder/example/cars/Car.java index e4b6d23..969b221 100644 --- a/src/refactoring_guru/builder/example/cars/Car.java +++ b/src/refactoring_guru/builder/example/cars/Car.java @@ -7,60 +7,60 @@ /** * EN: Car is a product class. - * + *

* RU: Автомобиль — это класс продукта. */ public class Car { - private final CarType carType; - private final int seats; - private final Engine engine; - private final Transmission transmission; - private final TripComputer tripComputer; - private final GPSNavigator gpsNavigator; - private double fuel = 0; + private final CarType carType; + private final int seats; + private final Engine engine; + private final Transmission transmission; + private final TripComputer tripComputer; + private final GPSNavigator gpsNavigator; + private double fuel = 0; - public Car(CarType carType, int seats, Engine engine, Transmission transmission, - TripComputer tripComputer, GPSNavigator gpsNavigator) { - this.carType = carType; - this.seats = seats; - this.engine = engine; - this.transmission = transmission; - this.tripComputer = tripComputer; - if (this.tripComputer != null) { - this.tripComputer.setCar(this); - } - this.gpsNavigator = gpsNavigator; + public Car(CarType carType, int seats, Engine engine, Transmission transmission, + TripComputer tripComputer, GPSNavigator gpsNavigator) { + this.carType = carType; + this.seats = seats; + this.engine = engine; + this.transmission = transmission; + this.tripComputer = tripComputer; + if (this.tripComputer != null) { + this.tripComputer.setCar(this); } + this.gpsNavigator = gpsNavigator; + } - public CarType getCarType() { - return carType; - } + public CarType getCarType() { + return carType; + } - public double getFuel() { - return fuel; - } + public double getFuel() { + return fuel; + } - public void setFuel(double fuel) { - this.fuel = fuel; - } + public void setFuel(double fuel) { + this.fuel = fuel; + } - public int getSeats() { - return seats; - } + public int getSeats() { + return seats; + } - public Engine getEngine() { - return engine; - } + public Engine getEngine() { + return engine; + } - public Transmission getTransmission() { - return transmission; - } + public Transmission getTransmission() { + return transmission; + } - public TripComputer getTripComputer() { - return tripComputer; - } + public TripComputer getTripComputer() { + return tripComputer; + } - public GPSNavigator getGpsNavigator() { - return gpsNavigator; - } + public GPSNavigator getGpsNavigator() { + return gpsNavigator; + } } diff --git a/src/refactoring_guru/builder/example/cars/CarType.java b/src/refactoring_guru/builder/example/cars/CarType.java index 2f8ee89..81cc741 100644 --- a/src/refactoring_guru/builder/example/cars/CarType.java +++ b/src/refactoring_guru/builder/example/cars/CarType.java @@ -1,5 +1,5 @@ package refactoring_guru.builder.example.cars; public enum CarType { - CITY_CAR, SPORTS_CAR, SUV + CITY_CAR, SPORTS_CAR, SUV } diff --git a/src/refactoring_guru/builder/example/components/Engine.java b/src/refactoring_guru/builder/example/components/Engine.java index 41956cc..f26dbc9 100644 --- a/src/refactoring_guru/builder/example/components/Engine.java +++ b/src/refactoring_guru/builder/example/components/Engine.java @@ -2,44 +2,44 @@ /** * EN: Just another feature of a car. - * + *

* RU: Одна из фишек автомобиля. */ public class Engine { - private final double volume; - private double mileage; - private boolean started; - - public Engine(double volume, double mileage) { - this.volume = volume; - this.mileage = mileage; - } - - public void on() { - started = true; + private final double volume; + private double mileage; + private boolean started; + + public Engine(double volume, double mileage) { + this.volume = volume; + this.mileage = mileage; + } + + public void on() { + started = true; + } + + public void off() { + started = false; + } + + public boolean isStarted() { + return started; + } + + public void go(double mileage) { + if (started) { + this.mileage += mileage; + } else { + System.err.println("Cannot go(), you must start engine first!"); } + } - public void off() { - started = false; - } - - public boolean isStarted() { - return started; - } + public double getVolume() { + return volume; + } - public void go(double mileage) { - if (started) { - this.mileage += mileage; - } else { - System.err.println("Cannot go(), you must start engine first!"); - } - } - - public double getVolume() { - return volume; - } - - public double getMileage() { - return mileage; - } + public double getMileage() { + return mileage; + } } diff --git a/src/refactoring_guru/builder/example/components/GPSNavigator.java b/src/refactoring_guru/builder/example/components/GPSNavigator.java index 68f4cc1..8929488 100644 --- a/src/refactoring_guru/builder/example/components/GPSNavigator.java +++ b/src/refactoring_guru/builder/example/components/GPSNavigator.java @@ -2,21 +2,21 @@ /** * EN: Just another feature of a car. - * + *

* RU: Одна из фишек автомобиля. */ public class GPSNavigator { - private String route; + private final String route; - public GPSNavigator() { - this.route = "221b, Baker Street, London to Scotland Yard, 8-10 Broadway, London"; - } + public GPSNavigator() { + this.route = "221b, Baker Street, London to Scotland Yard, 8-10 Broadway, London"; + } - public GPSNavigator(String manualRoute) { - this.route = manualRoute; - } + public GPSNavigator(String manualRoute) { + this.route = manualRoute; + } - public String getRoute() { - return route; - } + public String getRoute() { + return route; + } } diff --git a/src/refactoring_guru/builder/example/components/Transmission.java b/src/refactoring_guru/builder/example/components/Transmission.java index 2815235..6a84893 100644 --- a/src/refactoring_guru/builder/example/components/Transmission.java +++ b/src/refactoring_guru/builder/example/components/Transmission.java @@ -2,9 +2,9 @@ /** * EN: Just another feature of a car. - * + *

* RU: Одна из фишек автомобиля. */ public enum Transmission { - SINGLE_SPEED, MANUAL, AUTOMATIC, SEMI_AUTOMATIC + SINGLE_SPEED, MANUAL, AUTOMATIC, SEMI_AUTOMATIC } diff --git a/src/refactoring_guru/builder/example/components/TripComputer.java b/src/refactoring_guru/builder/example/components/TripComputer.java index 5617845..ab36aa1 100644 --- a/src/refactoring_guru/builder/example/components/TripComputer.java +++ b/src/refactoring_guru/builder/example/components/TripComputer.java @@ -4,26 +4,26 @@ /** * EN: Just another feature of a car. - * + *

* RU: Одна из фишек автомобиля. */ public class TripComputer { - private Car car; + private Car car; - public void setCar(Car car) { - this.car = car; - } + public void setCar(Car car) { + this.car = car; + } - public void showFuelLevel() { - System.out.println("Fuel level: " + car.getFuel()); - } + public void showFuelLevel() { + System.out.println("Fuel level: " + car.getFuel()); + } - public void showStatus() { - if (this.car.getEngine().isStarted()) { - System.out.println("Car is started"); - } else { - System.out.println("Car isn't started"); - } + public void showStatus() { + if (this.car.getEngine().isStarted()) { + System.out.println("Car is started"); + } else { + System.out.println("The Car isn't started"); } + } } diff --git a/src/refactoring_guru/builder/example/director/Director.java b/src/refactoring_guru/builder/example/director/Director.java index f5f8284..49baee2 100644 --- a/src/refactoring_guru/builder/example/director/Director.java +++ b/src/refactoring_guru/builder/example/director/Director.java @@ -11,36 +11,36 @@ * EN: Director defines the order of building steps. It works with a builder * object through common Builder interface. Therefore it may not know what * product is being built. - * + *

* RU: Директор знает в какой последовательности заставлять работать строителя. * Он работает с ним через общий интерфейс Строителя. Из-за этого, он может не * знать какой конкретно продукт сейчас строится. */ public class Director { - public void constructSportsCar(Builder builder) { - builder.setCarType(CarType.SPORTS_CAR); - builder.setSeats(2); - builder.setEngine(new Engine(3.0, 0)); - builder.setTransmission(Transmission.SEMI_AUTOMATIC); - builder.setTripComputer(new TripComputer()); - builder.setGPSNavigator(new GPSNavigator()); - } + public void constructSportsCar(Builder builder) { + builder.setCarType(CarType.SPORTS_CAR); + builder.setSeats(2); + builder.setEngine(new Engine(3.0, 0)); + builder.setTransmission(Transmission.SEMI_AUTOMATIC); + builder.setTripComputer(new TripComputer()); + builder.setGPSNavigator(new GPSNavigator()); + } - public void constructCityCar(Builder builder) { - builder.setCarType(CarType.CITY_CAR); - builder.setSeats(2); - builder.setEngine(new Engine(1.2, 0)); - builder.setTransmission(Transmission.AUTOMATIC); - builder.setTripComputer(new TripComputer()); - builder.setGPSNavigator(new GPSNavigator()); - } + public void constructCityCar(Builder builder) { + builder.setCarType(CarType.CITY_CAR); + builder.setSeats(2); + builder.setEngine(new Engine(1.2, 0)); + builder.setTransmission(Transmission.AUTOMATIC); + builder.setTripComputer(new TripComputer()); + builder.setGPSNavigator(new GPSNavigator()); + } - public void constructSUV(Builder builder) { - builder.setCarType(CarType.SUV); - builder.setSeats(4); - builder.setEngine(new Engine(2.5, 0)); - builder.setTransmission(Transmission.MANUAL); - builder.setGPSNavigator(new GPSNavigator()); - } + public void constructSUV(Builder builder) { + builder.setCarType(CarType.SUV); + builder.setSeats(4); + builder.setEngine(new Engine(2.5, 0)); + builder.setTransmission(Transmission.MANUAL); + builder.setGPSNavigator(new GPSNavigator()); + } } From 54520eed916d7c39e57ef1d7d79cef12e75b973d Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Wed, 4 Oct 2023 11:25:15 +0300 Subject: [PATCH 17/45] some changes in the chain of responsibility module --- .../example/Credentials.java | 4 + .../chain_of_responsibility/example/Demo.java | 72 ++++++++-------- .../example/middleware/Middleware.java | 63 +++++++------- .../middleware/RoleCheckMiddleware.java | 13 +-- .../middleware/ThrottlingMiddleware.java | 86 +++++++++++-------- .../middleware/UserExistsMiddleware.java | 30 +++---- .../example/server/Server.java | 84 ++++++++---------- 7 files changed, 179 insertions(+), 173 deletions(-) create mode 100644 src/refactoring_guru/chain_of_responsibility/example/Credentials.java diff --git a/src/refactoring_guru/chain_of_responsibility/example/Credentials.java b/src/refactoring_guru/chain_of_responsibility/example/Credentials.java new file mode 100644 index 0000000..daa41ad --- /dev/null +++ b/src/refactoring_guru/chain_of_responsibility/example/Credentials.java @@ -0,0 +1,4 @@ +package refactoring_guru.chain_of_responsibility.example; + +public record Credentials(String email, String password) { +} diff --git a/src/refactoring_guru/chain_of_responsibility/example/Demo.java b/src/refactoring_guru/chain_of_responsibility/example/Demo.java index 1934e61..42d0bf8 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/Demo.java +++ b/src/refactoring_guru/chain_of_responsibility/example/Demo.java @@ -9,48 +9,52 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.Optional; /** * EN: Demo class. Everything comes together here. - * + *

* RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); - private static Server server; - - private static void init() { - server = new Server(); - server.register("admin@example.com", "admin_pass"); - server.register("user@example.com", "user_pass"); - - // EN: All checks are linked. Client can build various chains using the - // same components. - // - // RU: Проверки связаны в одну цепь. Клиент может строить различные - // цепи, используя одни и те же компоненты. - Middleware middleware = Middleware.link( - new ThrottlingMiddleware(2), - new UserExistsMiddleware(server), - new RoleCheckMiddleware() - ); + private static Server server; - // EN: Server gets a chain from client code. - // - // RU: Сервер получает цепочку от клиентского кода. - server.setMiddleware(middleware); + public static void main(String[] args) { + init(); + while(!attemptLogin()) { + System.out.println("Error reading input. Try again."); } + } + + private static void init() { + server = new Server(); + server.register("admin@example.com", "admin_pass"); + server.register("user@example.com", "user_pass"); - public static void main(String[] args) throws IOException { - init(); - - boolean success; - do { - System.out.print("Enter email: "); - String email = reader.readLine(); - System.out.print("Input password: "); - String password = reader.readLine(); - success = server.logIn(email, password); - } while (!success); + Middleware middleware = Middleware.link( + new ThrottlingMiddleware(2), + new UserExistsMiddleware(server), + new RoleCheckMiddleware() + ); + + server.setMiddleware(middleware); + } + + private static boolean attemptLogin() { + return Optional.ofNullable(getCredentials()) + .map(credentials -> server.logIn(credentials.email(), credentials.password())) + .orElse(false); + } + + private static Credentials getCredentials() { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { + System.out.print("Enter email: "); + String email = reader.readLine(); + System.out.print("Input password: "); + String password = reader.readLine(); + return new Credentials(email, password); + } catch (IOException e) { + return null; } + } } diff --git a/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java b/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java index bd4d7bf..8e1d1bf 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java +++ b/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java @@ -2,44 +2,41 @@ /** * EN: Base middleware class. - * + *

* RU: Базовый класс цепочки. */ public abstract class Middleware { - private Middleware next; + private Middleware next; - /** - * EN: Builds chains of middleware objects. - * - * RU: Помогает строить цепь из объектов-проверок. - */ - public static Middleware link(Middleware first, Middleware... chain) { - Middleware head = first; - for (Middleware nextInChain: chain) { - head.next = nextInChain; - head = nextInChain; - } - return first; + /** + * EN: Builds chains of middleware objects. + *

+ * RU: Помогает строить цепь из объектов-проверок. + */ + public static Middleware link(Middleware first, Middleware... chain) { + Middleware head = first; + for (Middleware nextInChain : chain) { + head.next = nextInChain; + head = nextInChain; } + return first; + } - /** - * EN: Subclasses will implement this method with concrete checks. - * - * RU: Подклассы реализуют в этом методе конкретные проверки. - */ - public abstract boolean check(String email, String password); + /** + * EN: Subclasses will implement this method with concrete checks. + *

+ * RU: Подклассы реализуют в этом методе конкретные проверки. + */ + public abstract boolean check(String email, String password); - /** - * EN: Runs check on the next object in chain or ends traversing if we're in - * last object in chain. - * - * RU: Запускает проверку в следующем объекте или завершает проверку, если - * мы в последнем элементе цепи. - */ - protected boolean checkNext(String email, String password) { - if (next == null) { - return true; - } - return next.check(email, password); - } + /** + * EN: Runs check on the next object in chain or ends traversing if we're in + * last object in chain. + *

+ * RU: Запускает проверку в следующем объекте или завершает проверку, если + * мы в последнем элементе цепи. + */ + protected boolean checkNext(String email, String password) { + return next == null || next.check(email, password); + } } diff --git a/src/refactoring_guru/chain_of_responsibility/example/middleware/RoleCheckMiddleware.java b/src/refactoring_guru/chain_of_responsibility/example/middleware/RoleCheckMiddleware.java index 1315883..bbecc68 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/middleware/RoleCheckMiddleware.java +++ b/src/refactoring_guru/chain_of_responsibility/example/middleware/RoleCheckMiddleware.java @@ -2,16 +2,11 @@ /** * EN: ConcreteHandler. Checks a user's role. - * + *

* RU: Конкретный элемент цепи обрабатывает запрос по-своему. */ public class RoleCheckMiddleware extends Middleware { - public boolean check(String email, String password) { - if (email.equals("admin@example.com")) { - System.out.println("Hello, admin!"); - return true; - } - System.out.println("Hello, user!"); - return checkNext(email, password); - } + public boolean check(String email, String password) { + return email.equals("admin@example.com") || checkNext(email, password); + } } diff --git a/src/refactoring_guru/chain_of_responsibility/example/middleware/ThrottlingMiddleware.java b/src/refactoring_guru/chain_of_responsibility/example/middleware/ThrottlingMiddleware.java index 78341f2..7a63c39 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/middleware/ThrottlingMiddleware.java +++ b/src/refactoring_guru/chain_of_responsibility/example/middleware/ThrottlingMiddleware.java @@ -1,47 +1,63 @@ package refactoring_guru.chain_of_responsibility.example.middleware; +import java.util.Optional; + /** * EN: ConcreteHandler. Checks whether there are too many failed login requests. - * + *

* RU: Конкретный элемент цепи обрабатывает запрос по-своему. */ public class ThrottlingMiddleware extends Middleware { - private int requestPerMinute; - private int request; - private long currentTime; + private final int requestPerMinute; + private int request; + private long currentTime; - public ThrottlingMiddleware(int requestPerMinute) { - this.requestPerMinute = requestPerMinute; - this.currentTime = System.currentTimeMillis(); - } + public ThrottlingMiddleware(int requestPerMinute) { + this.requestPerMinute = requestPerMinute; + this.currentTime = System.currentTimeMillis(); + } - /** - * EN: Please, not that checkNext() call can be inserted both in the - * beginning of this method and in the end. - * - * This gives much more flexibility than a simple loop over all middleware - * objects. For instance, an element of a chain can change the order of - * checks by running its check after all other checks. - * - * RU: Обратите внимание, вызов checkNext() можно вставить как в начале - * этого метода, так и в середине или в конце. - * - * Это даёт еще один уровень гибкости по сравнению с проверками в цикле. - * Например, элемент цепи может пропустить все остальные проверки вперёд и - * запустить свою проверку в конце. - */ - public boolean check(String email, String password) { - if (System.currentTimeMillis() > currentTime + 60_000) { - request = 0; - currentTime = System.currentTimeMillis(); - } + /** + * EN: Please, not that checkNext() call can be inserted both in the + * beginning of this method and in the end. + *

+ * This gives much more flexibility than a simple loop over all middleware + * objects. For instance, an element of a chain can change the order of + * checks by running its check after all other checks. + *

+ * RU: Обратите внимание, вызов checkNext() можно вставить как в начале + * этого метода, так и в середине или в конце. + *

+ * Это даёт еще один уровень гибкости по сравнению с проверками в цикле. + * Например, элемент цепи может пропустить все остальные проверки вперёд и + * запустить свою проверку в конце. + */ + public boolean check(String email, String password) { + return resetIfTimeElapsed() + .filter(this::withinRateLimit) + .map(ignored -> checkNext(email, password)) + .orElseThrow(() -> { + System.out.println("Request limit exceeded!"); + return new RuntimeException("Request limit exceeded!"); + }); + } - request++; - - if (request > requestPerMinute) { - System.out.println("Request limit exceeded!"); - Thread.currentThread().stop(); - } - return checkNext(email, password); + private Optional resetIfTimeElapsed() { + long now = System.currentTimeMillis(); + if (now > currentTime + 60_000) { + request = 0; + currentTime = now; } + request++; + return Optional.of(true); + } + + @Override + protected boolean checkNext(String email, String password) { + return true; + } + + private boolean withinRateLimit(Boolean ignored) { + return request <= requestPerMinute; + } } diff --git a/src/refactoring_guru/chain_of_responsibility/example/middleware/UserExistsMiddleware.java b/src/refactoring_guru/chain_of_responsibility/example/middleware/UserExistsMiddleware.java index 005d0a6..5e64477 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/middleware/UserExistsMiddleware.java +++ b/src/refactoring_guru/chain_of_responsibility/example/middleware/UserExistsMiddleware.java @@ -4,25 +4,25 @@ /** * EN: ConcreteHandler. Checks whether a user with the given credentials exists. - * + *

* RU: Конкретный элемент цепи обрабатывает запрос по-своему. */ public class UserExistsMiddleware extends Middleware { - private Server server; + private final Server server; - public UserExistsMiddleware(Server server) { - this.server = server; - } + public UserExistsMiddleware(Server server) { + this.server = server; + } - public boolean check(String email, String password) { - if (!server.hasEmail(email)) { - System.out.println("This email is not registered!"); - return false; - } - if (!server.isValidPassword(email, password)) { - System.out.println("Wrong password!"); - return false; - } - return checkNext(email, password); + public boolean check(String email, String password) { + if (!server.hasEmail(email)) { + System.out.println("This email is not registered!"); + return false; + } + if (!server.isValidPassword(email, password)) { + System.out.println("Wrong password!"); + return false; } + return checkNext(email, password); + } } diff --git a/src/refactoring_guru/chain_of_responsibility/example/server/Server.java b/src/refactoring_guru/chain_of_responsibility/example/server/Server.java index 52f0be2..5be51c5 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/server/Server.java +++ b/src/refactoring_guru/chain_of_responsibility/example/server/Server.java @@ -7,54 +7,44 @@ /** * EN: Server class. - * + *

* RU: Класс сервера. */ public class Server { - private Map users = new HashMap<>(); - private Middleware middleware; - - /** - * EN: Client passes a chain of object to server. This improves flexibility - * and makes testing the server class easier. - * - * RU: Клиент подаёт готовую цепочку в сервер. Это увеличивает гибкость и - * упрощает тестирование класса сервера. - */ - public void setMiddleware(Middleware middleware) { - this.middleware = middleware; - } - - /** - * EN: Server gets email and password from client and sends the - * authorization request to the chain. - * - * RU: Сервер получает email и пароль от клиента и запускает проверку - * авторизации у цепочки. - */ - public boolean logIn(String email, String password) { - if (middleware.check(email, password)) { - System.out.println("Authorization have been successful!"); - - // EN: Do something useful here for authorized users. - // - // RU: Здесь должен быть какой-то полезный код, работающий для - // авторизированных пользователей. - - return true; - } - return false; - } - - public void register(String email, String password) { - users.put(email, password); - } - - public boolean hasEmail(String email) { - return users.containsKey(email); - } - - public boolean isValidPassword(String email, String password) { - return users.get(email).equals(password); - } + private final Map users = new HashMap<>(); + private Middleware middleware; + + /** + * EN: Client passes a chain of object to server. This improves flexibility + * and makes testing the server class easier. + *

+ * RU: Клиент подаёт готовую цепочку в сервер. Это увеличивает гибкость и + * упрощает тестирование класса сервера. + */ + public void setMiddleware(Middleware middleware) { + this.middleware = middleware; + } + + /** + * EN: Server gets email and password from client and sends the + * authorization request to the chain. + *

+ * RU: Сервер получает email и пароль от клиента и запускает проверку + * авторизации у цепочки. + */ + public boolean logIn(String email, String password) { + return middleware.check(email, password); + } + + public void register(String email, String password) { + users.put(email, password); + } + + public boolean hasEmail(String email) { + return users.containsKey(email); + } + + public boolean isValidPassword(String email, String password) { + return users.get(email).equals(password); + } } From 21a97767131733b210026c49a544f73cf2b55bcc Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Wed, 4 Oct 2023 13:50:01 +0300 Subject: [PATCH 18/45] some changes in the command package --- .../command/example/Demo.java | 8 +- .../example/commands/CommandHistory.java | 21 ++-- .../command/example/commands/CopyCommand.java | 16 +-- .../command/example/commands/CutCommand.java | 34 +++--- .../example/commands/PasteCommand.java | 22 ++-- .../command/example/editor/Editor.java | 104 +++++++----------- 6 files changed, 94 insertions(+), 111 deletions(-) diff --git a/src/refactoring_guru/command/example/Demo.java b/src/refactoring_guru/command/example/Demo.java index 7fa1d5a..56b748b 100644 --- a/src/refactoring_guru/command/example/Demo.java +++ b/src/refactoring_guru/command/example/Demo.java @@ -3,8 +3,8 @@ import refactoring_guru.command.example.editor.Editor; public class Demo { - public static void main(String[] args) { - Editor editor = new Editor(); - editor.init(); - } + public static void main(String[] args) { + Editor editor = new Editor(); + editor.init(); + } } diff --git a/src/refactoring_guru/command/example/commands/CommandHistory.java b/src/refactoring_guru/command/example/commands/CommandHistory.java index 5d578d6..843232e 100644 --- a/src/refactoring_guru/command/example/commands/CommandHistory.java +++ b/src/refactoring_guru/command/example/commands/CommandHistory.java @@ -1,17 +1,20 @@ package refactoring_guru.command.example.commands; -import java.util.Stack; +import java.util.ArrayDeque; +import java.util.Deque; public class CommandHistory { - private Stack history = new Stack<>(); + private final Deque history = new ArrayDeque<>(); - public void push(Command c) { - history.push(c); - } + public void push(Command c) { + history.push(c); + } - public Command pop() { - return history.pop(); - } + public Command pop() { + return history.pop(); + } - public boolean isEmpty() { return history.isEmpty(); } + public boolean isEmpty() { + return history.isEmpty(); + } } diff --git a/src/refactoring_guru/command/example/commands/CopyCommand.java b/src/refactoring_guru/command/example/commands/CopyCommand.java index 5d4d47b..3f74b51 100644 --- a/src/refactoring_guru/command/example/commands/CopyCommand.java +++ b/src/refactoring_guru/command/example/commands/CopyCommand.java @@ -4,13 +4,13 @@ public class CopyCommand extends Command { - public CopyCommand(Editor editor) { - super(editor); - } + public CopyCommand(Editor editor) { + super(editor); + } - @Override - public boolean execute() { - editor.clipboard = editor.textField.getSelectedText(); - return false; - } + @Override + public boolean execute() { + editor.clipboard = editor.textField.getSelectedText(); + return false; + } } diff --git a/src/refactoring_guru/command/example/commands/CutCommand.java b/src/refactoring_guru/command/example/commands/CutCommand.java index 495d9ab..902061b 100644 --- a/src/refactoring_guru/command/example/commands/CutCommand.java +++ b/src/refactoring_guru/command/example/commands/CutCommand.java @@ -4,24 +4,24 @@ public class CutCommand extends Command { - public CutCommand(Editor editor) { - super(editor); - } + public CutCommand(Editor editor) { + super(editor); + } - @Override - public boolean execute() { - if (editor.textField.getSelectedText().isEmpty()) return false; + @Override + public boolean execute() { + if (editor.textField.getSelectedText().isEmpty()) return false; - backup(); - String source = editor.textField.getText(); - editor.clipboard = editor.textField.getSelectedText(); - editor.textField.setText(cutString(source)); - return true; - } + backup(); + String source = editor.textField.getText(); + editor.clipboard = editor.textField.getSelectedText(); + editor.textField.setText(cutString(source)); + return true; + } - private String cutString(String source) { - String start = source.substring(0, editor.textField.getSelectionStart()); - String end = source.substring(editor.textField.getSelectionEnd()); - return start + end; - } + private String cutString(String source) { + String start = source.substring(0, editor.textField.getSelectionStart()); + String end = source.substring(editor.textField.getSelectionEnd()); + return start + end; + } } diff --git a/src/refactoring_guru/command/example/commands/PasteCommand.java b/src/refactoring_guru/command/example/commands/PasteCommand.java index e787346..17aee5c 100644 --- a/src/refactoring_guru/command/example/commands/PasteCommand.java +++ b/src/refactoring_guru/command/example/commands/PasteCommand.java @@ -4,16 +4,18 @@ public class PasteCommand extends Command { - public PasteCommand(Editor editor) { - super(editor); - } - - @Override - public boolean execute() { - if (editor.clipboard == null || editor.clipboard.isEmpty()) return false; + public PasteCommand(Editor editor) { + super(editor); + } - backup(); - editor.textField.insert(editor.clipboard, editor.textField.getCaretPosition()); - return true; + @Override + public boolean execute() { + if (editor.clipboard == null || editor.clipboard.isEmpty()) { + return false; } + + backup(); + editor.textField.insert(editor.clipboard, editor.textField.getCaretPosition()); + return true; + } } diff --git a/src/refactoring_guru/command/example/editor/Editor.java b/src/refactoring_guru/command/example/editor/Editor.java index 87b241b..9065c01 100644 --- a/src/refactoring_guru/command/example/editor/Editor.java +++ b/src/refactoring_guru/command/example/editor/Editor.java @@ -4,75 +4,53 @@ import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; public class Editor { - public JTextArea textField; - public String clipboard; - private CommandHistory history = new CommandHistory(); + public JTextArea textField; + public String clipboard; + private final CommandHistory history = new CommandHistory(); - public void init() { - JFrame frame = new JFrame("Text editor (type & use buttons, Luke!)"); - JPanel content = new JPanel(); - frame.setContentPane(content); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); - textField = new JTextArea(); - textField.setLineWrap(true); - content.add(textField); - JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER)); - JButton ctrlC = new JButton("Ctrl+C"); - JButton ctrlX = new JButton("Ctrl+X"); - JButton ctrlV = new JButton("Ctrl+V"); - JButton ctrlZ = new JButton("Ctrl+Z"); - Editor editor = this; - ctrlC.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - executeCommand(new CopyCommand(editor)); - } - }); - ctrlX.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - executeCommand(new CutCommand(editor)); - } - }); - ctrlV.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - executeCommand(new PasteCommand(editor)); - } - }); - ctrlZ.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - undo(); - } - }); - buttons.add(ctrlC); - buttons.add(ctrlX); - buttons.add(ctrlV); - buttons.add(ctrlZ); - content.add(buttons); - frame.setSize(450, 200); - frame.setLocationRelativeTo(null); - frame.setVisible(true); - } + public void init() { + JFrame frame = new JFrame("Text editor (type & use buttons, Luke!)"); + JPanel content = new JPanel(); + frame.setContentPane(content); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); + textField = new JTextArea(); + textField.setLineWrap(true); + content.add(textField); + JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER)); + JButton ctrlC = new JButton("Ctrl+C"); + JButton ctrlX = new JButton("Ctrl+X"); + JButton ctrlV = new JButton("Ctrl+V"); + JButton ctrlZ = new JButton("Ctrl+Z"); + Editor editor = this; + ctrlC.addActionListener(e -> executeCommand(new CopyCommand(editor))); + ctrlX.addActionListener(e -> executeCommand(new CutCommand(editor))); + ctrlV.addActionListener(e -> executeCommand(new PasteCommand(editor))); + ctrlZ.addActionListener(e -> undo()); + buttons.add(ctrlC); + buttons.add(ctrlX); + buttons.add(ctrlV); + buttons.add(ctrlZ); + content.add(buttons); + frame.setSize(450, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } - private void executeCommand(Command command) { - if (command.execute()) { - history.push(command); - } + private void executeCommand(Command command) { + if (command.execute()) { + history.push(command); } + } - private void undo() { - if (history.isEmpty()) return; + private void undo() { + if (history.isEmpty()) return; - Command command = history.pop(); - if (command != null) { - command.undo(); - } + Command command = history.pop(); + if (command != null) { + command.undo(); } + } } From da93f163f13ed2c3d25c3713941c3cf3fb3ea002 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Wed, 4 Oct 2023 13:55:57 +0300 Subject: [PATCH 19/45] some changes in the composite package --- .../composite/example/Demo.java | 35 +-- .../composite/example/editor/ImageEditor.java | 102 ++++---- .../composite/example/shapes/BaseShape.java | 169 +++++++------ .../composite/example/shapes/Circle.java | 35 +-- .../example/shapes/CompoundShape.java | 230 +++++++++--------- .../composite/example/shapes/Dot.java | 33 ++- .../composite/example/shapes/Rectangle.java | 40 +-- .../composite/example/shapes/Shape.java | 29 ++- 8 files changed, 340 insertions(+), 333 deletions(-) diff --git a/src/refactoring_guru/composite/example/Demo.java b/src/refactoring_guru/composite/example/Demo.java index 0e27c73..9d810b1 100644 --- a/src/refactoring_guru/composite/example/Demo.java +++ b/src/refactoring_guru/composite/example/Demo.java @@ -9,24 +9,25 @@ import java.awt.*; public class Demo { - public static void main(String[] args) { - ImageEditor editor = new ImageEditor(); + public static void main(String[] args) { + ImageEditor editor = new ImageEditor(); + createAndLoadShapes(editor); + } - editor.loadShapes( - new Circle(10, 10, 10, Color.BLUE), + private static void createAndLoadShapes(ImageEditor editor) { + Circle blueCircle = new Circle(10, 10, 10, Color.BLUE); - new CompoundShape( - new Circle(110, 110, 50, Color.RED), - new Dot(160, 160, Color.RED) - ), + Circle redCircle = new Circle(110, 110, 50, Color.RED); + Dot redDot = new Dot(160, 160, Color.RED); + CompoundShape redCompound = new CompoundShape(redCircle, redDot); - new CompoundShape( - new Rectangle(250, 250, 100, 100, Color.GREEN), - new Dot(240, 240, Color.GREEN), - new Dot(240, 360, Color.GREEN), - new Dot(360, 360, Color.GREEN), - new Dot(360, 240, Color.GREEN) - ) - ); - } + Rectangle greenRectangle = new Rectangle(250, 250, 100, 100, Color.GREEN); + Dot dot1 = new Dot(240, 240, Color.GREEN); + Dot dot2 = new Dot(240, 360, Color.GREEN); + Dot dot3 = new Dot(360, 360, Color.GREEN); + Dot dot4 = new Dot(360, 240, Color.GREEN); + CompoundShape greenCompound = new CompoundShape(greenRectangle, dot1, dot2, dot3, dot4); + + editor.loadShapes(blueCircle, redCompound, greenCompound); + } } \ No newline at end of file diff --git a/src/refactoring_guru/composite/example/editor/ImageEditor.java b/src/refactoring_guru/composite/example/editor/ImageEditor.java index dfc7277..8975b70 100644 --- a/src/refactoring_guru/composite/example/editor/ImageEditor.java +++ b/src/refactoring_guru/composite/example/editor/ImageEditor.java @@ -10,67 +10,69 @@ import java.awt.event.MouseEvent; public class ImageEditor { - private EditorCanvas canvas; - private CompoundShape allShapes = new CompoundShape(); + private final EditorCanvas canvas; + private final CompoundShape allShapes = new CompoundShape(); - public ImageEditor() { - canvas = new EditorCanvas(); - } - - public void loadShapes(Shape... shapes) { - allShapes.clear(); - allShapes.add(shapes); - canvas.refresh(); - } + public ImageEditor() { + canvas = new EditorCanvas(); + } - private class EditorCanvas extends Canvas { - JFrame frame; + public void loadShapes(Shape... shapes) { + allShapes.clear(); + allShapes.add(shapes); + canvas.refresh(); + } - private static final int PADDING = 10; + private class EditorCanvas extends Canvas { + private static final int PADDING = 10; + JFrame frame; - EditorCanvas() { - createFrame(); - refresh(); - addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - allShapes.unSelect(); - allShapes.selectChildAt(e.getX(), e.getY()); - e.getComponent().repaint(); - } - }); + EditorCanvas() { + createFrame(); + refresh(); + addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + allShapes.unSelect(); + allShapes.selectChildAt(e.getX(), e.getY()); + e.getComponent().repaint(); } + }); + } - void createFrame() { - frame = new JFrame(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - frame.setLocationRelativeTo(null); + void createFrame() { + frame = new JFrame(); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frame.setLocationRelativeTo(null); - JPanel contentPanel = new JPanel(); - Border padding = BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING); - contentPanel.setBorder(padding); - frame.setContentPane(contentPanel); + JPanel contentPanel = new JPanel(); + Border padding = BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING); + contentPanel.setBorder(padding); + frame.setContentPane(contentPanel); - frame.add(this); - frame.setVisible(true); - frame.getContentPane().setBackground(Color.LIGHT_GRAY); - } + frame.add(this); + frame.setVisible(true); + frame.getContentPane().setBackground(Color.LIGHT_GRAY); + } - public int getWidth() { - return allShapes.getX() + allShapes.getWidth() + PADDING; - } + @Override + public int getWidth() { + return allShapes.getX() + allShapes.getWidth() + PADDING; + } - public int getHeight() { - return allShapes.getY() + allShapes.getHeight() + PADDING; - } + @Override + public int getHeight() { + return allShapes.getY() + allShapes.getHeight() + PADDING; + } - void refresh() { - this.setSize(getWidth(), getHeight()); - frame.pack(); - } + void refresh() { + this.setSize(getWidth(), getHeight()); + frame.pack(); + } - public void paint(Graphics graphics) { - allShapes.paint(graphics); - } + @Override + public void paint(Graphics graphics) { + allShapes.paint(graphics); } + } } diff --git a/src/refactoring_guru/composite/example/shapes/BaseShape.java b/src/refactoring_guru/composite/example/shapes/BaseShape.java index f0f5552..6e1b421 100644 --- a/src/refactoring_guru/composite/example/shapes/BaseShape.java +++ b/src/refactoring_guru/composite/example/shapes/BaseShape.java @@ -3,91 +3,88 @@ import java.awt.*; abstract class BaseShape implements Shape { - public int x; - public int y; - public Color color; - private boolean selected = false; - - BaseShape(int x, int y, Color color) { - this.x = x; - this.y = y; - this.color = color; - } - - @Override - public int getX() { - return x; - } - - @Override - public int getY() { - return y; - } - - @Override - public int getWidth() { - return 0; - } - - @Override - public int getHeight() { - return 0; - } - - @Override - public void move(int x, int y) { - this.x += x; - this.y += y; - } - - @Override - public boolean isInsideBounds(int x, int y) { - return x > getX() && x < (getX() + getWidth()) && - y > getY() && y < (getY() + getHeight()); - } - - @Override - public void select() { - selected = true; - } - - @Override - public void unSelect() { - selected = false; - } - - @Override - public boolean isSelected() { - return selected; - } - - void enableSelectionStyle(Graphics graphics) { - graphics.setColor(Color.LIGHT_GRAY); - - Graphics2D g2 = (Graphics2D) graphics; - float[] dash1 = {2.0f}; - g2.setStroke(new BasicStroke(1.0f, - BasicStroke.CAP_BUTT, - BasicStroke.JOIN_MITER, - 2.0f, dash1, 0.0f)); - } - - void disableSelectionStyle(Graphics graphics) { - graphics.setColor(color); - Graphics2D g2 = (Graphics2D) graphics; - g2.setStroke(new BasicStroke()); - } - - - @Override - public void paint(Graphics graphics) { - if (isSelected()) { - enableSelectionStyle(graphics); - } - else { - disableSelectionStyle(graphics); - } - - // ... + public int x; + public int y; + public Color color; + private boolean selected = false; + + BaseShape(int x, int y, Color color) { + this.x = x; + this.y = y; + this.color = color; + } + + @Override + public int getX() { + return x; + } + + @Override + public int getY() { + return y; + } + + @Override + public int getWidth() { + return 0; + } + + @Override + public int getHeight() { + return 0; + } + + @Override + public void move(int x, int y) { + this.x += x; + this.y += y; + } + + @Override + public boolean isInsideBounds(int x, int y) { + return x > getX() && x < (getX() + getWidth()) && + y > getY() && y < (getY() + getHeight()); + } + + @Override + public void select() { + selected = true; + } + + @Override + public void unSelect() { + selected = false; + } + + @Override + public boolean isSelected() { + return selected; + } + + void enableSelectionStyle(Graphics graphics) { + graphics.setColor(Color.LIGHT_GRAY); + + Graphics2D g2 = (Graphics2D) graphics; + float[] dash1 = {2.0f}; + g2.setStroke(new BasicStroke(1.0f, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, + 2.0f, dash1, 0.0f)); + } + + void disableSelectionStyle(Graphics graphics) { + graphics.setColor(color); + Graphics2D g2 = (Graphics2D) graphics; + g2.setStroke(new BasicStroke()); + } + + + @Override + public void paint(Graphics graphics) { + if (isSelected()) { + enableSelectionStyle(graphics); + } else { + disableSelectionStyle(graphics); } + } } diff --git a/src/refactoring_guru/composite/example/shapes/Circle.java b/src/refactoring_guru/composite/example/shapes/Circle.java index 98fd6db..f9b8c1a 100644 --- a/src/refactoring_guru/composite/example/shapes/Circle.java +++ b/src/refactoring_guru/composite/example/shapes/Circle.java @@ -3,25 +3,26 @@ import java.awt.*; public class Circle extends BaseShape { - public int radius; + public int radius; - public Circle(int x, int y, int radius, Color color) { - super(x, y, color); - this.radius = radius; - } + public Circle(int x, int y, int radius, Color color) { + super(x, y, color); + this.radius = radius; + } - @Override - public int getWidth() { - return radius * 2; - } + @Override + public int getWidth() { + return radius * 2; + } - @Override - public int getHeight() { - return radius * 2; - } + @Override + public int getHeight() { + return radius * 2; + } - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.drawOval(x, y, getWidth() - 1, getHeight() - 1); - } + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.drawOval(x, y, getWidth() - 1, getHeight() - 1); + } } diff --git a/src/refactoring_guru/composite/example/shapes/CompoundShape.java b/src/refactoring_guru/composite/example/shapes/CompoundShape.java index ee9562a..2bba432 100644 --- a/src/refactoring_guru/composite/example/shapes/CompoundShape.java +++ b/src/refactoring_guru/composite/example/shapes/CompoundShape.java @@ -6,134 +6,132 @@ import java.util.List; public class CompoundShape extends BaseShape { - protected List children = new ArrayList<>(); - - public CompoundShape(Shape... components) { - super(0, 0, Color.BLACK); - add(components); - } - - public void add(Shape component) { - children.add(component); - } - - public void add(Shape... components) { - children.addAll(Arrays.asList(components)); - } - - public void remove(Shape child) { - children.remove(child); - } - - public void remove(Shape... components) { - children.removeAll(Arrays.asList(components)); + protected List children = new ArrayList<>(); + + public CompoundShape(Shape... components) { + super(0, 0, Color.BLACK); + add(components); + } + + public void add(Shape component) { + children.add(component); + } + + public void add(Shape... components) { + children.addAll(Arrays.asList(components)); + } + + public void remove(Shape child) { + children.remove(child); + } + + public void remove(Shape... components) { + children.removeAll(Arrays.asList(components)); + } + + public void clear() { + children.clear(); + } + + @Override + public int getX() { + checkNoEmpty(children); + int x = children.get(0).getX(); + for (Shape child : children) { + if (child.getX() < x) { + x = child.getX(); + } } - - public void clear() { - children.clear(); + return x; + } + + @Override + public int getY() { + checkNoEmpty(children); + int y = children.get(0).getY(); + for (Shape child : children) { + if (child.getY() < y) { + y = child.getY(); + } } - - @Override - public int getX() { - if (children.size() == 0) { - return 0; - } - int x = children.get(0).getX(); - for (Shape child : children) { - if (child.getX() < x) { - x = child.getX(); - } - } - return x; + return y; + } + + @Override + public int getWidth() { + int maxWidth = 0; + int x = getX(); + + for (Shape child : children) { + int childRelativeX = child.getX() - x; + int childWidth = childRelativeX + child.getWidth(); + maxWidth = Math.max(maxWidth, childWidth); } - - @Override - public int getY() { - if (children.size() == 0) { - return 0; - } - int y = children.get(0).getY(); - for (Shape child : children) { - if (child.getY() < y) { - y = child.getY(); - } - } - return y; + return maxWidth; + } + + @Override + public int getHeight() { + int maxHeight = 0; + int y = getY(); + + for (Shape child : children) { + int childRelativeY = child.getY() - y; + int childHeight = childRelativeY + child.getHeight(); + maxHeight = Math.max(maxHeight, childHeight); } + return maxHeight; + } - @Override - public int getWidth() { - int maxWidth = 0; - int x = getX(); - for (Shape child : children) { - int childsRelativeX = child.getX() - x; - int childWidth = childsRelativeX + child.getWidth(); - if (childWidth > maxWidth) { - maxWidth = childWidth; - } - } - return maxWidth; + @Override + public void move(int x, int y) { + for (Shape child : children) { + child.move(x, y); } - - @Override - public int getHeight() { - int maxHeight = 0; - int y = getY(); - for (Shape child : children) { - int childsRelativeY = child.getY() - y; - int childHeight = childsRelativeY + child.getHeight(); - if (childHeight > maxHeight) { - maxHeight = childHeight; - } - } - return maxHeight; + } + + @Override + public boolean isInsideBounds(int x, int y) { + for (Shape child : children) { + if (child.isInsideBounds(x, y)) { + return true; + } } - - @Override - public void move(int x, int y) { - for (Shape child : children) { - child.move(x, y); - } + return false; + } + + @Override + public void unSelect() { + super.unSelect(); + for (Shape child : children) { + child.unSelect(); } + } - @Override - public boolean isInsideBounds(int x, int y) { - for (Shape child : children) { - if (child.isInsideBounds(x, y)) { - return true; - } - } - return false; + public void selectChildAt(int x, int y) { + for (Shape child : children) { + if (child.isInsideBounds(x, y)) { + child.select(); + } } - - @Override - public void unSelect() { - super.unSelect(); - for (Shape child : children) { - child.unSelect(); - } + } + + @Override + public void paint(Graphics graphics) { + if (isSelected()) { + enableSelectionStyle(graphics); + graphics.drawRect(getX() - 1, getY() - 1, getWidth() + 1, getHeight() + 1); + disableSelectionStyle(graphics); } - public boolean selectChildAt(int x, int y) { - for (Shape child : children) { - if (child.isInsideBounds(x, y)) { - child.select(); - return true; - } - } - return false; + for (Shape child : children) { + child.paint(graphics); } + } - @Override - public void paint(Graphics graphics) { - if (isSelected()) { - enableSelectionStyle(graphics); - graphics.drawRect(getX() - 1, getY() - 1, getWidth() + 1, getHeight() + 1); - disableSelectionStyle(graphics); - } - - for (Shape child : children) { - child.paint(graphics); - } - } + private static void checkNoEmpty(List children) { + if (children.isEmpty()) { + throw new IllegalArgumentException("The List is empty "); + } + } } diff --git a/src/refactoring_guru/composite/example/shapes/Dot.java b/src/refactoring_guru/composite/example/shapes/Dot.java index 205326a..1e4a680 100644 --- a/src/refactoring_guru/composite/example/shapes/Dot.java +++ b/src/refactoring_guru/composite/example/shapes/Dot.java @@ -3,25 +3,24 @@ import java.awt.*; public class Dot extends BaseShape { - private final int DOT_SIZE = 3; - public Dot(int x, int y, Color color) { - super(x, y, color); - } + public Dot(int x, int y, Color color) { + super(x, y, color); + } - @Override - public int getWidth() { - return DOT_SIZE; - } + @Override + public int getWidth() { + return 3; + } - @Override - public int getHeight() { - return DOT_SIZE; - } + @Override + public int getHeight() { + return 3; + } - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.fillRect(x - 1, y - 1, getWidth(), getHeight()); - } + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.fillRect(x - 1, y - 1, getWidth(), getHeight()); + } } diff --git a/src/refactoring_guru/composite/example/shapes/Rectangle.java b/src/refactoring_guru/composite/example/shapes/Rectangle.java index 4a2b73f..d699590 100644 --- a/src/refactoring_guru/composite/example/shapes/Rectangle.java +++ b/src/refactoring_guru/composite/example/shapes/Rectangle.java @@ -3,28 +3,28 @@ import java.awt.*; public class Rectangle extends BaseShape { - public int width; - public int height; + public int width; + public int height; - public Rectangle(int x, int y, int width, int height, Color color) { - super(x, y, color); - this.width = width; - this.height = height; - } + public Rectangle(int x, int y, int width, int height, Color color) { + super(x, y, color); + this.width = width; + this.height = height; + } - @Override - public int getWidth() { - return width; - } + @Override + public int getWidth() { + return width; + } - @Override - public int getHeight() { - return height; - } + @Override + public int getHeight() { + return height; + } - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.drawRect(x, y, getWidth() - 1, getHeight() - 1); - } + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.drawRect(x, y, getWidth() - 1, getHeight() - 1); + } } diff --git a/src/refactoring_guru/composite/example/shapes/Shape.java b/src/refactoring_guru/composite/example/shapes/Shape.java index 746cf83..d209ec7 100644 --- a/src/refactoring_guru/composite/example/shapes/Shape.java +++ b/src/refactoring_guru/composite/example/shapes/Shape.java @@ -3,14 +3,23 @@ import java.awt.*; public interface Shape { - int getX(); - int getY(); - int getWidth(); - int getHeight(); - void move(int x, int y); - boolean isInsideBounds(int x, int y); - void select(); - void unSelect(); - boolean isSelected(); - void paint(Graphics graphics); + int getX(); + + int getY(); + + int getWidth(); + + int getHeight(); + + void move(int x, int y); + + boolean isInsideBounds(int x, int y); + + void select(); + + void unSelect(); + + boolean isSelected(); + + void paint(Graphics graphics); } From 7aa85553264848d36f703909d19322faa573acce Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Wed, 4 Oct 2023 15:58:42 +0300 Subject: [PATCH 20/45] some changes in the decorator package --- .../decorator/example/Demo.java | 31 +++--- .../decorators/CompressionDecorator.java | 94 +++++++++---------- .../example/decorators/DataSource.java | 4 +- .../decorators/DataSourceDecorator.java | 24 ++--- .../decorators/EncryptionDecorator.java | 46 ++++----- .../example/decorators/FileDataSource.java | 51 +++++----- 6 files changed, 127 insertions(+), 123 deletions(-) diff --git a/src/refactoring_guru/decorator/example/Demo.java b/src/refactoring_guru/decorator/example/Demo.java index cb58725..84a7303 100644 --- a/src/refactoring_guru/decorator/example/Demo.java +++ b/src/refactoring_guru/decorator/example/Demo.java @@ -3,19 +3,22 @@ import refactoring_guru.decorator.example.decorators.*; public class Demo { - public static void main(String[] args) { - String salaryRecords = "Name,Salary\nJohn Smith,100000\nSteven Jobs,912000"; - DataSourceDecorator encoded = new CompressionDecorator( - new EncryptionDecorator( - new FileDataSource("out/OutputDemo.txt"))); - encoded.writeData(salaryRecords); - DataSource plain = new FileDataSource("out/OutputDemo.txt"); + public static void main(String[] args) { + init(); + } - System.out.println("- Input ----------------"); - System.out.println(salaryRecords); - System.out.println("- Encoded --------------"); - System.out.println(plain.readData()); - System.out.println("- Decoded --------------"); - System.out.println(encoded.readData()); - } + private static void init() { + DataSourceDecorator encoded = new CompressionDecorator( + new EncryptionDecorator( + new FileDataSource("out/OutputDemo.txt"))); + encoded.writeData("Name, salary\nJohn Smith, 100000\nSteven Jobs\n"); + DataSource plain = new FileDataSource("out/OutputDemo.txt"); + + System.out.println("- Input ----------------"); + System.out.println("Name, salary\nJohn Smith, 100000\nSteven Jobs\n"); + System.out.println("- Encoded --------------"); + System.out.println(plain.readData()); + System.out.println("- Decoded --------------"); + System.out.println(encoded.readData()); + } } diff --git a/src/refactoring_guru/decorator/example/decorators/CompressionDecorator.java b/src/refactoring_guru/decorator/example/decorators/CompressionDecorator.java index fc63691..6af5261 100644 --- a/src/refactoring_guru/decorator/example/decorators/CompressionDecorator.java +++ b/src/refactoring_guru/decorator/example/decorators/CompressionDecorator.java @@ -10,60 +10,60 @@ import java.util.zip.InflaterInputStream; public class CompressionDecorator extends DataSourceDecorator { - private int compLevel = 6; + private int compLevel = 6; - public CompressionDecorator(DataSource source) { - super(source); - } + public CompressionDecorator(DataSource source) { + super(source); + } - public int getCompressionLevel() { - return compLevel; - } + public int getCompressionLevel() { + return compLevel; + } - public void setCompressionLevel(int value) { - compLevel = value; - } + public void setCompressionLevel(int value) { + compLevel = value; + } - @Override - public void writeData(String data) { - super.writeData(compress(data)); - } + @Override + public void writeData(String data) { + super.writeData(compress(data)); + } - @Override - public String readData() { - return decompress(super.readData()); - } + @Override + public String readData() { + return decompress(super.readData()); + } - private String compress(String stringData) { - byte[] data = stringData.getBytes(); - try { - ByteArrayOutputStream bout = new ByteArrayOutputStream(512); - DeflaterOutputStream dos = new DeflaterOutputStream(bout, new Deflater(compLevel)); - dos.write(data); - dos.close(); - bout.close(); - return Base64.getEncoder().encodeToString(bout.toByteArray()); - } catch (IOException ex) { - return null; - } + private String compress(String stringData) { + byte[] data = stringData.getBytes(); + try { + ByteArrayOutputStream bout = new ByteArrayOutputStream(512); + DeflaterOutputStream dos = new DeflaterOutputStream(bout, new Deflater(compLevel)); + dos.write(data); + dos.close(); + bout.close(); + return Base64.getEncoder().encodeToString(bout.toByteArray()); + } catch (IOException ex) { + return null; } + } - private String decompress(String stringData) { - byte[] data = Base64.getDecoder().decode(stringData); - try { - InputStream in = new ByteArrayInputStream(data); - InflaterInputStream iin = new InflaterInputStream(in); - ByteArrayOutputStream bout = new ByteArrayOutputStream(512); - int b; - while ((b = iin.read()) != -1) { - bout.write(b); - } - in.close(); - iin.close(); - bout.close(); - return new String(bout.toByteArray()); - } catch (IOException ex) { - return null; - } + private String decompress(String stringData) { + byte[] data = Base64.getDecoder().decode(stringData); + try { + InputStream in = new ByteArrayInputStream(data); + InflaterInputStream iin = new InflaterInputStream(in); + ByteArrayOutputStream bout = new ByteArrayOutputStream(512); + int b; + while ((b = iin.read()) != -1) { + bout.write(b); + } + in.close(); + iin.close(); + bout.close(); + return bout.toString(); + } catch (IOException ex) { + return null; } + } } diff --git a/src/refactoring_guru/decorator/example/decorators/DataSource.java b/src/refactoring_guru/decorator/example/decorators/DataSource.java index b26cd07..1d2c360 100644 --- a/src/refactoring_guru/decorator/example/decorators/DataSource.java +++ b/src/refactoring_guru/decorator/example/decorators/DataSource.java @@ -1,7 +1,7 @@ package refactoring_guru.decorator.example.decorators; public interface DataSource { - void writeData(String data); + void writeData(String data); - String readData(); + String readData(); } diff --git a/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java b/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java index f126d93..02b02e3 100644 --- a/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java +++ b/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java @@ -1,19 +1,19 @@ package refactoring_guru.decorator.example.decorators; public class DataSourceDecorator implements DataSource { - private DataSource wrappee; + private final DataSource dataSource; - DataSourceDecorator(DataSource source) { - this.wrappee = source; - } + DataSourceDecorator(DataSource source) { + this.dataSource = source; + } - @Override - public void writeData(String data) { - wrappee.writeData(data); - } + @Override + public void writeData(String data) { + dataSource.writeData(data); + } - @Override - public String readData() { - return wrappee.readData(); - } + @Override + public String readData() { + return dataSource.readData(); + } } diff --git a/src/refactoring_guru/decorator/example/decorators/EncryptionDecorator.java b/src/refactoring_guru/decorator/example/decorators/EncryptionDecorator.java index 2b8821c..0835af1 100644 --- a/src/refactoring_guru/decorator/example/decorators/EncryptionDecorator.java +++ b/src/refactoring_guru/decorator/example/decorators/EncryptionDecorator.java @@ -4,33 +4,33 @@ public class EncryptionDecorator extends DataSourceDecorator { - public EncryptionDecorator(DataSource source) { - super(source); - } + public EncryptionDecorator(DataSource source) { + super(source); + } - @Override - public void writeData(String data) { - super.writeData(encode(data)); - } + @Override + public void writeData(String data) { + super.writeData(encode(data)); + } - @Override - public String readData() { - return decode(super.readData()); - } + @Override + public String readData() { + return decode(super.readData()); + } - private String encode(String data) { - byte[] result = data.getBytes(); - for (int i = 0; i < result.length; i++) { - result[i] += (byte) 1; - } - return Base64.getEncoder().encodeToString(result); + private String encode(String data) { + byte[] result = data.getBytes(); + for (int i = 0; i < result.length; i++) { + result[i] += (byte) 1; } + return Base64.getEncoder().encodeToString(result); + } - private String decode(String data) { - byte[] result = Base64.getDecoder().decode(data); - for (int i = 0; i < result.length; i++) { - result[i] -= (byte) 1; - } - return new String(result); + private String decode(String data) { + byte[] result = Base64.getDecoder().decode(data); + for (int i = 0; i < result.length; i++) { + result[i] -= (byte) 1; } + return new String(result); + } } diff --git a/src/refactoring_guru/decorator/example/decorators/FileDataSource.java b/src/refactoring_guru/decorator/example/decorators/FileDataSource.java index 8b19251..97665f6 100644 --- a/src/refactoring_guru/decorator/example/decorators/FileDataSource.java +++ b/src/refactoring_guru/decorator/example/decorators/FileDataSource.java @@ -1,35 +1,36 @@ package refactoring_guru.decorator.example.decorators; -import java.io.*; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; public class FileDataSource implements DataSource { - private String name; + private final String name; - public FileDataSource(String name) { - this.name = name; - } + public FileDataSource(String name) { + this.name = name; + } - @Override - public void writeData(String data) { - File file = new File(name); - try (OutputStream fos = new FileOutputStream(file)) { - fos.write(data.getBytes(), 0, data.length()); - } catch (IOException ex) { - System.out.println(ex.getMessage()); - } + @Override + public void writeData(String data) { + Path path = Paths.get(name); + try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { + writer.write(data, 0, data.length()); + } catch (IOException ex) { + throw new RuntimeException("Failed to write data to file: " + name, ex); } + } - @Override - public String readData() { - char[] buffer = null; - File file = new File(name); - try (FileReader reader = new FileReader(file)) { - buffer = new char[(int) file.length()]; - reader.read(buffer); - } catch (IOException ex) { - System.out.println(ex.getMessage()); - } - return new String(buffer); + @Override + public String readData() { + Path path = Paths.get(name); + try { + return Files.readString(path); + } catch (IOException ex) { + throw new RuntimeException("Failed to read data from file: " + name, ex); } + } } - From 67d5bbefdee1a2c7a55eabc84077a9aa293a4466 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Wed, 4 Oct 2023 16:00:21 +0300 Subject: [PATCH 21/45] minor update --- .../factory_method/example/factory/Dialog.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/refactoring_guru/factory_method/example/factory/Dialog.java b/src/refactoring_guru/factory_method/example/factory/Dialog.java index 33bcd4f..1aaedd1 100644 --- a/src/refactoring_guru/factory_method/example/factory/Dialog.java +++ b/src/refactoring_guru/factory_method/example/factory/Dialog.java @@ -14,10 +14,6 @@ public abstract class Dialog { public void renderWindow() { - // EN: ... other code ... - // - // RU: ... остальной код диалога ... - Button okButton = createButton(); okButton.render(); } From fcfb5e11966455755002d80715c11667670aa595 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Wed, 4 Oct 2023 16:25:05 +0300 Subject: [PATCH 22/45] some changes in the flyweight package --- .../flyweight/example/Demo.java | 51 ++++++++++--------- .../flyweight/example/forest/Forest.java | 22 ++++---- .../flyweight/example/trees/Tree.java | 22 ++++---- .../flyweight/example/trees/TreeFactory.java | 20 ++++---- .../flyweight/example/trees/TreeType.java | 24 ++++----- 5 files changed, 67 insertions(+), 72 deletions(-) diff --git a/src/refactoring_guru/flyweight/example/Demo.java b/src/refactoring_guru/flyweight/example/Demo.java index 2f5b9f7..8d5d96d 100644 --- a/src/refactoring_guru/flyweight/example/Demo.java +++ b/src/refactoring_guru/flyweight/example/Demo.java @@ -2,35 +2,36 @@ import refactoring_guru.flyweight.example.forest.Forest; -import java.awt.*; +import java.util.Random; public class Demo { - static int CANVAS_SIZE = 500; - static int TREES_TO_DRAW = 1000000; - static int TREE_TYPES = 2; + static final int CANVAS_SIZE = 500; + static final int TREES_TO_DRAW = 1000000; + static final int TREE_TYPES = 2; - public static void main(String[] args) { - Forest forest = new Forest(); - for (int i = 0; i < Math.floor(TREES_TO_DRAW / TREE_TYPES); i++) { - forest.plantTree(random(0, CANVAS_SIZE), random(0, CANVAS_SIZE), - "Summer Oak", Color.GREEN, "Oak texture stub"); - forest.plantTree(random(0, CANVAS_SIZE), random(0, CANVAS_SIZE), - "Autumn Oak", Color.ORANGE, "Autumn Oak texture stub"); - } - forest.setSize(CANVAS_SIZE, CANVAS_SIZE); - forest.setVisible(true); + public static void main(String[] args) { + Forest forest = new Forest(); + int treesPerType = TREES_TO_DRAW / TREE_TYPES; + Random random = new Random(); - System.out.println(TREES_TO_DRAW + " trees drawn"); - System.out.println("---------------------"); - System.out.println("Memory usage:"); - System.out.println("Tree size (8 bytes) * " + TREES_TO_DRAW); - System.out.println("+ TreeTypes size (~30 bytes) * " + TREE_TYPES + ""); - System.out.println("---------------------"); - System.out.println("Total: " + ((TREES_TO_DRAW * 8 + TREE_TYPES * 30) / 1024 / 1024) + - "MB (instead of " + ((TREES_TO_DRAW * 38) / 1024 / 1024) + "MB)"); + for (int i = 0; i < treesPerType; i++) { + forest.plantTree(random.nextInt(CANVAS_SIZE), random.nextInt(CANVAS_SIZE), "Summer Oak"); + forest.plantTree(random.nextInt(CANVAS_SIZE), random.nextInt(CANVAS_SIZE), "Autumn Oak"); } - private static int random(int min, int max) { - return min + (int) (Math.random() * ((max - min) + 1)); - } + forest.setSize(CANVAS_SIZE, CANVAS_SIZE); + forest.setVisible(true); + logStatistics(); + } + + private static void logStatistics() { + System.out.println(TREES_TO_DRAW + " trees drawn"); + System.out.println("---------------------"); + System.out.println("Memory usage:"); + System.out.println("Tree size (8 bytes) * " + TREES_TO_DRAW); + System.out.println("+ TreeTypes size (~30 bytes) * " + TREE_TYPES); + System.out.println("---------------------"); + System.out.println("Total: " + ((TREES_TO_DRAW * 8 + TREE_TYPES * 30) / 1024 / 1024) + + "MB (instead of " + ((TREES_TO_DRAW * 38) / 1024 / 1024) + "MB)"); + } } diff --git a/src/refactoring_guru/flyweight/example/forest/Forest.java b/src/refactoring_guru/flyweight/example/forest/Forest.java index 7dff7a4..5fbfb53 100644 --- a/src/refactoring_guru/flyweight/example/forest/Forest.java +++ b/src/refactoring_guru/flyweight/example/forest/Forest.java @@ -10,18 +10,18 @@ import java.util.List; public class Forest extends JFrame { - private List trees = new ArrayList<>(); + private final List trees = new ArrayList<>(); - public void plantTree(int x, int y, String name, Color color, String otherTreeData) { - TreeType type = TreeFactory.getTreeType(name, color, otherTreeData); - Tree tree = new Tree(x, y, type); - trees.add(tree); - } + public void plantTree(int x, int y, String name) { + TreeType type = TreeFactory.getTreeType(name); + Tree tree = new Tree(x, y, type); + trees.add(tree); + } - @Override - public void paint(Graphics graphics) { - for (Tree tree : trees) { - tree.draw(graphics); - } + @Override + public void paint(Graphics graphics) { + for (Tree tree : trees) { + tree.draw(graphics); } + } } diff --git a/src/refactoring_guru/flyweight/example/trees/Tree.java b/src/refactoring_guru/flyweight/example/trees/Tree.java index d86e5ea..5bb7493 100644 --- a/src/refactoring_guru/flyweight/example/trees/Tree.java +++ b/src/refactoring_guru/flyweight/example/trees/Tree.java @@ -3,17 +3,17 @@ import java.awt.*; public class Tree { - private int x; - private int y; - private TreeType type; + private final int xCoordinate; + private final int yCoordinate; + private final TreeType treeType; - public Tree(int x, int y, TreeType type) { - this.x = x; - this.y = y; - this.type = type; - } + public Tree(int xCoordinate, int yCoordinate, TreeType treeType) { + this.xCoordinate = xCoordinate; + this.yCoordinate = yCoordinate; + this.treeType = treeType; + } - public void draw(Graphics g) { - type.draw(g, x, y); - } + public void draw(Graphics g) { + treeType.draw(g, xCoordinate, yCoordinate); + } } diff --git a/src/refactoring_guru/flyweight/example/trees/TreeFactory.java b/src/refactoring_guru/flyweight/example/trees/TreeFactory.java index 5f4f9fe..7a6016c 100644 --- a/src/refactoring_guru/flyweight/example/trees/TreeFactory.java +++ b/src/refactoring_guru/flyweight/example/trees/TreeFactory.java @@ -1,18 +1,16 @@ package refactoring_guru.flyweight.example.trees; -import java.awt.*; import java.util.HashMap; import java.util.Map; -public class TreeFactory { - static Map treeTypes = new HashMap<>(); +public final class TreeFactory { + private static final Map treeTypes = new HashMap<>(); - public static TreeType getTreeType(String name, Color color, String otherTreeData) { - TreeType result = treeTypes.get(name); - if (result == null) { - result = new TreeType(name, color, otherTreeData); - treeTypes.put(name, result); - } - return result; - } + private TreeFactory() throws InstantiationException { + throw new InstantiationException("Cannot create an instance of this class"); + } + + public static TreeType getTreeType(String name) { + return treeTypes.computeIfAbsent(name, k -> getTreeType(name)); + } } diff --git a/src/refactoring_guru/flyweight/example/trees/TreeType.java b/src/refactoring_guru/flyweight/example/trees/TreeType.java index 73c720b..32cea46 100644 --- a/src/refactoring_guru/flyweight/example/trees/TreeType.java +++ b/src/refactoring_guru/flyweight/example/trees/TreeType.java @@ -3,20 +3,16 @@ import java.awt.*; public class TreeType { - private String name; - private Color color; - private String otherTreeData; + private final Color color; - public TreeType(String name, Color color, String otherTreeData) { - this.name = name; - this.color = color; - this.otherTreeData = otherTreeData; - } + public TreeType(Color color) { + this.color = color; + } - public void draw(Graphics g, int x, int y) { - g.setColor(Color.BLACK); - g.fillRect(x - 1, y, 3, 5); - g.setColor(color); - g.fillOval(x - 5, y - 10, 10, 10); - } + public void draw(Graphics g, int x, int y) { + g.setColor(Color.BLACK); + g.fillRect(x - 1, y, 3, 5); + g.setColor(color); + g.fillOval(x - 5, y - 10, 10, 10); + } } From 725706da8904846596ccfdbdcea02c93a815991d Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Wed, 4 Oct 2023 16:25:53 +0300 Subject: [PATCH 23/45] minor update --- src/refactoring_guru/facade/example/Demo.java | 11 +++----- .../example/facade/VideoConversionFacade.java | 25 +++++++------------ .../AudioMixer.java | 8 +++--- .../BitrateReader.java | 24 ++++++++++-------- .../CodecFactory.java | 25 +++++++++++-------- .../MPEG4CompressionCodec.java | 3 +-- .../OggCompressionCodec.java | 2 +- .../some_complex_media_library/VideoFile.java | 24 +++++++++--------- 8 files changed, 59 insertions(+), 63 deletions(-) diff --git a/src/refactoring_guru/facade/example/Demo.java b/src/refactoring_guru/facade/example/Demo.java index eb1c8e1..1f1efe6 100644 --- a/src/refactoring_guru/facade/example/Demo.java +++ b/src/refactoring_guru/facade/example/Demo.java @@ -2,12 +2,9 @@ import refactoring_guru.facade.example.facade.VideoConversionFacade; -import java.io.File; - public class Demo { - public static void main(String[] args) { - VideoConversionFacade converter = new VideoConversionFacade(); - File mp4Video = converter.convertVideo("youtubevideo.ogg", "mp4"); - // ... - } + public static void main(String[] args) { + VideoConversionFacade converter = new VideoConversionFacade(); + converter.convertVideo("youtubevideo.ogg"); + } } diff --git a/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java b/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java index 5ae11d0..ef6c3d2 100644 --- a/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java +++ b/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java @@ -5,20 +5,13 @@ import java.io.File; public class VideoConversionFacade { - public File convertVideo(String fileName, String format) { - System.out.println("VideoConversionFacade: conversion started."); - VideoFile file = new VideoFile(fileName); - Codec sourceCodec = CodecFactory.extract(file); - Codec destinationCodec; - if (format.equals("mp4")) { - destinationCodec = new MPEG4CompressionCodec(); - } else { - destinationCodec = new OggCompressionCodec(); - } - VideoFile buffer = BitrateReader.read(file, sourceCodec); - VideoFile intermediateResult = BitrateReader.convert(buffer, destinationCodec); - File result = (new AudioMixer()).fix(intermediateResult); - System.out.println("VideoConversionFacade: conversion completed."); - return result; - } + public void convertVideo(String fileName) { + System.out.println("VideoConversionFacade: conversion started."); + VideoFile file = new VideoFile(fileName); + + VideoFile buffer = BitrateReader.read(file); + VideoFile intermediateResult = BitrateReader.convert(buffer); + File result = (new AudioMixer()).fix(intermediateResult); + System.out.println("VideoConversionFacade: conversion completed."); + } } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/AudioMixer.java b/src/refactoring_guru/facade/example/some_complex_media_library/AudioMixer.java index 399145d..e334ac8 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/AudioMixer.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/AudioMixer.java @@ -3,8 +3,8 @@ import java.io.File; public class AudioMixer { - public File fix(VideoFile result){ - System.out.println("AudioMixer: fixing audio..."); - return new File("tmp"); - } + public File fix(VideoFile result) { + System.out.println("AudioMixer: fixing audio..."); + return new File("tmp"); + } } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/BitrateReader.java b/src/refactoring_guru/facade/example/some_complex_media_library/BitrateReader.java index cc2d57f..148ace5 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/BitrateReader.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/BitrateReader.java @@ -1,13 +1,17 @@ package refactoring_guru.facade.example.some_complex_media_library; -public class BitrateReader { - public static VideoFile read(VideoFile file, Codec codec) { - System.out.println("BitrateReader: reading file..."); - return file; - } - - public static VideoFile convert(VideoFile buffer, Codec codec) { - System.out.println("BitrateReader: writing file..."); - return buffer; - } +public final class BitrateReader { + + private BitrateReader() { + } + + public static VideoFile read(VideoFile file) { + System.out.println("BitrateReader: reading file..."); + return file; + } + + public static VideoFile convert(VideoFile buffer) { + System.out.println("BitrateReader: writing file..."); + return buffer; + } } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/CodecFactory.java b/src/refactoring_guru/facade/example/some_complex_media_library/CodecFactory.java index 69a7c4d..b9e17f6 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/CodecFactory.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/CodecFactory.java @@ -1,15 +1,18 @@ package refactoring_guru.facade.example.some_complex_media_library; -public class CodecFactory { - public static Codec extract(VideoFile file) { - String type = file.getCodecType(); - if (type.equals("mp4")) { - System.out.println("CodecFactory: extracting mpeg audio..."); - return new MPEG4CompressionCodec(); - } - else { - System.out.println("CodecFactory: extracting ogg audio..."); - return new OggCompressionCodec(); - } +public final class CodecFactory { + + private CodecFactory() { + } + + public static Codec extract(VideoFile file) { + var type = file.getCodecType(); + if (type.equals("mp4")) { + System.out.println("CodecFactory: extracting mpeg audio..."); + return new MPEG4CompressionCodec(); + } else { + System.out.println("CodecFactory: extracting ogg audio..."); + return new OggCompressionCodec(); } + } } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/MPEG4CompressionCodec.java b/src/refactoring_guru/facade/example/some_complex_media_library/MPEG4CompressionCodec.java index e9e0d29..7bfc78d 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/MPEG4CompressionCodec.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/MPEG4CompressionCodec.java @@ -1,6 +1,5 @@ package refactoring_guru.facade.example.some_complex_media_library; public class MPEG4CompressionCodec implements Codec { - public String type = "mp4"; - + public String type = "mp4"; } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/OggCompressionCodec.java b/src/refactoring_guru/facade/example/some_complex_media_library/OggCompressionCodec.java index 42f200f..81a7c7c 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/OggCompressionCodec.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/OggCompressionCodec.java @@ -1,5 +1,5 @@ package refactoring_guru.facade.example.some_complex_media_library; public class OggCompressionCodec implements Codec { - public String type = "ogg"; + public String type = "ogg"; } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/VideoFile.java b/src/refactoring_guru/facade/example/some_complex_media_library/VideoFile.java index 243035a..a4a9cae 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/VideoFile.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/VideoFile.java @@ -1,19 +1,19 @@ package refactoring_guru.facade.example.some_complex_media_library; public class VideoFile { - private String name; - private String codecType; + private final String name; + private final String codecType; - public VideoFile(String name) { - this.name = name; - this.codecType = name.substring(name.indexOf(".") + 1); - } + public VideoFile(String name) { + this.name = name; + this.codecType = name.substring(name.indexOf(".") + 1); + } - public String getCodecType() { - return codecType; - } + public String getCodecType() { + return codecType; + } - public String getName() { - return name; - } + public String getName() { + return name; + } } From a3d537cd20e916b45f1b60adc9204db010605e76 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 14:47:39 +0300 Subject: [PATCH 24/45] some changes in iterator package --- .../iterator/example/Demo.java | 78 ++++++----- .../example/iterators/FacebookIterator.java | 90 ++++++------ .../example/iterators/LinkedInIterator.java | 90 ++++++------ .../iterator/example/profile/Profile.java | 89 +++++++----- .../example/social_networks/Facebook.java | 128 +++++++++--------- .../example/social_networks/LinkedIn.java | 115 +++++++--------- .../social_networks/SocialNetwork.java | 4 +- .../example/spammer/SocialSpammer.java | 44 +++--- 8 files changed, 326 insertions(+), 312 deletions(-) diff --git a/src/refactoring_guru/iterator/example/Demo.java b/src/refactoring_guru/iterator/example/Demo.java index 31ff314..fb3b9cb 100644 --- a/src/refactoring_guru/iterator/example/Demo.java +++ b/src/refactoring_guru/iterator/example/Demo.java @@ -7,46 +7,58 @@ import refactoring_guru.iterator.example.spammer.SocialSpammer; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Scanner; /** * EN: Demo class. Everything comes together here. - * + *

* RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - public static Scanner scanner = new Scanner(System.in); - - public static void main(String[] args) { - System.out.println("Please specify social network to target spam tool (default:Facebook):"); - System.out.println("1. Facebook"); - System.out.println("2. LinkedIn"); - String choice = scanner.nextLine(); - - SocialNetwork network; - if (choice.equals("2")) { - network = new LinkedIn(createTestProfiles()); - } - else { - network = new Facebook(createTestProfiles()); - } - - SocialSpammer spammer = new SocialSpammer(network); - spammer.sendSpamToFriends("anna.smith@bing.com", - "Hey! This is Anna's friend Josh. Can you do me a favor and like this post [link]?"); - spammer.sendSpamToCoworkers("anna.smith@bing.com", - "Hey! This is Anna's boss Jason. Anna told me you would be interested in [link]."); - } + private static final Scanner scanner = new Scanner(System.in); + private static final String ANNA_EMAIL = "anna.smith@bing.com"; + + public static void main(String[] args) { + System.out.println("Please specify the social network to target the spam tool (default: Facebook):"); + System.out.println("1. Facebook"); + System.out.println("2. LinkedIn"); + String choice = scanner.nextLine(); + + SocialNetwork network = (choice.equals("2")) ? new LinkedIn(createTestProfiles()) : new Facebook(createTestProfiles()); + + SocialSpammer spammer = new SocialSpammer(network); + spammer.sendSpamToFriends(ANNA_EMAIL, + "Hey! This is Anna's friend Josh. Can you do me a favor and like this post [link]?"); + spammer.sendSpamToCoworkers(ANNA_EMAIL, + "Hey! This is Anna's boss Jason. Anna told me you would be interested in [link]."); + } + + @SuppressWarnings("all") + private static List createTestProfiles() { + List data = new ArrayList<>(); + data.add(createProfile(ANNA_EMAIL, "Anna Smith", "friends", "mad_max@ya.com", "catwoman@yahoo.com", "coworkers", "sam@amazon.com")); + data.add(createProfile("mad_max@ya.com", "Maximilian", "friends", ANNA_EMAIL, "coworkers", "sam@amazon.com")); + data.add(createProfile("bill@microsoft.eu", "Billie", "coworkers", "avanger@ukr.net")); + data.add(createProfile("avanger@ukr.net", "John Day", "coworkers", "bill@microsoft.eu")); + data.add(createProfile("sam@amazon.com", "Sam Kitting", "coworkers", ANNA_EMAIL, "mad_max@ya.com", "friends", "catwoman@yahoo.com")); + data.add(createProfile("catwoman@yahoo.com", "Liza", "friends", ANNA_EMAIL, "sam@amazon.com")); + return data; + } - public static List createTestProfiles() { - List data = new ArrayList(); - data.add(new Profile("anna.smith@bing.com", "Anna Smith", "friends:mad_max@ya.com", "friends:catwoman@yahoo.com", "coworkers:sam@amazon.com")); - data.add(new Profile("mad_max@ya.com", "Maximilian", "friends:anna.smith@bing.com", "coworkers:sam@amazon.com")); - data.add(new Profile("bill@microsoft.eu", "Billie", "coworkers:avanger@ukr.net")); - data.add(new Profile("avanger@ukr.net", "John Day", "coworkers:bill@microsoft.eu")); - data.add(new Profile("sam@amazon.com", "Sam Kitting", "coworkers:anna.smith@bing.com", "coworkers:mad_max@ya.com", "friends:catwoman@yahoo.com")); - data.add(new Profile("catwoman@yahoo.com", "Liza", "friends:anna.smith@bing.com", "friends:sam@amazon.com")); - return data; + private static Profile createProfile(String email, String name, String... contacts) { + Map> contactMap = new HashMap<>(); + for (int i = 0; i < contacts.length; i += 2) { + var contactType = contacts[i]; + var contactEmail = contacts[i + 1]; + contactMap.merge(contactType, new ArrayList<>(Collections.singletonList(contactEmail)), (oldList, newList) -> { + oldList.addAll(newList); + return oldList; + }); } -} \ No newline at end of file + return new Profile(email, name, contactMap); + } +} diff --git a/src/refactoring_guru/iterator/example/iterators/FacebookIterator.java b/src/refactoring_guru/iterator/example/iterators/FacebookIterator.java index 1efb222..c1d471f 100644 --- a/src/refactoring_guru/iterator/example/iterators/FacebookIterator.java +++ b/src/refactoring_guru/iterator/example/iterators/FacebookIterator.java @@ -7,53 +7,53 @@ import java.util.List; public class FacebookIterator implements ProfileIterator { - private Facebook facebook; - private String type; - private String email; - private int currentPosition = 0; - private List emails = new ArrayList<>(); - private List profiles = new ArrayList<>(); - - public FacebookIterator(Facebook facebook, String type, String email) { - this.facebook = facebook; - this.type = type; - this.email = email; + private final Facebook facebook; + private final String type; + private final String email; + private int currentPosition = 0; + private final List emails = new ArrayList<>(); + private final List profiles = new ArrayList<>(); + + public FacebookIterator(Facebook facebook, String type, String email) { + this.facebook = facebook; + this.type = type; + this.email = email; + } + + @Override + public boolean hasNext() { + lazyLoad(); + return currentPosition < emails.size(); + } + + @Override + public Profile getNext() { + if (!hasNext()) { + throw new IllegalArgumentException("Next is null "); } - private void lazyLoad() { - if (emails.size() == 0) { - List profiles = facebook.requestProfileFriendsFromFacebook(this.email, this.type); - for (String profile : profiles) { - this.emails.add(profile); - this.profiles.add(null); - } - } + String friendEmail = emails.get(currentPosition); + Profile friendProfile = profiles.get(currentPosition); + if (friendProfile == null) { + friendProfile = facebook.requestProfileFromFacebook(friendEmail); + profiles.set(currentPosition, friendProfile); } - - @Override - public boolean hasNext() { - lazyLoad(); - return currentPosition < emails.size(); - } - - @Override - public Profile getNext() { - if (!hasNext()) { - return null; - } - - String friendEmail = emails.get(currentPosition); - Profile friendProfile = profiles.get(currentPosition); - if (friendProfile == null) { - friendProfile = facebook.requestProfileFromFacebook(friendEmail); - profiles.set(currentPosition, friendProfile); - } - currentPosition++; - return friendProfile; - } - - @Override - public void reset() { - currentPosition = 0; + currentPosition++; + return friendProfile; + } + + @Override + public void reset() { + currentPosition = 0; + } + + private void lazyLoad() { + if (emails.isEmpty()) { + List socialProfiles = facebook.requestProfileFriendsFromFacebook(this.email, this.type); + for (String profile : socialProfiles) { + this.emails.add(profile); + this.profiles.add(null); + } } + } } diff --git a/src/refactoring_guru/iterator/example/iterators/LinkedInIterator.java b/src/refactoring_guru/iterator/example/iterators/LinkedInIterator.java index 92d4fcc..48a320d 100644 --- a/src/refactoring_guru/iterator/example/iterators/LinkedInIterator.java +++ b/src/refactoring_guru/iterator/example/iterators/LinkedInIterator.java @@ -7,53 +7,53 @@ import java.util.List; public class LinkedInIterator implements ProfileIterator { - private LinkedIn linkedIn; - private String type; - private String email; - private int currentPosition = 0; - private List emails = new ArrayList<>(); - private List contacts = new ArrayList<>(); - - public LinkedInIterator(LinkedIn linkedIn, String type, String email) { - this.linkedIn = linkedIn; - this.type = type; - this.email = email; + private final LinkedIn linkedIn; + private final String type; + private final String email; + private int currentPosition = 0; + private final List emails = new ArrayList<>(); + private final List contacts = new ArrayList<>(); + + public LinkedInIterator(LinkedIn linkedIn, String type, String email) { + this.linkedIn = linkedIn; + this.type = type; + this.email = email; + } + + @Override + public boolean hasNext() { + lazyLoad(); + return currentPosition < emails.size(); + } + + @Override + public Profile getNext() { + if (!hasNext()) { + throw new IllegalArgumentException("Next is null "); } - private void lazyLoad() { - if (emails.size() == 0) { - List profiles = linkedIn.requestRelatedContactsFromLinkedInAPI(this.email, this.type); - for (String profile : profiles) { - this.emails.add(profile); - this.contacts.add(null); - } - } + String friendEmail = emails.get(currentPosition); + Profile friendContact = contacts.get(currentPosition); + if (friendContact == null) { + friendContact = linkedIn.requestContactInfoFromLinkedInAPI(friendEmail); + contacts.set(currentPosition, friendContact); } - - @Override - public boolean hasNext() { - lazyLoad(); - return currentPosition < emails.size(); - } - - @Override - public Profile getNext() { - if (!hasNext()) { - return null; - } - - String friendEmail = emails.get(currentPosition); - Profile friendContact = contacts.get(currentPosition); - if (friendContact == null) { - friendContact = linkedIn.requestContactInfoFromLinkedInAPI(friendEmail); - contacts.set(currentPosition, friendContact); - } - currentPosition++; - return friendContact; - } - - @Override - public void reset() { - currentPosition = 0; + currentPosition++; + return friendContact; + } + + @Override + public void reset() { + currentPosition = 0; + } + + private void lazyLoad() { + if (emails.isEmpty()) { + List profiles = linkedIn.requestRelatedContactsFromLinkedInAPI(this.email, this.type); + for (String profile : profiles) { + this.emails.add(profile); + this.contacts.add(null); + } } + } } diff --git a/src/refactoring_guru/iterator/example/profile/Profile.java b/src/refactoring_guru/iterator/example/profile/Profile.java index ed49864..dd322e4 100644 --- a/src/refactoring_guru/iterator/example/profile/Profile.java +++ b/src/refactoring_guru/iterator/example/profile/Profile.java @@ -1,49 +1,68 @@ package refactoring_guru.iterator.example.profile; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class Profile { - private String name; - private String email; - private Map> contacts = new HashMap<>(); + private final String name; + private final String email; + private final Map> contacts = new HashMap<>(); - public Profile(String email, String name, String... contacts) { - this.email = email; - this.name = name; + /** + * Constructs a new Profile. + * + * @param email the email address of the profile + * @param name the name of the profile + * @param contacts the contact list categorized by contact type + */ + public Profile(String email, String name, Map> contacts) { + this.email = email; + this.name = name; + this.contacts.putAll(contacts); + } - // Parse contact list from a set of "friend:email@gmail.com" pairs. - for (String contact : contacts) { - String[] parts = contact.split(":"); - String contactType = "friend", contactEmail; - if (parts.length == 1) { - contactEmail = parts[0]; - } - else { - contactType = parts[0]; - contactEmail = parts[1]; - } - if (!this.contacts.containsKey(contactType)) { - this.contacts.put(contactType, new ArrayList<>()); - } - this.contacts.get(contactType).add(contactEmail); - } - } + /** + * Returns the email address of this profile. + * + * @return the email address + */ + public String getEmail() { + return email; + } - public String getEmail() { - return email; - } + /** + * Returns the name of this profile. + * + * @return the name + */ + public String getName() { + return name; + } - public String getName() { - return name; - } + /** + * Returns an unmodifiable list of contacts of the specified type. + * + * @param contactType the type of contacts to retrieve + * @return an unmodifiable list of contacts + */ + public List getContacts(String contactType) { + List contactList = contacts.computeIfAbsent(contactType, k -> new ArrayList<>()); + return Collections.unmodifiableList(contactList); + } - public List getContacts(String contactType) { - if (!this.contacts.containsKey(contactType)) { - this.contacts.put(contactType, new ArrayList<>()); - } - return contacts.get(contactType); - } + /** + * Adds a contact to this profile. + * + * @param contactType the type of contact + * @param contactEmail the email address of the contact + */ + public void addContact(String contactType, String contactEmail) { + contacts.merge(contactType, new ArrayList<>(List.of(contactEmail)), (oldList, newList) -> { + oldList.addAll(newList); + return oldList; + }); + } } \ No newline at end of file diff --git a/src/refactoring_guru/iterator/example/social_networks/Facebook.java b/src/refactoring_guru/iterator/example/social_networks/Facebook.java index 7c6e6f3..d2e294a 100644 --- a/src/refactoring_guru/iterator/example/social_networks/Facebook.java +++ b/src/refactoring_guru/iterator/example/social_networks/Facebook.java @@ -6,81 +6,77 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class Facebook implements SocialNetwork { - private List profiles; + private final List profiles; - public Facebook(List cache) { - if (cache != null) { - this.profiles = cache; - } else { - this.profiles = new ArrayList<>(); - } - } - - public Profile requestProfileFromFacebook(String profileEmail) { - // EN: Here would be a POST request to one of the Facebook API - // endpoints. Instead, we emulates long network connection, which you - // would expect in the real life... - // - // RU: Здесь бы был POST запрос к одному из адресов API Facebook. Но - // вместо этого мы эмулируем долгое сетевое соединение, прямо как в - // реальной жизни... - simulateNetworkLatency(); - System.out.println("Facebook: Loading profile '" + profileEmail + "' over the network..."); - - // EN: ...and return test data. - // - // RU: ...и возвращаем тестовые данные. - return findProfile(profileEmail); - } + public Facebook(List cache) { + this.profiles = Objects.requireNonNullElseGet(cache, ArrayList::new); + } - public List requestProfileFriendsFromFacebook(String profileEmail, String contactType) { - // EN: Here would be a POST request to one of the Facebook API - // endpoints. Instead, we emulates long network connection, which you - // would expect in the real life... - // - // RU: Здесь бы был POST запрос к одному из адресов API Facebook. Но - // вместо этого мы эмулируем долгое сетевое соединение, прямо как в - // реальной жизни... - simulateNetworkLatency(); - System.out.println("Facebook: Loading '" + contactType + "' list of '" + profileEmail + "' over the network..."); + /** + * EN: Here would be a POST request to one of the Facebook API + * endpoints. Instead, we emulates long network connection, which you + * would expect in the real life + *

+ * RU: Здесь бы был POST запрос к одному из адресов API Facebook. Но + * вместо этого мы эмулируем долгое сетевое соединение, прямо как в + * реальной жизни + * + * @param profileEmail provided the profile mail + * @return expected result + */ + public Profile requestProfileFromFacebook(String profileEmail) { + simulateNetworkLatency(); + System.out.println("Facebook: Loading profile '" + profileEmail + "' over the network..."); + return findProfile(profileEmail); + } - // EN: ...and return test data. - // - // RU: ...и возвращаем тестовые данные. - Profile profile = findProfile(profileEmail); - if (profile != null) { - return profile.getContacts(contactType); - } - return null; - } - - private Profile findProfile(String profileEmail) { - for (Profile profile : profiles) { - if (profile.getEmail().equals(profileEmail)) { - return profile; - } - } - return null; - } + /** + * EN: Here would be a POST request to one of the Facebook API + * endpoints. Instead, we emulates long network connection, which you + * would expect in the real life + *

+ * RU: Здесь бы был POST запрос к одному из адресов API Facebook. Но + * вместо этого мы эмулируем долгое сетевое соединение, прямо как в + * реальной жизни + * + * @param profileEmail provided the profile mail + * @param contactType concrete type of given contact + * @return given data + */ + public List requestProfileFriendsFromFacebook(String profileEmail, String contactType) { + simulateNetworkLatency(); + System.out.println("Facebook: Loading '" + contactType + "' list of '" + profileEmail + "' over the network..."); + Profile profile = findProfile(profileEmail); + return profile.getContacts(contactType); + } - private void simulateNetworkLatency() { - try { - Thread.sleep(2500); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } + private Profile findProfile(String profileEmail) { + for (Profile profile : profiles) { + if (profile.getEmail().equals(profileEmail)) { + return profile; + } } + throw new IllegalArgumentException("Profile isn't found"); + } - @Override - public ProfileIterator createFriendsIterator(String profileEmail) { - return new FacebookIterator(this, "friends", profileEmail); + private void simulateNetworkLatency() { + try { + Thread.sleep(2500); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); } + } - @Override - public ProfileIterator createCoworkersIterator(String profileEmail) { - return new FacebookIterator(this, "coworkers", profileEmail); - } + @Override + public ProfileIterator createFriendsIterator(String profileEmail) { + return new FacebookIterator(this, "friends", profileEmail); + } + @Override + public ProfileIterator createCoworkersIterator(String profileEmail) { + return new FacebookIterator(this, "coworkers", profileEmail); + } } \ No newline at end of file diff --git a/src/refactoring_guru/iterator/example/social_networks/LinkedIn.java b/src/refactoring_guru/iterator/example/social_networks/LinkedIn.java index 28b1965..d1938c4 100644 --- a/src/refactoring_guru/iterator/example/social_networks/LinkedIn.java +++ b/src/refactoring_guru/iterator/example/social_networks/LinkedIn.java @@ -5,81 +5,68 @@ import refactoring_guru.iterator.example.profile.Profile; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Objects; public class LinkedIn implements SocialNetwork { - private List contacts; + private final List contacts; - public LinkedIn(List cache) { - if (cache != null) { - this.contacts = cache; - } else { - this.contacts = new ArrayList<>(); - } - } - - public Profile requestContactInfoFromLinkedInAPI(String profileEmail) { - // EN: Here would be a POST request to one of the LinkedIn API - // endpoints. Instead, we emulates long network connection, which you - // would expect in the real life... - // - // RU: Здесь бы был POST запрос к одному из адресов API LinkedIn. Но - // вместо этого мы эмулируем долгое сетевое соединение, прямо как в - // реальной жизни... - simulateNetworkLatency(); - System.out.println("LinkedIn: Loading profile '" + profileEmail + "' over the network..."); - - // EN: ...and return test data. - // - // RU: ...и возвращаем тестовые данные. - return findContact(profileEmail); - } + public LinkedIn(List cache) { + this.contacts = Objects.requireNonNullElseGet(cache, ArrayList::new); + } - public List requestRelatedContactsFromLinkedInAPI(String profileEmail, String contactType) { - // EN: Here would be a POST request to one of the LinkedIn API - // endpoints. Instead, we emulates long network connection, which you - // would expect in the real life. - // - // RU: Здесь бы был POST запрос к одному из адресов API LinkedIn. Но - // вместо этого мы эмулируем долгое сетевое соединение, прямо как в - // реальной жизни... - simulateNetworkLatency(); - System.out.println("LinkedIn: Loading '" + contactType + "' list of '" + profileEmail + "' over the network..."); + /** + * EN: Here would be a POST request to one of the LinkedIn API + * endpoints. Instead, we emulates long network connection, which you + * would expect in the real life... + *

+ * RU: Здесь бы был POST запрос к одному из адресов API LinkedIn. Но + * вместо этого мы эмулируем долгое сетевое соединение, прямо как в + * реальной жизни + * @param profileEmail the given mail + * @return the data + */ + public Profile requestContactInfoFromLinkedInAPI(String profileEmail) { + simulateNetworkLatency(); + System.out.println("LinkedIn: Loading profile '" + profileEmail + "' over the network..."); + return findContact(profileEmail); + } - // EN: ...and return test data. - // - // RU: ...и возвращаем тестовые данные. - Profile profile = findContact(profileEmail); - if (profile != null) { - return profile.getContacts(contactType); - } - return null; + public List requestRelatedContactsFromLinkedInAPI(String profileEmail, String contactType) { + simulateNetworkLatency(); + System.out.println("LinkedIn: Loading '" + contactType + "' list of '" + profileEmail + "' over the network..."); + Profile profile = findContact(profileEmail); + if (profile != null) { + return profile.getContacts(contactType); } + return Collections.emptyList(); + } - private Profile findContact(String profileEmail) { - for (Profile profile : contacts) { - if (profile.getEmail().equals(profileEmail)) { - return profile; - } - } - return null; + private Profile findContact(String profileEmail) { + for (Profile profile : contacts) { + if (profile.getEmail().equals(profileEmail)) { + return profile; + } } + throw new IllegalArgumentException("Contact isn't found"); + } - private void simulateNetworkLatency() { - try { - Thread.sleep(2500); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } + private void simulateNetworkLatency() { + try { + Thread.sleep(2500); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); } + } - @Override - public ProfileIterator createFriendsIterator(String profileEmail) { - return new LinkedInIterator(this, "friends", profileEmail); - } + @Override + public ProfileIterator createFriendsIterator(String profileEmail) { + return new LinkedInIterator(this, "friends", profileEmail); + } - @Override - public ProfileIterator createCoworkersIterator(String profileEmail) { - return new LinkedInIterator(this, "coworkers", profileEmail); - } + @Override + public ProfileIterator createCoworkersIterator(String profileEmail) { + return new LinkedInIterator(this, "coworkers", profileEmail); + } } diff --git a/src/refactoring_guru/iterator/example/social_networks/SocialNetwork.java b/src/refactoring_guru/iterator/example/social_networks/SocialNetwork.java index 65597af..c1d0a64 100644 --- a/src/refactoring_guru/iterator/example/social_networks/SocialNetwork.java +++ b/src/refactoring_guru/iterator/example/social_networks/SocialNetwork.java @@ -3,7 +3,7 @@ import refactoring_guru.iterator.example.iterators.ProfileIterator; public interface SocialNetwork { - ProfileIterator createFriendsIterator(String profileEmail); + ProfileIterator createFriendsIterator(String profileEmail); - ProfileIterator createCoworkersIterator(String profileEmail); + ProfileIterator createCoworkersIterator(String profileEmail); } diff --git a/src/refactoring_guru/iterator/example/spammer/SocialSpammer.java b/src/refactoring_guru/iterator/example/spammer/SocialSpammer.java index 9e6c99a..648d848 100644 --- a/src/refactoring_guru/iterator/example/spammer/SocialSpammer.java +++ b/src/refactoring_guru/iterator/example/spammer/SocialSpammer.java @@ -5,32 +5,32 @@ import refactoring_guru.iterator.example.social_networks.SocialNetwork; public class SocialSpammer { - public SocialNetwork network; - public ProfileIterator iterator; + public SocialNetwork network; + public ProfileIterator iterator; - public SocialSpammer(SocialNetwork network) { - this.network = network; - } + public SocialSpammer(SocialNetwork network) { + this.network = network; + } - public void sendSpamToFriends(String profileEmail, String message) { - System.out.println("\nIterating over friends...\n"); - iterator = network.createFriendsIterator(profileEmail); - while (iterator.hasNext()) { - Profile profile = iterator.getNext(); - sendMessage(profile.getEmail(), message); - } + public void sendSpamToFriends(String profileEmail, String message) { + System.out.println("\nIterating over friends...\n"); + iterator = network.createFriendsIterator(profileEmail); + while (iterator.hasNext()) { + Profile profile = iterator.getNext(); + sendMessage(profile.getEmail(), message); } + } - public void sendSpamToCoworkers(String profileEmail, String message) { - System.out.println("\nIterating over coworkers...\n"); - iterator = network.createCoworkersIterator(profileEmail); - while (iterator.hasNext()) { - Profile profile = iterator.getNext(); - sendMessage(profile.getEmail(), message); - } + public void sendSpamToCoworkers(String profileEmail, String message) { + System.out.println("\nIterating over coworkers...\n"); + iterator = network.createCoworkersIterator(profileEmail); + while (iterator.hasNext()) { + Profile profile = iterator.getNext(); + sendMessage(profile.getEmail(), message); } + } - public void sendMessage(String email, String message) { - System.out.println("Sent message to: '" + email + "'. Message body: '" + message + "'"); - } + public void sendMessage(String email, String message) { + System.out.println("Sent a message to: '" + email + "'. Message body: '" + message + "'"); + } } \ No newline at end of file From debec56e2176e93fcc8b630f57397ff7dc5a05c9 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 15:00:56 +0300 Subject: [PATCH 25/45] some changes in Command package --- .../command/example/commands/Command.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/refactoring_guru/command/example/commands/Command.java b/src/refactoring_guru/command/example/commands/Command.java index 9a6c680..88d7775 100644 --- a/src/refactoring_guru/command/example/commands/Command.java +++ b/src/refactoring_guru/command/example/commands/Command.java @@ -3,20 +3,20 @@ import refactoring_guru.command.example.editor.Editor; public abstract class Command { - public Editor editor; - private String backup; + public Editor editor; + private String backup; - Command(Editor editor) { - this.editor = editor; - } + Command(Editor editor) { + this.editor = editor; + } - void backup() { - backup = editor.textField.getText(); - } + void backup() { + backup = editor.textField.getText(); + } - public void undo() { - editor.textField.setText(backup); - } + public void undo() { + editor.textField.setText(backup); + } - public abstract boolean execute(); + public abstract boolean execute(); } From cfc915de4ceb446703e7fc1d3a9d7423f27c0789 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 15:02:06 +0300 Subject: [PATCH 26/45] some changes in Iterator package --- .../iterator/example/iterators/ProfileIterator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/refactoring_guru/iterator/example/iterators/ProfileIterator.java b/src/refactoring_guru/iterator/example/iterators/ProfileIterator.java index f07b7be..411dd01 100644 --- a/src/refactoring_guru/iterator/example/iterators/ProfileIterator.java +++ b/src/refactoring_guru/iterator/example/iterators/ProfileIterator.java @@ -3,9 +3,9 @@ import refactoring_guru.iterator.example.profile.Profile; public interface ProfileIterator { - boolean hasNext(); + boolean hasNext(); - Profile getNext(); + Profile getNext(); - void reset(); + void reset(); } \ No newline at end of file From 2e022d93d51b9df9abfb8df2697cc470ced9b455 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 15:43:07 +0300 Subject: [PATCH 27/45] some changes in Mediator package --- .../mediator/example/Demo.java | 36 +- .../example/components/AddButton.java | 34 +- .../example/components/Component.java | 7 +- .../example/components/DeleteButton.java | 36 +- .../mediator/example/components/Filter.java | 86 +++-- .../mediator/example/components/InitList.java | 74 ++++ .../example/components/SaveButton.java | 34 +- .../mediator/example/components/TextBox.java | 28 +- .../mediator/example/components/Title.java | 28 +- .../mediator/example/mediator/Editor.java | 330 +++++++++--------- .../mediator/example/mediator/Mediator.java | 34 +- .../mediator/example/mediator/Note.java | 44 +-- 12 files changed, 427 insertions(+), 344 deletions(-) create mode 100644 src/refactoring_guru/mediator/example/components/InitList.java diff --git a/src/refactoring_guru/mediator/example/Demo.java b/src/refactoring_guru/mediator/example/Demo.java index 14f5612..ec160df 100644 --- a/src/refactoring_guru/mediator/example/Demo.java +++ b/src/refactoring_guru/mediator/example/Demo.java @@ -3,26 +3,38 @@ import refactoring_guru.mediator.example.components.*; import refactoring_guru.mediator.example.mediator.Editor; import refactoring_guru.mediator.example.mediator.Mediator; +import refactoring_guru.mediator.example.mediator.Note; import javax.swing.*; /** * EN: Demo class. Everything comes together here. - * + *

* RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - public static void main(String[] args) { - Mediator mediator = new Editor(); + public static void main(String[] args) { + Mediator mediator = new Editor(); + ListModel noteList = new AbstractListModel<>() { + @Override + public int getSize() { + return 0; + } - mediator.registerComponent(new Title()); - mediator.registerComponent(new TextBox()); - mediator.registerComponent(new AddButton()); - mediator.registerComponent(new DeleteButton()); - mediator.registerComponent(new SaveButton()); - mediator.registerComponent(new List(new DefaultListModel())); - mediator.registerComponent(new Filter()); + @Override + public Note getElementAt(int i) { + return null; + } + }; - mediator.createGUI(); - } + mediator.registerComponent(new Title()); + mediator.registerComponent(new TextBox()); + mediator.registerComponent(new AddButton()); + mediator.registerComponent(new DeleteButton()); + mediator.registerComponent(new SaveButton()); + mediator.registerComponent(new InitList(new DefaultListModel<>())); + mediator.registerComponent(new Filter(mediator, noteList)); + + mediator.createGUI(); + } } diff --git a/src/refactoring_guru/mediator/example/components/AddButton.java b/src/refactoring_guru/mediator/example/components/AddButton.java index 6c351d4..eb56fdf 100644 --- a/src/refactoring_guru/mediator/example/components/AddButton.java +++ b/src/refactoring_guru/mediator/example/components/AddButton.java @@ -9,29 +9,29 @@ /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - * + *

* RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ public class AddButton extends JButton implements Component { - private Mediator mediator; + private transient Mediator mediator; - public AddButton() { - super("Add"); - } + public AddButton() { + super("Add"); + } - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } - @Override - protected void fireActionPerformed(ActionEvent actionEvent) { - mediator.addNewNote(new Note()); - } + @Override + protected void fireActionPerformed(ActionEvent actionEvent) { + mediator.addNewNote(new Note()); + } - @Override - public String getName() { - return "AddButton"; - } + @Override + public String getName() { + return "AddButton"; + } } diff --git a/src/refactoring_guru/mediator/example/components/Component.java b/src/refactoring_guru/mediator/example/components/Component.java index 780ff40..14ad5a9 100644 --- a/src/refactoring_guru/mediator/example/components/Component.java +++ b/src/refactoring_guru/mediator/example/components/Component.java @@ -4,10 +4,11 @@ /** * EN: Common component interface. - * + *

* RU: Общий интерфейс компонентов. */ public interface Component { - void setMediator(Mediator mediator); - String getName(); + void setMediator(Mediator mediator); + + String getName(); } diff --git a/src/refactoring_guru/mediator/example/components/DeleteButton.java b/src/refactoring_guru/mediator/example/components/DeleteButton.java index b9389a6..b822bf0 100644 --- a/src/refactoring_guru/mediator/example/components/DeleteButton.java +++ b/src/refactoring_guru/mediator/example/components/DeleteButton.java @@ -8,29 +8,29 @@ /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - * + *

* RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ -public class DeleteButton extends JButton implements Component { - private Mediator mediator; +public class DeleteButton extends JButton implements Component { + private transient Mediator mediator; - public DeleteButton() { - super("Del"); - } + public DeleteButton() { + super("Del"); + } - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } - @Override - protected void fireActionPerformed(ActionEvent actionEvent) { - mediator.deleteNote(); - } + @Override + protected void fireActionPerformed(ActionEvent actionEvent) { + mediator.deleteNote(); + } - @Override - public String getName() { - return "DelButton"; - } + @Override + public String getName() { + return "DelButton"; + } } diff --git a/src/refactoring_guru/mediator/example/components/Filter.java b/src/refactoring_guru/mediator/example/components/Filter.java index c60aa0e..4fddf08 100644 --- a/src/refactoring_guru/mediator/example/components/Filter.java +++ b/src/refactoring_guru/mediator/example/components/Filter.java @@ -5,61 +5,57 @@ import javax.swing.*; import java.awt.event.KeyEvent; -import java.util.ArrayList; +import javax.swing.DefaultListModel; /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - * + *

* RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ public class Filter extends JTextField implements Component { - private Mediator mediator; - private ListModel listModel; - - public Filter() {} - - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; + private transient Mediator mediator; + private transient ListModel listModel; + + public Filter(Mediator mediator, ListModel listModel) { + this.mediator = mediator; + this.listModel = listModel; + } + + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + @Override + protected void processComponentKeyEvent(KeyEvent keyEvent) { + String start = getText(); + searchElements(start); + } + + public void setList(ListModel listModel) { + this.listModel = listModel; + } + + private void searchElements(String s) { + if (listModel == null || s.equals("")) { + mediator.setElementsList(listModel); + return; } - @Override - protected void processComponentKeyEvent(KeyEvent keyEvent) { - String start = getText(); - searchElements(start); + DefaultListModel filteredListModel = new DefaultListModel<>(); + for (int i = 0; i < listModel.getSize(); i++) { + Note note = listModel.getElementAt(i); + if (note.getName().contains(s)) { + filteredListModel.addElement(note); + } } + mediator.setElementsList(filteredListModel); + } - public void setList(ListModel listModel) { - this.listModel = listModel; - } - - private void searchElements(String s) { - if (listModel == null) { - return; - } - - if (s.equals("")) { - mediator.setElementsList(listModel); - return; - } - - ArrayList notes = new ArrayList<>(); - for (int i = 0; i < listModel.getSize(); i++) { - notes.add((Note) listModel.getElementAt(i)); - } - DefaultListModel listModel = new DefaultListModel<>(); - for (Note note : notes) { - if (note.getName().contains(s)) { - listModel.addElement(note); - } - } - mediator.setElementsList(listModel); - } - - @Override - public String getName() { - return "Filter"; - } + @Override + public String getName() { + return "Filter"; + } } diff --git a/src/refactoring_guru/mediator/example/components/InitList.java b/src/refactoring_guru/mediator/example/components/InitList.java new file mode 100644 index 0000000..5159de0 --- /dev/null +++ b/src/refactoring_guru/mediator/example/components/InitList.java @@ -0,0 +1,74 @@ +package refactoring_guru.mediator.example.components; + +import refactoring_guru.mediator.example.mediator.Mediator; +import refactoring_guru.mediator.example.mediator.Note; + +import javax.swing.*; + +/** + * EN: Concrete components don't talk with each other. They have only one + * communication channel–sending requests to the mediator. + *

+ * RU: Конкретные компоненты никак не связаны между собой. У них есть только + * один канал общения – через отправку уведомлений посреднику. + */ +@SuppressWarnings("unchecked") +public class InitList extends JList implements Component { + private transient Mediator mediator; + private final DefaultListModel listModel; + private static final boolean running = true; + + public InitList(DefaultListModel listModel) { + super(listModel); + this.listModel = listModel; + setModel(listModel); + this.setLayoutOrientation(JList.VERTICAL); + Thread thread = new Thread(new Hide(this)); + thread.start(); + } + + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + public void addElement(Note note) { + listModel.addElement(note); + int index = listModel.size() - 1; + setSelectedIndex(index); + ensureIndexIsVisible(index); + mediator.sendToFilter(listModel); + } + + public void deleteElement() { + int index = this.getSelectedIndex(); + if (index >= 0 && index < listModel.size()) { + listModel.remove(index); + mediator.sendToFilter(listModel); + } + } + + public Note getCurrentElement() { + return (Note) getSelectedValue(); + } + + @Override + public String getName() { + return "List"; + } + + private class Hide implements Runnable { + private final InitList list; + + Hide(InitList list) { + this.list = list; + } + + @Override + public void run() { + while (running) { + SwingUtilities.invokeLater(() -> mediator.hideElements(list.isSelectionEmpty())); + } + } + } +} diff --git a/src/refactoring_guru/mediator/example/components/SaveButton.java b/src/refactoring_guru/mediator/example/components/SaveButton.java index 52f897f..4a417ac 100644 --- a/src/refactoring_guru/mediator/example/components/SaveButton.java +++ b/src/refactoring_guru/mediator/example/components/SaveButton.java @@ -8,29 +8,29 @@ /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - * + *

* RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ public class SaveButton extends JButton implements Component { - private Mediator mediator; + private transient Mediator mediator; - public SaveButton() { - super("Save"); - } + public SaveButton() { + super("Save"); + } - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } - @Override - protected void fireActionPerformed(ActionEvent actionEvent) { - mediator.saveChanges(); - } + @Override + protected void fireActionPerformed(ActionEvent actionEvent) { + mediator.saveChanges(); + } - @Override - public String getName() { - return "SaveButton"; - } + @Override + public String getName() { + return "SaveButton"; + } } diff --git a/src/refactoring_guru/mediator/example/components/TextBox.java b/src/refactoring_guru/mediator/example/components/TextBox.java index fff5887..2cabad3 100644 --- a/src/refactoring_guru/mediator/example/components/TextBox.java +++ b/src/refactoring_guru/mediator/example/components/TextBox.java @@ -8,25 +8,25 @@ /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - * + *

* RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ public class TextBox extends JTextArea implements Component { - private Mediator mediator; + private transient Mediator mediator; - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } - @Override - protected void processComponentKeyEvent(KeyEvent keyEvent) { - mediator.markNote(); - } + @Override + protected void processComponentKeyEvent(KeyEvent keyEvent) { + mediator.markNote(); + } - @Override - public String getName() { - return "TextBox"; - } + @Override + public String getName() { + return "TextBox"; + } } diff --git a/src/refactoring_guru/mediator/example/components/Title.java b/src/refactoring_guru/mediator/example/components/Title.java index 4f0e0b9..e15d555 100644 --- a/src/refactoring_guru/mediator/example/components/Title.java +++ b/src/refactoring_guru/mediator/example/components/Title.java @@ -8,25 +8,25 @@ /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - * + *

* RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ public class Title extends JTextField implements Component { - private Mediator mediator; + private transient Mediator mediator; - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } - @Override - protected void processComponentKeyEvent(KeyEvent keyEvent) { - mediator.markNote(); - } + @Override + protected void processComponentKeyEvent(KeyEvent keyEvent) { + mediator.markNote(); + } - @Override - public String getName() { - return "Title"; - } + @Override + public String getName() { + return "Title"; + } } diff --git a/src/refactoring_guru/mediator/example/mediator/Editor.java b/src/refactoring_guru/mediator/example/mediator/Editor.java index d60ff2a..c506569 100644 --- a/src/refactoring_guru/mediator/example/mediator/Editor.java +++ b/src/refactoring_guru/mediator/example/mediator/Editor.java @@ -2,201 +2,191 @@ import refactoring_guru.mediator.example.components.*; import refactoring_guru.mediator.example.components.Component; -import refactoring_guru.mediator.example.components.List; +import refactoring_guru.mediator.example.components.InitList; import javax.swing.*; import javax.swing.border.LineBorder; import java.awt.*; +import java.util.logging.Level; +import java.util.logging.Logger; /** * EN: Concrete mediator. All chaotic communications between concrete components * have been extracted to the mediator. Now components only talk with the * mediator, which knows who has to handle a request. - * + *

* RU: Конкретный посредник. Все связи между конкретными компонентами переехали * в код посредника. Он получает извещения от своих компонентов и знает как на * них реагировать. */ public class Editor implements Mediator { - private Title title; - private TextBox textBox; - private AddButton add; - private DeleteButton del; - private SaveButton save; - private List list; - private Filter filter; - - private JLabel titleLabel = new JLabel("Title:"); - private JLabel textLabel = new JLabel("Text:"); - private JLabel label = new JLabel("Add or select existing note to proceed..."); - - /** - * EN: Here the registration of components by the mediator. - * - * RU: Здесь происходит регистрация компонентов посредником. - */ - @Override - public void registerComponent(Component component) { - component.setMediator(this); - switch (component.getName()) { - case "AddButton": - add = (AddButton)component; - break; - case "DelButton": - del = (DeleteButton)component; - break; - case "Filter": - filter = (Filter)component; - break; - case "List": - list = (List)component; - this.list.addListSelectionListener(listSelectionEvent -> { - Note note = (Note)list.getSelectedValue(); - if (note != null) { - getInfoFromList(note); - } else { - clear(); - } - }); - break; - case "SaveButton": - save = (SaveButton)component; - break; - case "TextBox": - textBox = (TextBox)component; - break; - case "Title": - title = (Title)component; - break; - } - } + private Title title; + private TextBox textBox; + private AddButton add; + private DeleteButton del; + private SaveButton save; + private InitList list; + private Filter filter; - /** - * EN: Various methods to handle requests from particular components. - * - * RU: Разнообразные методы общения с компонентами. - */ - @Override - public void addNewNote(Note note) { - title.setText(""); - textBox.setText(""); - list.addElement(note); - } + private final JLabel titleLabel = new JLabel("Title:"); + private final JLabel textLabel = new JLabel("Text:"); + private final JLabel label = new JLabel("Add or select existing note to proceed..."); - @Override - public void deleteNote() { - list.deleteElement(); + /** + * EN: Here the registration of components by the mediator. + *

+ * RU: Здесь происходит регистрация компонентов посредником. + */ + @Override + public void registerComponent(Component component) { + component.setMediator(this); + switch (component.getName()) { + case "AddButton" -> add = (AddButton) component; + case "DelButton" -> del = (DeleteButton) component; + case "Filter" -> filter = (Filter) component; + case "List" -> list = (InitList) component; // assign the component to list + case "SaveButton" -> save = (SaveButton) component; + case "TextBox" -> textBox = (TextBox) component; + case "Title" -> title = (Title) component; + default -> Logger.getLogger(Editor.class.getName()) + .log(Level.WARNING, () -> "Unknown component: " + component.getName()); } - @Override - public void getInfoFromList(Note note) { - title.setText(note.getName().replace('*', ' ')); - textBox.setText(note.getText()); + if (list != null) { + list.addListSelectionListener(listSelectionEvent -> { + Note note = (Note) list.getSelectedValue(); + if (note != null) { + getInfoFromList(note); + } else { + clear(); + } + }); } - @Override - public void saveChanges() { - try { - Note note = (Note) list.getSelectedValue(); - note.setName(title.getText()); - note.setText(textBox.getText()); - list.repaint(); - } catch (NullPointerException ignored) {} - } + } - @Override - public void markNote() { - try { - Note note = list.getCurrentElement(); - String name = note.getName(); - if (!name.endsWith("*")) { - note.setName(note.getName() + "*"); - } - list.repaint(); - } catch (NullPointerException ignored) {} - } + /** + * EN: Various methods to handle requests from particular components. + *

+ * RU: Разнообразные методы общения с компонентами. + */ + @Override + public void addNewNote(Note note) { + title.setText(""); + textBox.setText(""); + list.addElement(note); + } - @Override - public void clear() { - title.setText(""); - textBox.setText(""); - } + @Override + public void deleteNote() { + list.deleteElement(); + } - @Override - public void sendToFilter(ListModel listModel) { - filter.setList(listModel); - } + @Override + public void getInfoFromList(Note note) { + title.setText(note.getName().replace('*', ' ')); + textBox.setText(note.getText()); + } - @SuppressWarnings("unchecked") - @Override - public void setElementsList(ListModel list) { - this.list.setModel(list); - this.list.repaint(); - } + @Override + public void saveChanges() { + Note note = (Note) list.getSelectedValue(); + note.setName(title.getText()); + note.setText(textBox.getText()); + list.repaint(); + } - @Override - public void hideElements(boolean flag) { - titleLabel.setVisible(!flag); - textLabel.setVisible(!flag); - title.setVisible(!flag); - textBox.setVisible(!flag); - save.setVisible(!flag); - label.setVisible(flag); + @Override + public void markNote() { + Note note = list.getCurrentElement(); + String name = note.getName(); + if (!name.endsWith("*")) { + note.setName(note.getName() + "*"); } + list.repaint(); + } - @Override - public void createGUI() { - JFrame notes = new JFrame("Notes"); - notes.setSize(960, 600); - notes.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - JPanel left = new JPanel(); - left.setBorder(new LineBorder(Color.BLACK)); - left.setSize(320, 600); - left.setLayout(new BoxLayout(left, BoxLayout.Y_AXIS)); - JPanel filterPanel = new JPanel(); - filterPanel.add(new JLabel("Filter:")); - filter.setColumns(20); - filterPanel.add(filter); - filterPanel.setPreferredSize(new Dimension(280, 40)); - JPanel listPanel = new JPanel(); - list.setFixedCellWidth(260); - listPanel.setSize(320, 470); - JScrollPane scrollPane = new JScrollPane(list); - scrollPane.setPreferredSize(new Dimension(275, 410)); - listPanel.add(scrollPane); - JPanel buttonPanel = new JPanel(); - add.setPreferredSize(new Dimension(85, 25)); - buttonPanel.add(add); - del.setPreferredSize(new Dimension(85, 25)); - buttonPanel.add(del); - buttonPanel.setLayout(new FlowLayout()); - left.add(filterPanel); - left.add(listPanel); - left.add(buttonPanel); - JPanel right = new JPanel(); - right.setLayout(null); - right.setSize(640, 600); - right.setLocation(320, 0); - right.setBorder(new LineBorder(Color.BLACK)); - titleLabel.setBounds(20, 4, 50, 20); - title.setBounds(60, 5, 555, 20); - textLabel.setBounds(20, 4, 50, 130); - textBox.setBorder(new LineBorder(Color.DARK_GRAY)); - textBox.setBounds(20, 80, 595, 410); - save.setBounds(270, 535, 80, 25); - label.setFont(new Font("Verdana", Font.PLAIN, 22)); - label.setBounds(100, 240, 500, 100); - right.add(label); - right.add(titleLabel); - right.add(title); - right.add(textLabel); - right.add(textBox); - right.add(save); - notes.setLayout(null); - notes.getContentPane().add(left); - notes.getContentPane().add(right); - notes.setResizable(false); - notes.setLocationRelativeTo(null); - notes.setVisible(true); - } + @Override + public void clear() { + title.setText(""); + textBox.setText(""); + } + + @Override + public void sendToFilter(ListModel listModel) { + filter.setList(listModel); + } + + @SuppressWarnings("unchecked") + @Override + public void setElementsList(ListModel list) { + this.list.setModel(list); + this.list.repaint(); + } + + @Override + public void hideElements(boolean flag) { + titleLabel.setVisible(!flag); + textLabel.setVisible(!flag); + title.setVisible(!flag); + textBox.setVisible(!flag); + save.setVisible(!flag); + label.setVisible(flag); + } + + @Override + public void createGUI() { + JFrame notes = new JFrame("Notes"); + notes.setSize(960, 600); + notes.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + JPanel left = new JPanel(); + left.setBorder(new LineBorder(Color.BLACK)); + left.setSize(320, 600); + left.setLayout(new BoxLayout(left, BoxLayout.Y_AXIS)); + JPanel filterPanel = new JPanel(); + filterPanel.add(new JLabel("Filter:")); + filter.setColumns(20); + filterPanel.add(filter); + filterPanel.setPreferredSize(new Dimension(280, 40)); + JPanel listPanel = new JPanel(); + list.setFixedCellWidth(260); + listPanel.setSize(320, 470); + JScrollPane scrollPane = new JScrollPane(list); + scrollPane.setPreferredSize(new Dimension(275, 410)); + listPanel.add(scrollPane); + JPanel buttonPanel = new JPanel(); + add.setPreferredSize(new Dimension(85, 25)); + buttonPanel.add(add); + del.setPreferredSize(new Dimension(85, 25)); + buttonPanel.add(del); + buttonPanel.setLayout(new FlowLayout()); + left.add(filterPanel); + left.add(listPanel); + left.add(buttonPanel); + JPanel right = new JPanel(); + right.setLayout(null); + right.setSize(640, 600); + right.setLocation(320, 0); + right.setBorder(new LineBorder(Color.BLACK)); + titleLabel.setBounds(20, 4, 50, 20); + title.setBounds(60, 5, 555, 20); + textLabel.setBounds(20, 4, 50, 130); + textBox.setBorder(new LineBorder(Color.DARK_GRAY)); + textBox.setBounds(20, 80, 595, 410); + save.setBounds(270, 535, 80, 25); + label.setFont(new Font("Verdana", Font.PLAIN, 22)); + label.setBounds(100, 240, 500, 100); + right.add(label); + right.add(titleLabel); + right.add(title); + right.add(textLabel); + right.add(textBox); + right.add(save); + notes.setLayout(null); + notes.getContentPane().add(left); + notes.getContentPane().add(right); + notes.setResizable(false); + notes.setLocationRelativeTo(null); + notes.setVisible(true); + } } diff --git a/src/refactoring_guru/mediator/example/mediator/Mediator.java b/src/refactoring_guru/mediator/example/mediator/Mediator.java index 86806f5..dd3b1b6 100644 --- a/src/refactoring_guru/mediator/example/mediator/Mediator.java +++ b/src/refactoring_guru/mediator/example/mediator/Mediator.java @@ -6,19 +6,29 @@ /** * EN: Common mediator interface. - * + *

* RU: Общий интерфейс посредников. */ public interface Mediator { - void addNewNote(Note note); - void deleteNote(); - void getInfoFromList(Note note); - void saveChanges(); - void markNote(); - void clear(); - void sendToFilter(ListModel listModel); - void setElementsList(ListModel list); - void registerComponent(Component component); - void hideElements(boolean flag); - void createGUI(); + void addNewNote(Note note); + + void deleteNote(); + + void getInfoFromList(Note note); + + void saveChanges(); + + void markNote(); + + void clear(); + + void sendToFilter(ListModel noteListModel); + + void setElementsList(ListModel elementList); + + void registerComponent(Component component); + + void hideElements(boolean flag); + + void createGUI(); } diff --git a/src/refactoring_guru/mediator/example/mediator/Note.java b/src/refactoring_guru/mediator/example/mediator/Note.java index d727fef..6fb06e1 100644 --- a/src/refactoring_guru/mediator/example/mediator/Note.java +++ b/src/refactoring_guru/mediator/example/mediator/Note.java @@ -2,35 +2,35 @@ /** * EN: Note class. - * + *

* RU: Класс заметок. */ public class Note { - private String name; - private String text; + private String name; + private String text; - public Note() { - name = "New note"; - } + public Note() { + name = "New note"; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public void setText(String text) { - this.text = text; - } + public void setText(String text) { + this.text = text; + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public String getText() { - return text; - } + public String getText() { + return text; + } - @Override - public String toString() { - return name; - } + @Override + public String toString() { + return name; + } } From dacf2941b1b62c951b0f393865d4cbb791d44b8c Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 15:49:12 +0300 Subject: [PATCH 28/45] some changes in Memento package --- .../memento/example/Demo.java | 34 +- .../example/commands/ColorCommand.java | 30 +- .../memento/example/commands/Command.java | 5 +- .../memento/example/commands/MoveCommand.java | 70 ++-- .../memento/example/editor/Editor.java | 94 +++-- .../memento/example/editor/Frame.java | 188 ++++++++++ .../memento/example/editor/FrameMemento.java | 5 + .../memento/example/history/History.java | 101 ++--- .../memento/example/history/Memento.java | 20 +- .../memento/example/shapes/BaseShape.java | 227 ++++++----- .../memento/example/shapes/Circle.java | 36 +- .../memento/example/shapes/CompoundShape.java | 354 +++++++++--------- .../memento/example/shapes/Dot.java | 35 +- .../memento/example/shapes/Rectangle.java | 40 +- .../memento/example/shapes/Shape.java | 44 ++- 15 files changed, 747 insertions(+), 536 deletions(-) create mode 100644 src/refactoring_guru/memento/example/editor/Frame.java create mode 100644 src/refactoring_guru/memento/example/editor/FrameMemento.java diff --git a/src/refactoring_guru/memento/example/Demo.java b/src/refactoring_guru/memento/example/Demo.java index da19c60..59e2cbc 100644 --- a/src/refactoring_guru/memento/example/Demo.java +++ b/src/refactoring_guru/memento/example/Demo.java @@ -9,23 +9,23 @@ import java.awt.*; public class Demo { - public static void main(String[] args) { - Editor editor = new Editor(); - editor.loadShapes( - new Circle(10, 10, 10, Color.BLUE), + public static void main(String[] args) { + Editor editor = new Editor(); + editor.loadShapes( + new Circle(10, 10, 10, Color.BLUE), - new CompoundShape( - new Circle(110, 110, 50, Color.RED), - new Dot(160, 160, Color.RED) - ), + new CompoundShape( + new Circle(110, 110, 50, Color.RED), + new Dot(160, 160, Color.RED) + ), - new CompoundShape( - new Rectangle(250, 250, 100, 100, Color.GREEN), - new Dot(240, 240, Color.GREEN), - new Dot(240, 360, Color.GREEN), - new Dot(360, 360, Color.GREEN), - new Dot(360, 240, Color.GREEN) - ) - ); - } + new CompoundShape( + new Rectangle(250, 250, 100, 100, Color.GREEN), + new Dot(240, 240, Color.GREEN), + new Dot(240, 360, Color.GREEN), + new Dot(360, 360, Color.GREEN), + new Dot(360, 240, Color.GREEN) + ) + ); + } } diff --git a/src/refactoring_guru/memento/example/commands/ColorCommand.java b/src/refactoring_guru/memento/example/commands/ColorCommand.java index 3c6d9a3..e71856f 100644 --- a/src/refactoring_guru/memento/example/commands/ColorCommand.java +++ b/src/refactoring_guru/memento/example/commands/ColorCommand.java @@ -6,23 +6,23 @@ import java.awt.*; public class ColorCommand implements Command { - private Editor editor; - private Color color; + private final Editor editor; + private final Color color; - public ColorCommand(Editor editor, Color color) { - this.editor = editor; - this.color = color; - } + public ColorCommand(Editor editor, Color color) { + this.editor = editor; + this.color = color; + } - @Override - public String getName() { - return "Colorize: " + color.toString(); - } + @Override + public String getName() { + return "Colorize: " + color.toString(); + } - @Override - public void execute() { - for (Shape child : editor.getShapes().getSelected()) { - child.setColor(color); - } + @Override + public void execute() { + for (Shape child : editor.getShapes().getSelected()) { + child.setColor(color); } + } } diff --git a/src/refactoring_guru/memento/example/commands/Command.java b/src/refactoring_guru/memento/example/commands/Command.java index 56e0997..45cf0c2 100644 --- a/src/refactoring_guru/memento/example/commands/Command.java +++ b/src/refactoring_guru/memento/example/commands/Command.java @@ -1,6 +1,7 @@ package refactoring_guru.memento.example.commands; public interface Command { - String getName(); - void execute(); + String getName(); + + void execute(); } diff --git a/src/refactoring_guru/memento/example/commands/MoveCommand.java b/src/refactoring_guru/memento/example/commands/MoveCommand.java index f134c43..9daed95 100644 --- a/src/refactoring_guru/memento/example/commands/MoveCommand.java +++ b/src/refactoring_guru/memento/example/commands/MoveCommand.java @@ -4,45 +4,47 @@ import refactoring_guru.memento.example.shapes.Shape; public class MoveCommand implements Command { - private Editor editor; - private int startX, startY; - private int endX, endY; - - public MoveCommand(Editor editor) { - this.editor = editor; - } - - @Override - public String getName() { - return "Move by X:" + (endX - startX) + " Y:" + (endY - startY); - } - - public void start(int x, int y) { - startX = x; - startY = y; - for (Shape child : editor.getShapes().getSelected()) { - child.drag(); - } + private final Editor editor; + private int startX; + private int startY; + private int endX; + private int endY; + + public MoveCommand(Editor editor) { + this.editor = editor; + } + + @Override + public String getName() { + return "Move by X:" + (endX - startX) + " Y:" + (endY - startY); + } + + public void start(int x, int y) { + startX = x; + startY = y; + for (Shape child : editor.getShapes().getSelected()) { + child.drag(); } + } - public void move(int x, int y) { - for (Shape child : editor.getShapes().getSelected()) { - child.moveTo(x - startX, y - startY); - } + public void move(int x, int y) { + for (Shape child : editor.getShapes().getSelected()) { + child.moveTo(x - startX, y - startY); } + } - public void stop(int x, int y) { - endX = x; - endY = y; - for (Shape child : editor.getShapes().getSelected()) { - child.drop(); - } + public void stop(int x, int y) { + endX = x; + endY = y; + for (Shape child : editor.getShapes().getSelected()) { + child.drop(); } + } - @Override - public void execute() { - for (Shape child : editor.getShapes().getSelected()) { - child.moveBy(endX - startX, endY - startY); - } + @Override + public void execute() { + for (Shape child : editor.getShapes().getSelected()) { + child.moveBy(endX - startX, endY - startY); } + } } diff --git a/src/refactoring_guru/memento/example/editor/Editor.java b/src/refactoring_guru/memento/example/editor/Editor.java index 90f7dc6..78d7e9c 100644 --- a/src/refactoring_guru/memento/example/editor/Editor.java +++ b/src/refactoring_guru/memento/example/editor/Editor.java @@ -11,62 +11,58 @@ import java.util.Base64; public class Editor extends JComponent { - private Canvas canvas; - private CompoundShape allShapes = new CompoundShape(); - private History history; + private final Frame canvas; + private CompoundShape allShapes = new CompoundShape(); + private final transient History history; - public Editor() { - canvas = new Canvas(this); - history = new History(); - } + public Editor() { + canvas = new Frame(this); + history = new History(); + } - public void loadShapes(Shape... shapes) { - allShapes.clear(); - allShapes.add(shapes); - canvas.refresh(); - } + public void loadShapes(Shape... shapes) { + allShapes.clear(); + allShapes.add(shapes); + canvas.refresh(); + } - public CompoundShape getShapes() { - return allShapes; - } + public CompoundShape getShapes() { + return allShapes; + } - public void execute(Command c) { - history.push(c, new Memento(this)); - c.execute(); - } + public void execute(Command c) throws IOException { + history.push(c, new Memento(this)); + c.execute(); + } - public void undo() { - if (history.undo()) - canvas.repaint(); - } + public void undo() { + if (history.undo()) + canvas.repaint(); + } - public void redo() { - if (history.redo()) - canvas.repaint(); - } + public void redo() { + if (history.redo()) + canvas.repaint(); + } - public String backup() { - try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(this.allShapes); - oos.close(); - return Base64.getEncoder().encodeToString(baos.toByteArray()); - } catch (IOException e) { - return ""; - } - } + public String backup() throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); + objectOutputStream.writeObject(this.allShapes); + objectOutputStream.close(); + return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()); + } - public void restore(String state) { - try { - byte[] data = Base64.getDecoder().decode(state); - ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data)); - this.allShapes = (CompoundShape) ois.readObject(); - ois.close(); - } catch (ClassNotFoundException e) { - System.out.print("ClassNotFoundException occurred."); - } catch (IOException e) { - System.out.print("IOException occurred."); - } + public void restore(String state) { + try { + byte[] data = Base64.getDecoder().decode(state); + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data)); + this.allShapes = (CompoundShape) ois.readObject(); + ois.close(); + } catch (ClassNotFoundException e) { + System.out.print("ClassNotFoundException occurred."); + } catch (IOException e) { + System.out.print("IOException occurred."); } + } } diff --git a/src/refactoring_guru/memento/example/editor/Frame.java b/src/refactoring_guru/memento/example/editor/Frame.java new file mode 100644 index 0000000..c647ef5 --- /dev/null +++ b/src/refactoring_guru/memento/example/editor/Frame.java @@ -0,0 +1,188 @@ +package refactoring_guru.memento.example.editor; + +import refactoring_guru.memento.example.commands.ColorCommand; +import refactoring_guru.memento.example.commands.MoveCommand; +import refactoring_guru.memento.example.shapes.Shape; + +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; +import java.awt.event.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.Random; +import java.util.logging.Level; +import java.util.logging.Logger; + +class Frame extends Canvas implements FrameMemento { + private final Editor editor; + private JFrame jFrame; + private static final int PADDING = 10; + private final Random random = new Random(); + + Frame(Editor editor) { + this.editor = editor; + initFrame(); + attachListeners(); + mouseListeners(); + refresh(); + } + + private void initFrame() { + jFrame = new JFrame(); + jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + jFrame.setLocationRelativeTo(null); + + JPanel contentPanel = new JPanel(); + Border padding = BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING); + contentPanel.setBorder(padding); + contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS)); + jFrame.setContentPane(contentPanel); + + contentPanel.add(new JLabel("Select and drag to move."), BorderLayout.PAGE_END); + contentPanel.add(new JLabel("Right click to change color."), BorderLayout.PAGE_END); + contentPanel.add(new JLabel("Undo: Ctrl+Z, Redo: Ctrl+R"), BorderLayout.PAGE_END); + contentPanel.add(this); + jFrame.setVisible(true); + contentPanel.setBackground(Color.LIGHT_GRAY); + } + + private void attachListeners() { + addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) { + switch (e.getKeyCode()) { + case KeyEvent.VK_Z -> editor.undo(); + case KeyEvent.VK_R -> editor.redo(); + default -> Logger.getLogger(Frame.class.getName()) + .log(Level.WARNING, () -> "Unknown component: "); + + } + } + } + }); + } + + private void mouseListeners() { + MouseAdapter mouseAdapter = new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (e.getButton() != MouseEvent.BUTTON3) { + return; + } + Shape target = editor.getShapes().getChildAt(e.getX(), e.getY()); + if (target != null) { + try { + editor.execute(new ColorCommand(editor, new Color((random.nextInt() * 0x1000000)))); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + repaint(); + } + } + }; + addMouseListener(mouseAdapter); + + MouseAdapter selector = new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (e.getButton() != MouseEvent.BUTTON1) { + throw new IllegalArgumentException("if the button is not working "); + } + + Shape target = editor.getShapes().getChildAt(e.getX(), e.getY()); + boolean ctrl = (e.getModifiersEx() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK; + + if (target == null) { + if (!ctrl) { + editor.getShapes().unSelect(); + } + } else { + if (ctrl) { + if (target.isSelected()) { + target.unSelect(); + } else { + target.select(); + } + } else { + if (!target.isSelected()) { + editor.getShapes().unSelect(); + } + target.select(); + } + } + repaint(); + } + }; + addMouseListener(selector); + + + MouseAdapter mouseAdapter1 = new MouseAdapter() { + MoveCommand moveCommand; + + @Override + public void mouseDragged(MouseEvent e) { + if ((e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != InputEvent.BUTTON1_DOWN_MASK) { + return; + } + if (moveCommand == null) { + moveCommand = new MoveCommand(editor); + moveCommand.start(e.getX(), e.getY()); + } + moveCommand.move(e.getX(), e.getY()); + repaint(); + } + + @Override + public void mouseReleased(MouseEvent e) { + if (e.getButton() != MouseEvent.BUTTON1 || moveCommand == null) { + throw new IllegalArgumentException("Cannot execute"); + } + moveCommand.stop(e.getX(), e.getY()); + try { + editor.execute(moveCommand); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + this.moveCommand = null; + repaint(); + } + }; + addMouseListener(mouseAdapter1); + addMouseMotionListener(mouseAdapter1); + } + + @Override + public int getWidth() { + return editor.getShapes().getX() + editor.getShapes().getWidth() + PADDING; + } + + @Override + public int getHeight() { + return editor.getShapes().getY() + editor.getShapes().getHeight() + PADDING; + } + + @Override + public void refresh() { + this.setSize(getWidth(), getHeight()); + jFrame.pack(); + } + + @Override + public void update(Graphics g) { + paint(g); + } + + @Override + public void paint(Graphics graphics) { + BufferedImage buffer = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB); + Graphics2D ig2 = buffer.createGraphics(); + ig2.setBackground(Color.WHITE); + ig2.clearRect(0, 0, this.getWidth(), this.getHeight()); + + editor.getShapes().paint(buffer.getGraphics()); + + graphics.drawImage(buffer, 0, 0, null); + } +} diff --git a/src/refactoring_guru/memento/example/editor/FrameMemento.java b/src/refactoring_guru/memento/example/editor/FrameMemento.java new file mode 100644 index 0000000..340f966 --- /dev/null +++ b/src/refactoring_guru/memento/example/editor/FrameMemento.java @@ -0,0 +1,5 @@ +package refactoring_guru.memento.example.editor; + +public interface FrameMemento { + void refresh(); +} diff --git a/src/refactoring_guru/memento/example/history/History.java b/src/refactoring_guru/memento/example/history/History.java index 90d6cbd..a0fe4b3 100644 --- a/src/refactoring_guru/memento/example/history/History.java +++ b/src/refactoring_guru/memento/example/history/History.java @@ -6,68 +6,69 @@ import java.util.List; public class History { - private List history = new ArrayList(); - private int virtualSize = 0; + private List pairs = new ArrayList<>(); + private int virtualSize = 0; - private class Pair { - Command command; - Memento memento; - Pair(Command c, Memento m) { - command = c; - memento = m; - } + public void push(Command c, Memento m) { + if (virtualSize != pairs.size() && virtualSize > 0) { + pairs = pairs.subList(0, virtualSize - 1); + } + pairs.add(new Pair(c, m)); + virtualSize = pairs.size(); + } - private Command getCommand() { - return command; - } + public boolean undo() { + Pair pair = getUndo(); + if (pair == null) { + return false; + } + System.out.println("Undoing: " + pair.getCommand().getName()); + pair.getMemento().restore(); + return true; + } - private Memento getMemento() { - return memento; - } + public boolean redo() { + Pair pair = getRedo(); + if (pair == null) { + return false; } + System.out.println("Redoing: " + pair.getCommand().getName()); + pair.getMemento().restore(); + pair.getCommand().execute(); + return true; + } - public void push(Command c, Memento m) { - if (virtualSize != history.size() && virtualSize > 0) { - history = history.subList(0, virtualSize - 1); - } - history.add(new Pair(c, m)); - virtualSize = history.size(); + private Pair getUndo() { + if (virtualSize == 0) { + return null; } + virtualSize = Math.max(0, virtualSize - 1); + return pairs.get(virtualSize); + } - public boolean undo() { - Pair pair = getUndo(); - if (pair == null) { - return false; - } - System.out.println("Undoing: " + pair.getCommand().getName()); - pair.getMemento().restore(); - return true; + private Pair getRedo() { + if (virtualSize == pairs.size()) { + return null; } + virtualSize = Math.min(pairs.size(), virtualSize + 1); + return pairs.get(virtualSize - 1); + } + + private static class Pair { + Command command; + Memento memento; - public boolean redo() { - Pair pair = getRedo(); - if (pair == null) { - return false; - } - System.out.println("Redoing: " + pair.getCommand().getName()); - pair.getMemento().restore(); - pair.getCommand().execute(); - return true; + Pair(Command c, Memento m) { + command = c; + memento = m; } - private Pair getUndo() { - if (virtualSize == 0) { - return null; - } - virtualSize = Math.max(0, virtualSize - 1); - return history.get(virtualSize); + private Command getCommand() { + return command; } - private Pair getRedo() { - if (virtualSize == history.size()) { - return null; - } - virtualSize = Math.min(history.size(), virtualSize + 1); - return history.get(virtualSize - 1); + private Memento getMemento() { + return memento; } + } } diff --git a/src/refactoring_guru/memento/example/history/Memento.java b/src/refactoring_guru/memento/example/history/Memento.java index 6800638..dc5e6cd 100644 --- a/src/refactoring_guru/memento/example/history/Memento.java +++ b/src/refactoring_guru/memento/example/history/Memento.java @@ -2,16 +2,18 @@ import refactoring_guru.memento.example.editor.Editor; +import java.io.IOException; + public class Memento { - private String backup; - private Editor editor; + private final String backup; + private final Editor editor; - public Memento(Editor editor) { - this.editor = editor; - this.backup = editor.backup(); - } + public Memento(Editor editor) throws IOException { + this.editor = editor; + this.backup = editor.backup(); + } - public void restore() { - editor.restore(backup); - } + public void restore() { + editor.restore(backup); + } } diff --git a/src/refactoring_guru/memento/example/shapes/BaseShape.java b/src/refactoring_guru/memento/example/shapes/BaseShape.java index 3433329..fd08d1a 100644 --- a/src/refactoring_guru/memento/example/shapes/BaseShape.java +++ b/src/refactoring_guru/memento/example/shapes/BaseShape.java @@ -3,118 +3,117 @@ import java.awt.*; public abstract class BaseShape implements Shape { - int x, y; - private int dx = 0, dy = 0; - private Color color; - private boolean selected = false; - - BaseShape(int x, int y, Color color) { - this.x = x; - this.y = y; - this.color = color; - } - - @Override - public int getX() { - return x; - } - - @Override - public int getY() { - return y; - } - - @Override - public int getWidth() { - return 0; - } - - @Override - public int getHeight() { - return 0; - } - - @Override - public void drag() { - dx = x; - dy = y; - } - - @Override - public void moveTo(int x, int y) { - this.x = dx + x; - this.y = dy + y; - } - - @Override - public void moveBy(int x, int y) { - this.x += x; - this.y += y; - } - - @Override - public void drop() { - this.x = dx; - this.y = dy; - } - - @Override - public boolean isInsideBounds(int x, int y) { - return x > getX() && x < (getX() + getWidth()) && - y > getY() && y < (getY() + getHeight()); - } - - @Override - public Color getColor() { - return color; - } - - @Override - public void setColor(Color color) { - this.color = color; - } - - @Override - public void select() { - selected = true; - } - - @Override - public void unSelect() { - selected = false; - } - - @Override - public boolean isSelected() { - return selected; - } - - void enableSelectionStyle(Graphics graphics) { - graphics.setColor(Color.LIGHT_GRAY); - - Graphics2D g2 = (Graphics2D) graphics; - float[] dash1 = {2.0f}; - g2.setStroke(new BasicStroke(1.0f, - BasicStroke.CAP_BUTT, - BasicStroke.JOIN_MITER, - 2.0f, dash1, 0.0f)); - } - - void disableSelectionStyle(Graphics graphics) { - graphics.setColor(color); - Graphics2D g2 = (Graphics2D) graphics; - g2.setStroke(new BasicStroke()); - } - - @Override - public void paint(Graphics graphics) { - if (isSelected()) { - enableSelectionStyle(graphics); - } - else { - disableSelectionStyle(graphics); - } - - // ... - } + int x; + int y; + private int dx = 0; + private int dy = 0; + private Color color; + private boolean selected = false; + + BaseShape(int x, int y, Color color) { + this.x = x; + this.y = y; + this.color = color; + } + + @Override + public int getX() { + return x; + } + + @Override + public int getY() { + return y; + } + + @Override + public int getWidth() { + return 0; + } + + @Override + public int getHeight() { + return 0; + } + + @Override + public void drag() { + dx = x; + dy = y; + } + + @Override + public void moveTo(int x, int y) { + this.x = dx + x; + this.y = dy + y; + } + + @Override + public void moveBy(int x, int y) { + this.x += x; + this.y += y; + } + + @Override + public void drop() { + this.x = dx; + this.y = dy; + } + + @Override + public boolean isInsideBounds(int x, int y) { + return x > getX() && x < (getX() + getWidth()) && + y > getY() && y < (getY() + getHeight()); + } + + @Override + public Color getColor() { + return color; + } + + @Override + public void setColor(Color color) { + this.color = color; + } + + @Override + public void select() { + selected = true; + } + + @Override + public void unSelect() { + selected = false; + } + + @Override + public boolean isSelected() { + return selected; + } + + void enableSelectionStyle(Graphics graphics) { + graphics.setColor(Color.LIGHT_GRAY); + + Graphics2D g2 = (Graphics2D) graphics; + float[] dash1 = {2.0f}; + g2.setStroke(new BasicStroke(1.0f, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, + 2.0f, dash1, 0.0f)); + } + + void disableSelectionStyle(Graphics graphics) { + graphics.setColor(color); + Graphics2D g2 = (Graphics2D) graphics; + g2.setStroke(new BasicStroke()); + } + + @Override + public void paint(Graphics graphics) { + if (isSelected()) { + enableSelectionStyle(graphics); + } else { + disableSelectionStyle(graphics); + } + } } \ No newline at end of file diff --git a/src/refactoring_guru/memento/example/shapes/Circle.java b/src/refactoring_guru/memento/example/shapes/Circle.java index 6400a50..e15b719 100644 --- a/src/refactoring_guru/memento/example/shapes/Circle.java +++ b/src/refactoring_guru/memento/example/shapes/Circle.java @@ -3,26 +3,26 @@ import java.awt.*; public class Circle extends BaseShape { - private int radius; + private final int radius; - public Circle(int x, int y, int radius, Color color) { - super(x, y, color); - this.radius = radius; - } + public Circle(int x, int y, int radius, Color color) { + super(x, y, color); + this.radius = radius; + } - @Override - public int getWidth() { - return radius * 2; - } + @Override + public int getWidth() { + return radius * 2; + } - @Override - public int getHeight() { - return radius * 2; - } + @Override + public int getHeight() { + return radius * 2; + } - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.drawOval(x, y, getWidth() - 1, getHeight() - 1); - } + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.drawOval(x, y, getWidth() - 1, getHeight() - 1); + } } diff --git a/src/refactoring_guru/memento/example/shapes/CompoundShape.java b/src/refactoring_guru/memento/example/shapes/CompoundShape.java index ba94a4b..5236a02 100644 --- a/src/refactoring_guru/memento/example/shapes/CompoundShape.java +++ b/src/refactoring_guru/memento/example/shapes/CompoundShape.java @@ -6,181 +6,183 @@ import java.util.List; public class CompoundShape extends BaseShape { - private List children = new ArrayList<>(); + private final List children = new ArrayList<>(); + + public CompoundShape(Shape... components) { + super(0, 0, Color.BLACK); + add(components); + } + + public void add(Shape component) { + children.add(component); + } + + public void add(Shape... components) { + children.addAll(Arrays.asList(components)); + } + + public void remove(Shape child) { + children.remove(child); + } + + public void remove(Shape... components) { + children.removeAll(Arrays.asList(components)); + } + + public void clear() { + children.clear(); + } + + @Override + public int getX() { + checkNotEmpty(children); + int x = children.get(0).getX(); + for (Shape child : children) { + if (child.getX() < x) { + x = child.getX(); + } + } + return x; + } + + @Override + public int getY() { + checkNotEmpty(children); + int y = children.get(0).getY(); + for (Shape child : children) { + if (child.getY() < y) { + y = child.getY(); + } + } + return y; + } + + @Override + public int getWidth() { + int maxWidth = 0; + int x = getX(); + for (Shape child : children) { + int childsRelativeX = child.getX() - x; + int childWidth = childsRelativeX + child.getWidth(); + if (childWidth > maxWidth) { + maxWidth = childWidth; + } + } + return maxWidth; + } + + @Override + public int getHeight() { + int maxHeight = 0; + int y = getY(); + for (Shape child : children) { + int childsRelativeY = child.getY() - y; + int childHeight = childsRelativeY + child.getHeight(); + if (childHeight > maxHeight) { + maxHeight = childHeight; + } + } + return maxHeight; + } + + @Override + public void drag() { + for (Shape child : children) { + child.drag(); + } + } + + @Override + public void drop() { + for (Shape child : children) { + child.drop(); + } + } + + @Override + public void moveTo(int x, int y) { + for (Shape child : children) { + child.moveTo(x, y); + } + } + + @Override + public void moveBy(int x, int y) { + for (Shape child : children) { + child.moveBy(x, y); + } + } + + @Override + public boolean isInsideBounds(int x, int y) { + for (Shape child : children) { + if (child.isInsideBounds(x, y)) { + return true; + } + } + return false; + } + + @Override + public void setColor(Color color) { + super.setColor(color); + for (Shape child : children) { + child.setColor(color); + } + } + + @Override + public void unSelect() { + super.unSelect(); + for (Shape child : children) { + child.unSelect(); + } + } + + public Shape getChildAt(int x, int y) { + for (Shape child : children) { + if (child.isInsideBounds(x, y)) { + return child; + } + } + return null; + } + + public boolean selectChildAt(int x, int y) { + Shape child = getChildAt(x, y); + if (child != null) { + child.select(); + return true; + } + return false; + } + + public List getSelected() { + List selected = new ArrayList<>(); + for (Shape child : children) { + if (child.isSelected()) { + selected.add(child); + } + } + return selected; + } + + @Override + public void paint(Graphics graphics) { + if (isSelected()) { + enableSelectionStyle(graphics); + graphics.drawRect(getX() - 1, getY() - 1, getWidth() + 1, getHeight() + 1); + disableSelectionStyle(graphics); + } + + for (Shape child : children) { + child.paint(graphics); + } + } - public CompoundShape(Shape... components) { - super(0, 0, Color.BLACK); - add(components); - } - - public void add(Shape component) { - children.add(component); - } - - public void add(Shape... components) { - children.addAll(Arrays.asList(components)); - } - - public void remove(Shape child) { - children.remove(child); - } - - public void remove(Shape... components) { - children.removeAll(Arrays.asList(components)); - } - - public void clear() { - children.clear(); - } - - @Override - public int getX() { - if (children.size() == 0) { - return 0; - } - int x = children.get(0).getX(); - for (Shape child : children) { - if (child.getX() < x) { - x = child.getX(); - } - } - return x; - } - - @Override - public int getY() { - if (children.size() == 0) { - return 0; - } - int y = children.get(0).getY(); - for (Shape child : children) { - if (child.getY() < y) { - y = child.getY(); - } - } - return y; - } - - @Override - public int getWidth() { - int maxWidth = 0; - int x = getX(); - for (Shape child : children) { - int childsRelativeX = child.getX() - x; - int childWidth = childsRelativeX + child.getWidth(); - if (childWidth > maxWidth) { - maxWidth = childWidth; - } - } - return maxWidth; - } - - @Override - public int getHeight() { - int maxHeight = 0; - int y = getY(); - for (Shape child : children) { - int childsRelativeY = child.getY() - y; - int childHeight = childsRelativeY + child.getHeight(); - if (childHeight > maxHeight) { - maxHeight = childHeight; - } - } - return maxHeight; - } - - @Override - public void drag() { - for (Shape child : children) { - child.drag(); - } - } - - @Override - public void drop() { - for (Shape child : children) { - child.drop(); - } - } - - @Override - public void moveTo(int x, int y) { - for (Shape child : children) { - child.moveTo(x, y); - } - } - - @Override - public void moveBy(int x, int y) { - for (Shape child : children) { - child.moveBy(x, y); - } - } - - @Override - public boolean isInsideBounds(int x, int y) { - for (Shape child : children) { - if (child.isInsideBounds(x, y)) { - return true; - } - } - return false; - } - - @Override - public void setColor(Color color) { - super.setColor(color); - for (Shape child : children) { - child.setColor(color); - } - } - - @Override - public void unSelect() { - super.unSelect(); - for (Shape child : children) { - child.unSelect(); - } - } - - public Shape getChildAt(int x, int y) { - for (Shape child : children) { - if (child.isInsideBounds(x, y)) { - return child; - } - } - return null; - } - - public boolean selectChildAt(int x, int y) { - Shape child = getChildAt(x,y); - if (child != null) { - child.select(); - return true; - } - return false; - } - - public List getSelected() { - List selected = new ArrayList<>(); - for (Shape child : children) { - if (child.isSelected()) { - selected.add(child); - } - } - return selected; - } - - @Override - public void paint(Graphics graphics) { - if (isSelected()) { - enableSelectionStyle(graphics); - graphics.drawRect(getX() - 1, getY() - 1, getWidth() + 1, getHeight() + 1); - disableSelectionStyle(graphics); - } - - for (Shape child : children) { - child.paint(graphics); - } - } + private void checkNotEmpty(List children) { + if (children.isEmpty()) { + throw new IllegalArgumentException("The List is empty "); + } + } } diff --git a/src/refactoring_guru/memento/example/shapes/Dot.java b/src/refactoring_guru/memento/example/shapes/Dot.java index a8562e6..8c8cdf9 100644 --- a/src/refactoring_guru/memento/example/shapes/Dot.java +++ b/src/refactoring_guru/memento/example/shapes/Dot.java @@ -3,25 +3,26 @@ import java.awt.*; public class Dot extends BaseShape { - private final int DOT_SIZE = 3; + private final int DOT_WIDTH = 3; + private final int DOT_HEIGHT = 3; - public Dot(int x, int y, Color color) { - super(x, y, color); - } + public Dot(int x, int y, Color color) { + super(x, y, color); + } - @Override - public int getWidth() { - return DOT_SIZE; - } + @Override + public int getWidth() { + return DOT_WIDTH; + } - @Override - public int getHeight() { - return DOT_SIZE; - } + @Override + public int getHeight() { + return DOT_HEIGHT; + } - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.fillRect(x - 1, y - 1, getWidth(), getHeight()); - } + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.fillRect(x - 1, y - 1, getWidth(), getHeight()); + } } diff --git a/src/refactoring_guru/memento/example/shapes/Rectangle.java b/src/refactoring_guru/memento/example/shapes/Rectangle.java index 76aa5e8..e53a2e3 100644 --- a/src/refactoring_guru/memento/example/shapes/Rectangle.java +++ b/src/refactoring_guru/memento/example/shapes/Rectangle.java @@ -3,28 +3,28 @@ import java.awt.*; public class Rectangle extends BaseShape { - private int width; - private int height; + private final int width; + private final int height; - public Rectangle(int x, int y, int width, int height, Color color) { - super(x, y, color); - this.width = width; - this.height = height; - } + public Rectangle(int x, int y, int width, int height, Color color) { + super(x, y, color); + this.width = width; + this.height = height; + } - @Override - public int getWidth() { - return width; - } + @Override + public int getWidth() { + return width; + } - @Override - public int getHeight() { - return height; - } + @Override + public int getHeight() { + return height; + } - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.drawRect(x, y, getWidth() - 1, getHeight() - 1); - } + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.drawRect(x, y, getWidth() - 1, getHeight() - 1); + } } diff --git a/src/refactoring_guru/memento/example/shapes/Shape.java b/src/refactoring_guru/memento/example/shapes/Shape.java index 90d078d..71b4d9a 100644 --- a/src/refactoring_guru/memento/example/shapes/Shape.java +++ b/src/refactoring_guru/memento/example/shapes/Shape.java @@ -4,20 +4,34 @@ import java.io.Serializable; public interface Shape extends Serializable { - int getX(); - int getY(); - int getWidth(); - int getHeight(); - void drag(); - void drop(); - void moveTo(int x, int y); - void moveBy(int x, int y); - boolean isInsideBounds(int x, int y); - Color getColor(); - void setColor(Color color); - void select(); - void unSelect(); - boolean isSelected(); - void paint(Graphics graphics); + int getX(); + + int getY(); + + int getWidth(); + + int getHeight(); + + void drag(); + + void drop(); + + void moveTo(int x, int y); + + void moveBy(int x, int y); + + boolean isInsideBounds(int x, int y); + + Color getColor(); + + void setColor(Color color); + + void select(); + + void unSelect(); + + boolean isSelected(); + + void paint(Graphics graphics); } From 4d5549ffc9ce3297a618123ee331d25e66f72b70 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 15:49:53 +0300 Subject: [PATCH 29/45] some changes in Observer package --- .../observer/example/Demo.java | 19 ++++------ .../observer/example/editor/Editor.java | 30 ++++++++-------- .../listeners/EmailNotificationListener.java | 21 ++++++----- .../example/listeners/EventListener.java | 2 +- .../example/listeners/LogOpenListener.java | 21 ++++++----- .../example/publisher/EventManager.java | 36 +++++++++---------- 6 files changed, 67 insertions(+), 62 deletions(-) diff --git a/src/refactoring_guru/observer/example/Demo.java b/src/refactoring_guru/observer/example/Demo.java index 7d399c0..6515a09 100644 --- a/src/refactoring_guru/observer/example/Demo.java +++ b/src/refactoring_guru/observer/example/Demo.java @@ -5,16 +5,11 @@ import refactoring_guru.observer.example.listeners.LogOpenListener; public class Demo { - public static void main(String[] args) { - Editor editor = new Editor(); - editor.events.subscribe("open", new LogOpenListener("/path/to/log/file.txt")); - editor.events.subscribe("save", new EmailNotificationListener("admin@example.com")); - - try { - editor.openFile("test.txt"); - editor.saveFile(); - } catch (Exception e) { - e.printStackTrace(); - } - } + public static void main(String[] args) throws Exception { + Editor editor = new Editor(); + editor.events.subscribe("open", new LogOpenListener("/path/to/log/file.txt")); + editor.events.subscribe("save", new EmailNotificationListener("admin@example.com")); + editor.openFile("test.txt"); + editor.saveFile(); + } } diff --git a/src/refactoring_guru/observer/example/editor/Editor.java b/src/refactoring_guru/observer/example/editor/Editor.java index f373045..20117fc 100644 --- a/src/refactoring_guru/observer/example/editor/Editor.java +++ b/src/refactoring_guru/observer/example/editor/Editor.java @@ -5,23 +5,23 @@ import java.io.File; public class Editor { - public EventManager events; - private File file; + public EventManager events; + private File file; - public Editor() { - this.events = new EventManager("open", "save"); - } + public Editor() { + this.events = new EventManager("open", "save"); + } - public void openFile(String filePath) { - this.file = new File(filePath); - events.notify("open", file); - } + public void openFile(String filePath) { + this.file = new File(filePath); + events.notify("open", file); + } - public void saveFile() throws Exception { - if (this.file != null) { - events.notify("save", file); - } else { - throw new Exception("Please open a file first."); - } + public void saveFile() throws Exception { + if (this.file != null) { + events.notify("save", file); + } else { + throw new Exception("Please open a file first."); } + } } diff --git a/src/refactoring_guru/observer/example/listeners/EmailNotificationListener.java b/src/refactoring_guru/observer/example/listeners/EmailNotificationListener.java index efd3f9d..6daac9f 100644 --- a/src/refactoring_guru/observer/example/listeners/EmailNotificationListener.java +++ b/src/refactoring_guru/observer/example/listeners/EmailNotificationListener.java @@ -3,14 +3,19 @@ import java.io.File; public class EmailNotificationListener implements EventListener { - private String email; + private final String email; - public EmailNotificationListener(String email) { - this.email = email; - } + public EmailNotificationListener(String email) { + this.email = email; + } - @Override - public void update(String eventType, File file) { - System.out.println("Email to " + email + ": Someone has performed " + eventType + " operation with the following file: " + file.getName()); - } + @Override + public void update(String eventType, File file) { + System.out.println("Email to " + + email + + "Someone has performed " + + eventType + + " operation with the following file: " + + file.getClass().getName()); + } } diff --git a/src/refactoring_guru/observer/example/listeners/EventListener.java b/src/refactoring_guru/observer/example/listeners/EventListener.java index a996b3a..4ff0d0b 100644 --- a/src/refactoring_guru/observer/example/listeners/EventListener.java +++ b/src/refactoring_guru/observer/example/listeners/EventListener.java @@ -3,5 +3,5 @@ import java.io.File; public interface EventListener { - void update(String eventType, File file); + void update(String eventType, File file); } diff --git a/src/refactoring_guru/observer/example/listeners/LogOpenListener.java b/src/refactoring_guru/observer/example/listeners/LogOpenListener.java index 180470b..09f4388 100644 --- a/src/refactoring_guru/observer/example/listeners/LogOpenListener.java +++ b/src/refactoring_guru/observer/example/listeners/LogOpenListener.java @@ -3,14 +3,19 @@ import java.io.File; public class LogOpenListener implements EventListener { - private File log; + private final File log; - public LogOpenListener(String fileName) { - this.log = new File(fileName); - } + public LogOpenListener(String fileName) { + this.log = new File(fileName); + } - @Override - public void update(String eventType, File file) { - System.out.println("Save to log " + log + ": Someone has performed " + eventType + " operation with the following file: " + file.getName()); - } + @Override + public void update(String eventType, File file) { + System.out.println("Save to log " + + log + + "Someone has performed " + + eventType + + " operation with the following file: " + + file.getClass().getName()); + } } diff --git a/src/refactoring_guru/observer/example/publisher/EventManager.java b/src/refactoring_guru/observer/example/publisher/EventManager.java index 2918ba1..5116817 100644 --- a/src/refactoring_guru/observer/example/publisher/EventManager.java +++ b/src/refactoring_guru/observer/example/publisher/EventManager.java @@ -9,28 +9,28 @@ import java.util.Map; public class EventManager { - Map> listeners = new HashMap<>(); + Map> listeners = new HashMap<>(); - public EventManager(String... operations) { - for (String operation : operations) { - this.listeners.put(operation, new ArrayList<>()); - } + public EventManager(String... operations) { + for (String operation : operations) { + this.listeners.put(operation, new ArrayList<>()); } + } - public void subscribe(String eventType, EventListener listener) { - List users = listeners.get(eventType); - users.add(listener); - } + public void subscribe(String eventType, EventListener listener) { + List users = listeners.get(eventType); + users.add(listener); + } - public void unsubscribe(String eventType, EventListener listener) { - List users = listeners.get(eventType); - users.remove(listener); - } + public void unsubscribe(String eventType, EventListener listener) { + List users = listeners.get(eventType); + users.remove(listener); + } - public void notify(String eventType, File file) { - List users = listeners.get(eventType); - for (EventListener listener : users) { - listener.update(eventType, file); - } + public void notify(String eventType, File file) { + List users = listeners.get(eventType); + for (EventListener listener : users) { + listener.update(eventType, file); } + } } From bdde169e4c773b1dff2ea6b660fce793073b540d Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 15:50:33 +0300 Subject: [PATCH 30/45] some changes in prototype package --- .../prototype/caching/Demo.java | 40 ++++++------- .../caching/cache/BundledShapeCache.java | 56 +++++++++---------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/refactoring_guru/prototype/caching/Demo.java b/src/refactoring_guru/prototype/caching/Demo.java index 5cad2ed..557b216 100644 --- a/src/refactoring_guru/prototype/caching/Demo.java +++ b/src/refactoring_guru/prototype/caching/Demo.java @@ -4,28 +4,28 @@ import refactoring_guru.prototype.example.shapes.Shape; public class Demo { - public static void main(String[] args) { - BundledShapeCache cache = new BundledShapeCache(); + public static void main(String[] args) { + BundledShapeCache cache = new BundledShapeCache(); - Shape shape1 = cache.get("Big green circle"); - Shape shape2 = cache.get("Medium blue rectangle"); - Shape shape3 = cache.get("Medium blue rectangle"); + Shape shape1 = cache.get("Big green circle"); + Shape shape2 = cache.get("Medium blue rectangle"); + Shape shape3 = cache.get("Medium blue rectangle"); - if (shape1 != shape2 && !shape1.equals(shape2)) { - System.out.println("Big green circle != Medium blue rectangle (yay!)"); - } else { - System.out.println("Big green circle == Medium blue rectangle (booo!)"); - } + if (shape1 != shape2 && !shape1.equals(shape2)) { + System.out.println("Big green circle != Medium blue rectangle (yay!)"); + } else { + System.out.println("Big green circle == Medium blue rectangle (booo!)"); + } - if (shape2 != shape3) { - System.out.println("Medium blue rectangles are two different objects (yay!)"); - if (shape2.equals(shape3)) { - System.out.println("And they are identical (yay!)"); - } else { - System.out.println("But they are not identical (booo!)"); - } - } else { - System.out.println("Rectangle objects are the same (booo!)"); - } + if (shape2 != shape3) { + System.out.println("Medium blue rectangles are two different objects (yay!)"); + if (shape2.equals(shape3)) { + System.out.println("And they are identical (yay!)"); + } else { + System.out.println("But they are not identical (booo!)"); + } + } else { + System.out.println("Rectangle objects are the same (booo!)"); } + } } \ No newline at end of file diff --git a/src/refactoring_guru/prototype/caching/cache/BundledShapeCache.java b/src/refactoring_guru/prototype/caching/cache/BundledShapeCache.java index cd67746..3367423 100644 --- a/src/refactoring_guru/prototype/caching/cache/BundledShapeCache.java +++ b/src/refactoring_guru/prototype/caching/cache/BundledShapeCache.java @@ -8,32 +8,32 @@ import java.util.Map; public class BundledShapeCache { - private Map cache = new HashMap<>(); - - public BundledShapeCache() { - Circle circle = new Circle(); - circle.x = 5; - circle.y = 7; - circle.radius = 45; - circle.color = "Green"; - - Rectangle rectangle = new Rectangle(); - rectangle.x = 6; - rectangle.y = 9; - rectangle.width = 8; - rectangle.height = 10; - rectangle.color = "Blue"; - - cache.put("Big green circle", circle); - cache.put("Medium blue rectangle", rectangle); - } - - public Shape put(String key, Shape shape) { - cache.put(key, shape); - return shape; - } - - public Shape get(String key) { - return cache.get(key).clone(); - } + private final Map cache = new HashMap<>(); + + public BundledShapeCache() { + Circle circle = new Circle(); + circle.x = 5; + circle.y = 7; + circle.radius = 45; + circle.color = "Green"; + + Rectangle rectangle = new Rectangle(); + rectangle.x = 6; + rectangle.y = 9; + rectangle.width = 8; + rectangle.height = 10; + rectangle.color = "Blue"; + + cache.put("Big green circle", circle); + cache.put("Medium blue rectangle", rectangle); + } + + public Shape put(String key, Shape shape) { + cache.put(key, shape); + return shape; + } + + public Shape get(String key) { + return cache.get(key).clone(); + } } From 730bc1d79df00a9af4a60293975535c7d55e7842 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 15:54:49 +0300 Subject: [PATCH 31/45] some changes in prototype package --- .../prototype/example/Demo.java | 74 +++++++++---------- .../prototype/example/shapes/Circle.java | 39 +++++----- .../prototype/example/shapes/Rectangle.java | 45 ++++++----- .../prototype/example/shapes/Shape.java | 41 +++++----- 4 files changed, 108 insertions(+), 91 deletions(-) diff --git a/src/refactoring_guru/prototype/example/Demo.java b/src/refactoring_guru/prototype/example/Demo.java index c02a2cd..29c9a25 100644 --- a/src/refactoring_guru/prototype/example/Demo.java +++ b/src/refactoring_guru/prototype/example/Demo.java @@ -8,45 +8,45 @@ import java.util.List; public class Demo { - public static void main(String[] args) { - List shapes = new ArrayList<>(); - List shapesCopy = new ArrayList<>(); - - Circle circle = new Circle(); - circle.x = 10; - circle.y = 20; - circle.radius = 15; - circle.color = "red"; - shapes.add(circle); - - Circle anotherCircle = (Circle) circle.clone(); - shapes.add(anotherCircle); - - Rectangle rectangle = new Rectangle(); - rectangle.width = 10; - rectangle.height = 20; - rectangle.color = "blue"; - shapes.add(rectangle); - - cloneAndCompare(shapes, shapesCopy); + public static void main(String[] args) { + List shapes = new ArrayList<>(); + List shapeArrayList = new ArrayList<>(); + + Circle circle = new Circle(); + circle.x = 10; + circle.y = 20; + circle.radius = 15; + circle.color = "red"; + shapes.add(circle); + + Circle anotherCircle = (Circle) circle.clone(); + shapes.add(anotherCircle); + + Rectangle rectangle = new Rectangle(); + rectangle.width = 10; + rectangle.height = 20; + rectangle.color = "blue"; + shapes.add(rectangle); + + cloneAndCompare(shapes, shapeArrayList); + } + + private static void cloneAndCompare(List shapes, List shapeList) { + for (Shape shape : shapes) { + shapeList.add(shape.clone()); } - private static void cloneAndCompare(List shapes, List shapesCopy) { - for (Shape shape : shapes) { - shapesCopy.add(shape.clone()); - } - - for (int i = 0; i < shapes.size(); i++) { - if (shapes.get(i) != shapesCopy.get(i)) { - System.out.println(i + ": Shapes are different objects (yay!)"); - if (shapes.get(i).equals(shapesCopy.get(i))) { - System.out.println(i + ": And they are identical (yay!)"); - } else { - System.out.println(i + ": But they are not identical (booo!)"); - } - } else { - System.out.println(i + ": Shape objects are the same (booo!)"); - } + for (int i = 0; i < shapes.size(); i++) { + if (shapes.get(i) != shapeList.get(i)) { + System.out.println(i + "Shapes are different objects (yay!)"); + if (shapes.get(i).equals(shapeList.get(i))) { + System.out.println(i + "And they are identical (yay!)"); + } else { + System.out.println(i + "But they are not identical (booo!)"); } + } else { + System.out.println(i + "Shape objects are the same (booo!)"); + } } + } } diff --git a/src/refactoring_guru/prototype/example/shapes/Circle.java b/src/refactoring_guru/prototype/example/shapes/Circle.java index 074e178..32aca7b 100644 --- a/src/refactoring_guru/prototype/example/shapes/Circle.java +++ b/src/refactoring_guru/prototype/example/shapes/Circle.java @@ -1,27 +1,32 @@ package refactoring_guru.prototype.example.shapes; public class Circle extends Shape { - public int radius; + public int radius; - public Circle() { - } + public Circle() { + } - public Circle(Circle target) { - super(target); - if (target != null) { - this.radius = target.radius; - } + public Circle(Circle target) { + super(target); + if (target != null) { + this.radius = target.radius; } + } - @Override - public Shape clone() { - return new Circle(this); - } + @Override + public Shape clone() { + return new Circle(this); + } - @Override - public boolean equals(Object object2) { - if (!(object2 instanceof Circle) || !super.equals(object2)) return false; - Circle shape2 = (Circle) object2; - return shape2.radius == radius; + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; } + Shape shape = (Shape) object; + return radius == shape.x && radius == shape.y; + } } diff --git a/src/refactoring_guru/prototype/example/shapes/Rectangle.java b/src/refactoring_guru/prototype/example/shapes/Rectangle.java index 4adbf0e..072b4fc 100644 --- a/src/refactoring_guru/prototype/example/shapes/Rectangle.java +++ b/src/refactoring_guru/prototype/example/shapes/Rectangle.java @@ -1,29 +1,36 @@ package refactoring_guru.prototype.example.shapes; public class Rectangle extends Shape { - public int width; - public int height; + public int width; + public int height; - public Rectangle() { - } + public Rectangle() { + } - public Rectangle(Rectangle target) { - super(target); - if (target != null) { - this.width = target.width; - this.height = target.height; - } + public Rectangle(Rectangle target) { + super(target); + if (target != null) { + this.width = target.width; + this.height = target.height; } + } - @Override - public Shape clone() { - return new Rectangle(this); - } + @Override + public Shape clone() { + return new Rectangle(this); + } - @Override - public boolean equals(Object object2) { - if (!(object2 instanceof Rectangle) || !super.equals(object2)) return false; - Rectangle shape2 = (Rectangle) object2; - return shape2.width == width && shape2.height == height; + @Override + public boolean equals(Object object2) { + if (!(object2 instanceof Rectangle shape2) || !super.equals(object2)) { + return false; } + return shape2.width == width && shape2.height == height; + } + + @Override + public int hashCode() { + return Integer.hashCode(width) + ^ Integer.hashCode(height); + } } diff --git a/src/refactoring_guru/prototype/example/shapes/Shape.java b/src/refactoring_guru/prototype/example/shapes/Shape.java index 6893a3f..28215a7 100644 --- a/src/refactoring_guru/prototype/example/shapes/Shape.java +++ b/src/refactoring_guru/prototype/example/shapes/Shape.java @@ -3,27 +3,32 @@ import java.util.Objects; public abstract class Shape { - public int x; - public int y; - public String color; + public int x; + public int y; + public String color; - public Shape() { - } + protected Shape() { + } - public Shape(Shape target) { - if (target != null) { - this.x = target.x; - this.y = target.y; - this.color = target.color; - } + protected Shape(Shape target) { + if (target != null) { + this.x = target.x; + this.y = target.y; + this.color = target.color; } + } - public abstract Shape clone(); + public abstract Shape clone(); - @Override - public boolean equals(Object object2) { - if (!(object2 instanceof Shape)) return false; - Shape shape2 = (Shape) object2; - return shape2.x == x && shape2.y == y && Objects.equals(shape2.color, color); - } + @Override + public boolean equals(Object object2) { + if (!(object2 instanceof Shape shape2)) return false; + return shape2.x == x && shape2.y == y && Objects.equals(shape2.color, color); + } + + @Override + public int hashCode() { + return Integer.hashCode(x) + ^ Integer.hashCode(y); + } } From 5231019f208736eb2abbad6f9db40ef17ad0479c Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 15:55:44 +0300 Subject: [PATCH 32/45] some changes in proxy package --- src/refactoring_guru/proxy/example/Demo.java | 59 ++++++------ .../proxy/example/downloader/Renderer.java | 27 ++++++ .../example/downloader/YouTubeDownloader.java | 42 ++++---- .../example/proxy/YouTubeCacheProxy.java | 52 +++++----- .../ThirdPartyYouTubeClass.java | 96 +++++++------------ .../ThirdPartyYouTubeLib.java | 6 +- .../some_cool_media_library/Video.java | 16 ++-- 7 files changed, 148 insertions(+), 150 deletions(-) create mode 100644 src/refactoring_guru/proxy/example/downloader/Renderer.java diff --git a/src/refactoring_guru/proxy/example/Demo.java b/src/refactoring_guru/proxy/example/Demo.java index 4861f65..f9c47c4 100644 --- a/src/refactoring_guru/proxy/example/Demo.java +++ b/src/refactoring_guru/proxy/example/Demo.java @@ -1,35 +1,40 @@ package refactoring_guru.proxy.example; +import refactoring_guru.proxy.example.downloader.Renderer; import refactoring_guru.proxy.example.downloader.YouTubeDownloader; import refactoring_guru.proxy.example.proxy.YouTubeCacheProxy; import refactoring_guru.proxy.example.some_cool_media_library.ThirdPartyYouTubeClass; -public class Demo { - - public static void main(String[] args) { - YouTubeDownloader naiveDownloader = new YouTubeDownloader(new ThirdPartyYouTubeClass()); - YouTubeDownloader smartDownloader = new YouTubeDownloader(new YouTubeCacheProxy()); - - long naive = test(naiveDownloader); - long smart = test(smartDownloader); - System.out.print("Time saved by caching proxy: " + (naive - smart) + "ms"); - - } +import java.util.logging.Logger; - private static long test(YouTubeDownloader downloader) { - long startTime = System.currentTimeMillis(); - - // User behavior in our app: - downloader.renderPopularVideos(); - downloader.renderVideoPage("catzzzzzzzzz"); - downloader.renderPopularVideos(); - downloader.renderVideoPage("dancesvideoo"); - // Users might visit the same page quite often. - downloader.renderVideoPage("catzzzzzzzzz"); - downloader.renderVideoPage("someothervid"); - - long estimatedTime = System.currentTimeMillis() - startTime; - System.out.print("Time elapsed: " + estimatedTime + "ms\n"); - return estimatedTime; - } +public class Demo { + private static final Logger LOGGER = Logger.getLogger(Demo.class.getName()); + + public static void main(String[] args) { + final YouTubeDownloader naiveDownloader = new YouTubeDownloader(new ThirdPartyYouTubeClass(), new Renderer()); + final YouTubeDownloader smartDownloader = new YouTubeDownloader(new YouTubeCacheProxy(), new Renderer()); + + final long naive = test(naiveDownloader); + final long smart = test(smartDownloader); + + LOGGER.info("Time saved by caching proxy: " + (naive - smart) + "ms"); + } + + private static long test(YouTubeDownloader downloader) { + final long startTime = System.currentTimeMillis(); + simulateUserBehavior(downloader); + + final long estimatedTime = System.currentTimeMillis() - startTime; + LOGGER.info("Time elapsed: " + estimatedTime + "ms"); + return estimatedTime; + } + + private static void simulateUserBehavior(YouTubeDownloader downloader) { + downloader.renderPopularVideos(); + downloader.renderVideoPage("catzzzzzzzzz"); + downloader.renderPopularVideos(); + downloader.renderVideoPage("dancesvideoo"); + downloader.renderVideoPage("catzzzzzzzzz"); + downloader.renderVideoPage("someothervid"); + } } \ No newline at end of file diff --git a/src/refactoring_guru/proxy/example/downloader/Renderer.java b/src/refactoring_guru/proxy/example/downloader/Renderer.java new file mode 100644 index 0000000..626f7ae --- /dev/null +++ b/src/refactoring_guru/proxy/example/downloader/Renderer.java @@ -0,0 +1,27 @@ +package refactoring_guru.proxy.example.downloader; + +import refactoring_guru.proxy.example.some_cool_media_library.Video; + +import java.util.Map; + +public class Renderer { + private static final String SEPARATOR = "\n-------------------------------\n"; + + void renderVideo(Video video) { + System.out.println(SEPARATOR); + System.out.println("Video page (imagine fancy HTML)"); + System.out.println("ID: " + video.id); + System.out.println("Title: " + video.title); + System.out.println("Video: " + video.data); + System.out.println(SEPARATOR); + } + + void renderPopularVideos(Map videos) { + System.out.println(SEPARATOR); + System.out.println("Most popular videos on YouTube (imagine fancy HTML)"); + for (Video video : videos.values()) { + System.out.println("ID: " + video.id + " / Title: " + video.title); + } + System.out.println(SEPARATOR); + } +} diff --git a/src/refactoring_guru/proxy/example/downloader/YouTubeDownloader.java b/src/refactoring_guru/proxy/example/downloader/YouTubeDownloader.java index 1ae9d2c..28ef58a 100644 --- a/src/refactoring_guru/proxy/example/downloader/YouTubeDownloader.java +++ b/src/refactoring_guru/proxy/example/downloader/YouTubeDownloader.java @@ -3,32 +3,32 @@ import refactoring_guru.proxy.example.some_cool_media_library.ThirdPartyYouTubeLib; import refactoring_guru.proxy.example.some_cool_media_library.Video; -import java.util.HashMap; +import java.util.Map; public class YouTubeDownloader { - private ThirdPartyYouTubeLib api; + private final ThirdPartyYouTubeLib api; + private final Renderer renderer; - public YouTubeDownloader(ThirdPartyYouTubeLib api) { - this.api = api; - } + public YouTubeDownloader(ThirdPartyYouTubeLib api, Renderer renderer) { + this.api = api; + this.renderer = renderer; + } - public void renderVideoPage(String videoId) { - Video video = api.getVideo(videoId); - System.out.println("\n-------------------------------"); - System.out.println("Video page (imagine fancy HTML)"); - System.out.println("ID: " + video.id); - System.out.println("Title: " + video.title); - System.out.println("Video: " + video.data); - System.out.println("-------------------------------\n"); + public void renderVideoPage(String videoId) { + Video video = api.getVideo(videoId); + if (video != null) { + renderer.renderVideo(video); + } else { + throw new IllegalArgumentException("No more videos "); } + } - public void renderPopularVideos() { - HashMap list = api.popularVideos(); - System.out.println("\n-------------------------------"); - System.out.println("Most popular videos on YouTube (imagine fancy HTML)"); - for (Video video : list.values()) { - System.out.println("ID: " + video.id + " / Title: " + video.title); - } - System.out.println("-------------------------------\n"); + public void renderPopularVideos() { + Map list = api.popularVideos(); + if (list != null && !list.isEmpty()) { + renderer.renderPopularVideos(list); + } else { + throw new IllegalArgumentException("The List is empty "); } + } } diff --git a/src/refactoring_guru/proxy/example/proxy/YouTubeCacheProxy.java b/src/refactoring_guru/proxy/example/proxy/YouTubeCacheProxy.java index 7a2887c..676fb2b 100644 --- a/src/refactoring_guru/proxy/example/proxy/YouTubeCacheProxy.java +++ b/src/refactoring_guru/proxy/example/proxy/YouTubeCacheProxy.java @@ -5,40 +5,32 @@ import refactoring_guru.proxy.example.some_cool_media_library.Video; import java.util.HashMap; +import java.util.Map; public class YouTubeCacheProxy implements ThirdPartyYouTubeLib { - private ThirdPartyYouTubeLib youtubeService; - private HashMap cachePopular = new HashMap(); - private HashMap cacheAll = new HashMap(); + private final ThirdPartyYouTubeLib youtubeService; + private final Map cachePopular = new HashMap<>(); + private final Map cacheAll = new HashMap<>(); - public YouTubeCacheProxy() { - this.youtubeService = new ThirdPartyYouTubeClass(); - } + public YouTubeCacheProxy() { + this.youtubeService = new ThirdPartyYouTubeClass(); + } - @Override - public HashMap popularVideos() { - if (cachePopular.isEmpty()) { - cachePopular = youtubeService.popularVideos(); - } else { - System.out.println("Retrieved list from cache."); - } - return cachePopular; - } + @Override + public Map popularVideos() { + return cachePopular.isEmpty() ? youtubeService.popularVideos() : logAndReturn(cachePopular); + } - @Override - public Video getVideo(String videoId) { - Video video = cacheAll.get(videoId); - if (video == null) { - video = youtubeService.getVideo(videoId); - cacheAll.put(videoId, video); - } else { - System.out.println("Retrieved video '" + videoId + "' from cache."); - } - return video; - } + @Override + public Video getVideo(String videoId) { + return cacheAll.computeIfAbsent(videoId, key -> { + System.out.println("Fetching video '" + key + "' from YouTube service."); + return youtubeService.getVideo(key); + }); + } - public void reset() { - cachePopular.clear(); - cacheAll.clear(); - } + private T logAndReturn(T result) { + System.out.println("Retrieved a list from cache."); + return result; + } } diff --git a/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeClass.java b/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeClass.java index 7c2e07e..d9433d0 100644 --- a/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeClass.java +++ b/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeClass.java @@ -1,68 +1,42 @@ package refactoring_guru.proxy.example.some_cool_media_library; import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; public class ThirdPartyYouTubeClass implements ThirdPartyYouTubeLib { - @Override - public HashMap popularVideos() { - connectToServer("http://www.youtube.com"); - return getRandomVideos(); - } - - @Override - public Video getVideo(String videoId) { - connectToServer("http://www.youtube.com/" + videoId); - return getSomeVideo(videoId); - } - - // ----------------------------------------------------------------------- - // Fake methods to simulate network activity. They as slow as a real life. - - private int random(int min, int max) { - return min + (int) (Math.random() * ((max - min) + 1)); - } - - private void experienceNetworkLatency() { - int randomLatency = random(5, 10); - for (int i = 0; i < randomLatency; i++) { - try { - Thread.sleep(100); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } - } - } - - private void connectToServer(String server) { - System.out.print("Connecting to " + server + "... "); - experienceNetworkLatency(); - System.out.print("Connected!" + "\n"); - } - - private HashMap getRandomVideos() { - System.out.print("Downloading populars... "); - - experienceNetworkLatency(); - HashMap hmap = new HashMap(); - hmap.put("catzzzzzzzzz", new Video("sadgahasgdas", "Catzzzz.avi")); - hmap.put("mkafksangasj", new Video("mkafksangasj", "Dog play with ball.mp4")); - hmap.put("dancesvideoo", new Video("asdfas3ffasd", "Dancing video.mpq")); - hmap.put("dlsdk5jfslaf", new Video("dlsdk5jfslaf", "Barcelona vs RealM.mov")); - hmap.put("3sdfgsd1j333", new Video("3sdfgsd1j333", "Programing lesson#1.avi")); - - System.out.print("Done!" + "\n"); - return hmap; - } - - private Video getSomeVideo(String videoId) { - System.out.print("Downloading video... "); - - experienceNetworkLatency(); - Video video = new Video(videoId, "Some video title"); - - System.out.print("Done!" + "\n"); - return video; - } - + private static final Logger LOGGER = Logger.getLogger(ThirdPartyYouTubeClass.class.getName()); + + @Override + public Map popularVideos() { + connectToServer("http://www.youtube.com"); + return fetchPopularVideos(); + } + + @Override + public Video getVideo(String videoId) { + connectToServer("http://www.youtube.com/" + videoId); + return fetchVideo(videoId); + } + + private void connectToServer(String server) { + LOGGER.info("Connecting to " + server + "... "); + LOGGER.info("Connected!" + "\n"); + } + + private Map fetchPopularVideos() { + LOGGER.info("Downloading popular videos... "); + Map videoMap = new HashMap<>(); + videoMap.put("catzzzzzzzzz", new Video("sadgahasgdas", "Catzzzz.avi")); + LOGGER.info("Done!" + "\n"); + return videoMap; + } + + private Video fetchVideo(String videoId) { + LOGGER.info("Downloading video... "); + Video video = new Video(videoId, "Some video title"); + LOGGER.info("Done!" + "\n"); + return video; + } } diff --git a/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeLib.java b/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeLib.java index e05ff22..2839975 100644 --- a/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeLib.java +++ b/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeLib.java @@ -1,9 +1,9 @@ package refactoring_guru.proxy.example.some_cool_media_library; -import java.util.HashMap; +import java.util.Map; public interface ThirdPartyYouTubeLib { - HashMap popularVideos(); + Map popularVideos(); - Video getVideo(String videoId); + Video getVideo(String videoId); } diff --git a/src/refactoring_guru/proxy/example/some_cool_media_library/Video.java b/src/refactoring_guru/proxy/example/some_cool_media_library/Video.java index 96cf8b8..4411287 100644 --- a/src/refactoring_guru/proxy/example/some_cool_media_library/Video.java +++ b/src/refactoring_guru/proxy/example/some_cool_media_library/Video.java @@ -1,13 +1,13 @@ package refactoring_guru.proxy.example.some_cool_media_library; public class Video { - public String id; - public String title; - public String data; + public String id; + public String title; + public String data; - Video(String id, String title) { - this.id = id; - this.title = title; - this.data = "Random video."; - } + Video(String id, String title) { + this.id = id; + this.title = title; + this.data = "Random video."; + } } From 73cfa09e412eba066da325b76cedc05812248a09 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 15:58:43 +0300 Subject: [PATCH 33/45] some changes in Singleton package --- .../non_thread_safe/DemoMultiThread.java | 46 +++++---- .../non_thread_safe/DemoSingleThread.java | 22 +++-- .../example/non_thread_safe/Singleton.java | 38 ++++---- .../example/thread_safe/DemoMultiThread.java | 46 +++++---- .../example/thread_safe/Singleton.java | 95 ++++++++++--------- 5 files changed, 135 insertions(+), 112 deletions(-) diff --git a/src/refactoring_guru/singleton/example/non_thread_safe/DemoMultiThread.java b/src/refactoring_guru/singleton/example/non_thread_safe/DemoMultiThread.java index 848534b..7bab4ee 100644 --- a/src/refactoring_guru/singleton/example/non_thread_safe/DemoMultiThread.java +++ b/src/refactoring_guru/singleton/example/non_thread_safe/DemoMultiThread.java @@ -1,29 +1,33 @@ package refactoring_guru.singleton.example.non_thread_safe; public class DemoMultiThread { - public static void main(String[] args) { - System.out.println("If you see the same value, then singleton was reused (yay!)" + "\n" + - "If you see different values, then 2 singletons were created (booo!!)" + "\n\n" + - "RESULT:" + "\n"); - Thread threadFoo = new Thread(new ThreadFoo()); - Thread threadBar = new Thread(new ThreadBar()); - threadFoo.start(); - threadBar.start(); - } + public static void main(String[] args) { + String textBlock = """ + \""" If you see the same value, then singleton was reused (yay!) + \"""If you see different values, then 2 singletons were created (booo!!) + \"""RESULT + """; + + System.out.println(textBlock); + Thread threadFoo = new Thread(new ThreadFoo()); + Thread threadBar = new Thread(new ThreadBar()); + threadFoo.start(); + threadBar.start(); + } - static class ThreadFoo implements Runnable { - @Override - public void run() { - Singleton singleton = Singleton.getInstance("FOO"); - System.out.println(singleton.value); - } + static class ThreadFoo implements Runnable { + @Override + public void run() { + Singleton singleton = Singleton.getInstance("FOO"); + System.out.println(singleton.value); } + } - static class ThreadBar implements Runnable { - @Override - public void run() { - Singleton singleton = Singleton.getInstance("BAR"); - System.out.println(singleton.value); - } + static class ThreadBar implements Runnable { + @Override + public void run() { + Singleton singleton = Singleton.getInstance("BAR"); + System.out.println(singleton.value); } + } } diff --git a/src/refactoring_guru/singleton/example/non_thread_safe/DemoSingleThread.java b/src/refactoring_guru/singleton/example/non_thread_safe/DemoSingleThread.java index 6aba849..fbc5b85 100644 --- a/src/refactoring_guru/singleton/example/non_thread_safe/DemoSingleThread.java +++ b/src/refactoring_guru/singleton/example/non_thread_safe/DemoSingleThread.java @@ -1,13 +1,17 @@ package refactoring_guru.singleton.example.non_thread_safe; public class DemoSingleThread { - public static void main(String[] args) { - System.out.println("If you see the same value, then singleton was reused (yay!)" + "\n" + - "If you see different values, then 2 singletons were created (booo!!)" + "\n\n" + - "RESULT:" + "\n"); - Singleton singleton = Singleton.getInstance("FOO"); - Singleton anotherSingleton = Singleton.getInstance("BAR"); - System.out.println(singleton.value); - System.out.println(anotherSingleton.value); - } + public static void main(String[] args) { + var textBlock = """ + If you see the same value, then singleton was reused (yay!) + If you see different values, then 2 singletons were created (booo!!) + RESULT + """; + + System.out.println(textBlock); + Singleton singleton = Singleton.getInstance("FOO"); + Singleton anotherSingleton = Singleton.getInstance("BAR"); + System.out.println(singleton.value); + System.out.println(anotherSingleton.value); + } } diff --git a/src/refactoring_guru/singleton/example/non_thread_safe/Singleton.java b/src/refactoring_guru/singleton/example/non_thread_safe/Singleton.java index d091303..22c00cd 100644 --- a/src/refactoring_guru/singleton/example/non_thread_safe/Singleton.java +++ b/src/refactoring_guru/singleton/example/non_thread_safe/Singleton.java @@ -1,25 +1,29 @@ package refactoring_guru.singleton.example.non_thread_safe; public final class Singleton { - private static Singleton instance; - public String value; + private static Singleton instance; + public String value; - private Singleton(String value) { - // EN: The following code emulates slow initialization. - // - // RU: Этот код эмулирует медленную инициализацию. - try { - Thread.sleep(1000); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } - this.value = value; + /** + * EN: The following code emulates slow initialization. + *

+ * RU: Этот код эмулирует медленную инициализацию. + * + * @param value example value + */ + private Singleton(String value) { + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); } + this.value = value; + } - public static Singleton getInstance(String value) { - if (instance == null) { - instance = new Singleton(value); - } - return instance; + public static Singleton getInstance(String value) { + if (instance == null) { + instance = new Singleton(value); } + return instance; + } } diff --git a/src/refactoring_guru/singleton/example/thread_safe/DemoMultiThread.java b/src/refactoring_guru/singleton/example/thread_safe/DemoMultiThread.java index a0fd882..a37e204 100644 --- a/src/refactoring_guru/singleton/example/thread_safe/DemoMultiThread.java +++ b/src/refactoring_guru/singleton/example/thread_safe/DemoMultiThread.java @@ -1,29 +1,33 @@ package refactoring_guru.singleton.example.thread_safe; public class DemoMultiThread { - public static void main(String[] args) { - System.out.println("If you see the same value, then singleton was reused (yay!)" + "\n" + - "If you see different values, then 2 singletons were created (booo!!)" + "\n\n" + - "RESULT:" + "\n"); - Thread threadFoo = new Thread(new ThreadFoo()); - Thread threadBar = new Thread(new ThreadBar()); - threadFoo.start(); - threadBar.start(); - } + public static void main(String[] args) { + var textBlock = """ + If you see the same value, then singleton was reused (yay!) + If you see different values, then 2 singletons were created (booo!!) + RESULT + """; + + System.out.println(textBlock); + Thread threadFoo = new Thread(new ThreadFoo()); + Thread threadBar = new Thread(new ThreadBar()); + threadFoo.start(); + threadBar.start(); + } - static class ThreadFoo implements Runnable { - @Override - public void run() { - Singleton singleton = Singleton.getInstance("FOO"); - System.out.println(singleton.value); - } + static class ThreadFoo implements Runnable { + @Override + public void run() { + Singleton singleton = Singleton.getInstance("FOO"); + System.out.println(singleton.value); } + } - static class ThreadBar implements Runnable { - @Override - public void run() { - Singleton singleton = Singleton.getInstance("BAR"); - System.out.println(singleton.value); - } + static class ThreadBar implements Runnable { + @Override + public void run() { + Singleton singleton = Singleton.getInstance("BAR"); + System.out.println(singleton.value); } + } } diff --git a/src/refactoring_guru/singleton/example/thread_safe/Singleton.java b/src/refactoring_guru/singleton/example/thread_safe/Singleton.java index 95b8365..0f03d31 100644 --- a/src/refactoring_guru/singleton/example/thread_safe/Singleton.java +++ b/src/refactoring_guru/singleton/example/thread_safe/Singleton.java @@ -1,52 +1,59 @@ package refactoring_guru.singleton.example.thread_safe; +/** + * EN: The field must be declared volatile so that double check lock would + * work correctly. + *

+ * RU: Поле обязательно должно быть объявлено volatile, чтобы двойная + * проверка блокировки сработала как надо. + */ public final class Singleton { - // EN: The field must be declared volatile so that double check lock would - // work correctly. - // - // RU: Поле обязательно должно быть объявлено volatile, чтобы двойная - // проверка блокировки сработала как надо. - private static volatile Singleton instance; + private static Singleton instance; - public String value; + public String value; - private Singleton(String value) { - this.value = value; - } + private Singleton(String value) { + this.value = value; + } - public static Singleton getInstance(String value) { - // EN: The approach taken here is called double-checked locking (DCL). - // It exists to prevent race condition between multiple threads that may - // attempt to get singleton instance at the same time, creating - // separate instances as a result. - // - // It may seem that having the `result` variable here is completely - // pointless. There is, however, a very important caveat when - // implementing double-checked locking in Java, which is solved by - // introducing this local variable. - // - // You can read more info DCL issues in Java here: - // https://refactoring.guru/java-dcl-issue - // - // RU: Техника, которую мы здесь применяем называется «блокировка с - // двойной проверкой» (Double-Checked Locking). Она применяется, чтобы - // предотвратить создание нескольких объектов-одиночек, если метод будет - // вызван из нескольких потоков одновременно. - // - // Хотя переменная `result` вполне оправданно кажется здесь лишней, она - // помогает избежать подводных камней реализации DCL в Java. - // - // Больше об этой проблеме можно почитать здесь: - // https://refactoring.guru/ru/java-dcl-issue - Singleton result = instance; - if (result != null) { - return result; - } - synchronized(Singleton.class) { - if (instance == null) { - instance = new Singleton(value); - } - return instance; - } + /** + * It exists to prevent race condition between multiple threads that may + * EN: The approach taken here is called double-checked locking (DCL). + * attempt to get singleton instance at the same time, creating + * separate instances as a result. + *

+ * It may seem that having the `result` variable here is completely + * pointless. There is, however, a very important caveat when + * implementing double-checked locking in Java, which is solved by + * introducing this local variable. + *

+ * You can read more info DCL issues in Java here: + * {@link ...} + *

+ * RU: Техника, которую мы здесь применяем называется «блокировка с + * двойной проверкой» (Double-Checked Locking). Она применяется, чтобы + * предотвратить создание нескольких объектов-одиночек, если метод будет + * вызван из нескольких потоков одновременно. + *

+ * Хотя переменная `result` вполне оправданно кажется здесь лишней, она + * помогает избежать подводных камней реализации DCL в Java. + *

+ * Больше об этой проблеме можно почитать здесь: + * {@link ...} + * + * @param value value which can be provided + * @return the instance of the Singleton class + */ + public static Singleton getInstance(String value) { + Singleton result = instance; + if (result != null) { + return result; + } + synchronized (Singleton.class) { + if (instance == null) { + instance = new Singleton(value); + } + return instance; } + } } From ed2f705ad023a84bd009b14aaaaf98b7269cff2d Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 17:18:50 +0300 Subject: [PATCH 34/45] some changes in State package --- src/refactoring_guru/state/example/Demo.java | 12 +- .../state/example/states/LockedState.java | 53 ++++----- .../state/example/states/PlayingState.java | 44 ++++---- .../state/example/states/ReadyState.java | 47 ++++---- .../state/example/states/State.java | 35 +++--- .../state/example/ui/Player.java | 105 +++++++++--------- src/refactoring_guru/state/example/ui/UI.java | 72 ++++++------ 7 files changed, 187 insertions(+), 181 deletions(-) diff --git a/src/refactoring_guru/state/example/Demo.java b/src/refactoring_guru/state/example/Demo.java index 03b89dd..20cd91e 100644 --- a/src/refactoring_guru/state/example/Demo.java +++ b/src/refactoring_guru/state/example/Demo.java @@ -5,13 +5,13 @@ /** * EN: Demo class. Everything comes together here. - * + *

* RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - public static void main(String[] args) { - Player player = new Player(); - UI ui = new UI(player); - ui.init(); - } + public static void main(String[] args) { + Player player = new Player(); + UI ui = new UI(player); + ui.init(); + } } diff --git a/src/refactoring_guru/state/example/states/LockedState.java b/src/refactoring_guru/state/example/states/LockedState.java index 1dde3f1..69f4303 100644 --- a/src/refactoring_guru/state/example/states/LockedState.java +++ b/src/refactoring_guru/state/example/states/LockedState.java @@ -5,39 +5,40 @@ /** * EN: Concrete states provide the special implementation for all interface * methods. - * + *

* RU: Конкретные состояния реализуют методы абстрактного состояния по-своему. */ public class LockedState extends State { + private static final String LOCKED = "Locked..."; - LockedState(Player player) { - super(player); - player.setPlaying(false); - } + public LockedState(Player player) { + super(player); + player.setPlaying(false); + } - @Override - public String onLock() { - if (player.isPlaying()) { - player.changeState(new ReadyState(player)); - return "Stop playing"; - } else { - return "Locked..."; - } + @Override + public String onLock() { + if (player.isPlaying()) { + player.changeState(new ReadyState(player)); + return "Stop playing"; + } else { + return LOCKED; } + } - @Override - public String onPlay() { - player.changeState(new ReadyState(player)); - return "Ready"; - } + @Override + public String onPlay() { + player.changeState(new ReadyState(player)); + return "Ready"; + } - @Override - public String onNext() { - return "Locked..."; - } + @Override + public String onNext() { + return LOCKED; + } - @Override - public String onPrevious() { - return "Locked..."; - } + @Override + public String onPrevious() { + return LOCKED; + } } diff --git a/src/refactoring_guru/state/example/states/PlayingState.java b/src/refactoring_guru/state/example/states/PlayingState.java index 8b42e70..9a6cf94 100644 --- a/src/refactoring_guru/state/example/states/PlayingState.java +++ b/src/refactoring_guru/state/example/states/PlayingState.java @@ -4,30 +4,30 @@ public class PlayingState extends State { - PlayingState(Player player) { - super(player); - } + public PlayingState(Player player) { + super(player); + } - @Override - public String onLock() { - player.changeState(new LockedState(player)); - player.setCurrentTrackAfterStop(); - return "Stop playing"; - } + @Override + public String onLock() { + player.changeState(new LockedState(player)); + player.setCurrentTrackAfterStop(); + return "Stop playing"; + } - @Override - public String onPlay() { - player.changeState(new ReadyState(player)); - return "Paused..."; - } + @Override + public String onPlay() { + player.changeState(new ReadyState(player)); + return "Paused..."; + } - @Override - public String onNext() { - return player.nextTrack(); - } + @Override + public String onNext() { + return player.nextTrack(); + } - @Override - public String onPrevious() { - return player.previousTrack(); - } + @Override + public String onPrevious() { + return player.previousTrack(); + } } diff --git a/src/refactoring_guru/state/example/states/ReadyState.java b/src/refactoring_guru/state/example/states/ReadyState.java index c27e138..5287797 100644 --- a/src/refactoring_guru/state/example/states/ReadyState.java +++ b/src/refactoring_guru/state/example/states/ReadyState.java @@ -4,35 +4,36 @@ /** * EN: They can also trigger state transitions in the context. - * + *

* RU: Они также могут переводить контекст в другие состояния. */ public class ReadyState extends State { + private static final String LOCKED = "Locked..."; - public ReadyState(Player player) { - super(player); - } + public ReadyState(Player player) { + super(player); + } - @Override - public String onLock() { - player.changeState(new LockedState(player)); - return "Locked..."; - } + @Override + public String onLock() { + player.changeState(new LockedState(player)); + return LOCKED; + } - @Override - public String onPlay() { - String action = player.startPlayback(); - player.changeState(new PlayingState(player)); - return action; - } + @Override + public String onPlay() { + String action = player.startPlayback(); + player.changeState(new PlayingState(player)); + return action; + } - @Override - public String onNext() { - return "Locked..."; - } + @Override + public String onNext() { + return LOCKED; + } - @Override - public String onPrevious() { - return "Locked..."; - } + @Override + public String onPrevious() { + return LOCKED; + } } diff --git a/src/refactoring_guru/state/example/states/State.java b/src/refactoring_guru/state/example/states/State.java index 8263cf9..f038f3d 100644 --- a/src/refactoring_guru/state/example/states/State.java +++ b/src/refactoring_guru/state/example/states/State.java @@ -4,25 +4,28 @@ /** * EN: Common interface for all states. - * + *

* RU: Общий интерфейс всех состояний. */ public abstract class State { - Player player; + Player player; - /** - * EN: Context passes itself through the state constructor. This may help a - * state to fetch some useful context data if needed. - * - * RU: Контекст передаёт себя в конструктор состояния, чтобы состояние могло - * обращаться к его данным и методам в будущем, если потребуется. - */ - State(Player player) { - this.player = player; - } + /** + * EN: Context passes itself through the state constructor. This may help a + * state to fetch some useful context data if needed. + *

+ * RU: Контекст передаёт себя в конструктор состояния, чтобы состояние могло + * обращаться к его данным и методам в будущем, если потребуется. + */ + protected State(Player player) { + this.player = player; + } - public abstract String onLock(); - public abstract String onPlay(); - public abstract String onNext(); - public abstract String onPrevious(); + public abstract String onLock(); + + public abstract String onPlay(); + + public abstract String onNext(); + + public abstract String onPrevious(); } diff --git a/src/refactoring_guru/state/example/ui/Player.java b/src/refactoring_guru/state/example/ui/Player.java index c8b7cb7..837bbc1 100644 --- a/src/refactoring_guru/state/example/ui/Player.java +++ b/src/refactoring_guru/state/example/ui/Player.java @@ -7,56 +7,57 @@ import java.util.List; public class Player { - private State state; - private boolean playing = false; - private List playlist = new ArrayList<>(); - private int currentTrack = 0; - - public Player() { - this.state = new ReadyState(this); - setPlaying(true); - for (int i = 1; i <= 12; i++) { - playlist.add("Track " + i); - } - } - - public void changeState(State state) { - this.state = state; - } - - public State getState() { - return state; - } - - public void setPlaying(boolean playing) { - this.playing = playing; - } - - public boolean isPlaying() { - return playing; - } - - public String startPlayback() { - return "Playing " + playlist.get(currentTrack); - } - - public String nextTrack() { - currentTrack++; - if (currentTrack > playlist.size() - 1) { - currentTrack = 0; - } - return "Playing " + playlist.get(currentTrack); - } - - public String previousTrack() { - currentTrack--; - if (currentTrack < 0) { - currentTrack = playlist.size() - 1; - } - return "Playing " + playlist.get(currentTrack); - } - - public void setCurrentTrackAfterStop() { - this.currentTrack = 0; - } + private static final String PLAY = "Playing "; + private State state; + private boolean playing = false; + private final List playlist = new ArrayList<>(); + private int currentTrack = 0; + + public Player() { + this.state = new ReadyState(this); + setPlaying(true); + for (int i = 1; i <= 12; i++) { + playlist.add("Track " + i); + } + } + + public void changeState(State state) { + this.state = state; + } + + public State getState() { + return state; + } + + public void setPlaying(boolean playing) { + this.playing = playing; + } + + public boolean isPlaying() { + return playing; + } + + public String startPlayback() { + return PLAY + playlist.get(currentTrack); + } + + public String nextTrack() { + currentTrack++; + if (currentTrack > playlist.size() - 1) { + currentTrack = 0; + } + return PLAY + playlist.get(currentTrack); + } + + public String previousTrack() { + currentTrack--; + if (currentTrack < 0) { + currentTrack = playlist.size() - 1; + } + return PLAY + playlist.get(currentTrack); + } + + public void setCurrentTrackAfterStop() { + this.currentTrack = 0; + } } diff --git a/src/refactoring_guru/state/example/ui/UI.java b/src/refactoring_guru/state/example/ui/UI.java index 9f66146..e4ce600 100644 --- a/src/refactoring_guru/state/example/ui/UI.java +++ b/src/refactoring_guru/state/example/ui/UI.java @@ -4,43 +4,43 @@ import java.awt.*; public class UI { - private Player player; - private static JTextField textField = new JTextField(); + private final Player player; + private static final JTextField textField = new JTextField(); - public UI(Player player) { - this.player = player; - } + public UI(Player player) { + this.player = player; + } - public void init() { - JFrame frame = new JFrame("Test player"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - JPanel context = new JPanel(); - context.setLayout(new BoxLayout(context, BoxLayout.Y_AXIS)); - frame.getContentPane().add(context); - JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER)); - context.add(textField); - context.add(buttons); + public void init() { + JFrame frame = new JFrame("Test player"); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + JPanel context = new JPanel(); + context.setLayout(new BoxLayout(context, BoxLayout.Y_AXIS)); + frame.getContentPane().add(context); + JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER)); + context.add(textField); + context.add(buttons); - // EN: Context delegates handling user's input to a state object. - // Naturally, the outcome will depend on what state is currently active, - // since all states can handle the input differently. - // - // RU: Контекст заставляет состояние реагировать на пользовательский - // ввод вместо себя. Реакция может быть разной в зависимости от того, - // какое состояние сейчас активно. - JButton play = new JButton("Play"); - play.addActionListener(e -> textField.setText(player.getState().onPlay())); - JButton stop = new JButton("Stop"); - stop.addActionListener(e -> textField.setText(player.getState().onLock())); - JButton next = new JButton("Next"); - next.addActionListener(e -> textField.setText(player.getState().onNext())); - JButton prev = new JButton("Prev"); - prev.addActionListener(e -> textField.setText(player.getState().onPrevious())); - frame.setVisible(true); - frame.setSize(300, 100); - buttons.add(play); - buttons.add(stop); - buttons.add(next); - buttons.add(prev); - } + // EN: Context delegates handling user's input to a state object. + // Naturally, the outcome will depend on what state is currently active, + // since all states can handle the input differently. + // + // RU: Контекст заставляет состояние реагировать на пользовательский + // ввод вместо себя. Реакция может быть разной в зависимости от того, + // какое состояние сейчас активно. + JButton play = new JButton("Play"); + play.addActionListener(e -> textField.setText(player.getState().onPlay())); + JButton stop = new JButton("Stop"); + stop.addActionListener(e -> textField.setText(player.getState().onLock())); + JButton next = new JButton("Next"); + next.addActionListener(e -> textField.setText(player.getState().onNext())); + JButton prev = new JButton("Prev"); + prev.addActionListener(e -> textField.setText(player.getState().onPrevious())); + frame.setVisible(true); + frame.setSize(300, 100); + buttons.add(play); + buttons.add(stop); + buttons.add(next); + buttons.add(prev); + } } From 5e6bac44d68b8920b5613229b3d3b75d997fe48b Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 18:08:12 +0300 Subject: [PATCH 35/45] some changes in Strategy package --- .../strategy/example/order/Order.java | 61 +++++----- .../example/strategies/CreditCard.java | 28 ++--- .../example/strategies/PayByCreditCard.java | 82 ++++++-------- .../example/strategies/PayByPayPal.java | 104 +++++++++--------- .../example/strategies/PayStrategy.java | 7 +- 5 files changed, 134 insertions(+), 148 deletions(-) diff --git a/src/refactoring_guru/strategy/example/order/Order.java b/src/refactoring_guru/strategy/example/order/Order.java index f8695c7..69edfe3 100644 --- a/src/refactoring_guru/strategy/example/order/Order.java +++ b/src/refactoring_guru/strategy/example/order/Order.java @@ -6,37 +6,40 @@ * EN: Order class. Doesn't know the concrete payment method (strategy) user has * picked. It uses common strategy interface to delegate collecting payment data * to strategy object. It can be used to save order to database. - * + *

* RU: Класс заказа. Ничего не знает о том каким способом (стратегией) будет * расчитыватся клиент, а просто вызывает метод оплаты. Все остальное стратегия * делает сама. */ public class Order { - private int totalCost = 0; - private boolean isClosed = false; - - public void processOrder(PayStrategy strategy) { - strategy.collectPaymentDetails(); - // EN: Here we could collect and store payment data from the strategy. - // - // RU: Здесь мы могли бы забрать и сохранить платежные данные из - // стратегии. - } - - public void setTotalCost(int cost) { - this.totalCost += cost; - } - - public int getTotalCost() { - return totalCost; - } - - public boolean isClosed() { - return isClosed; - } - - public void setClosed() { - isClosed = true; - } -} - + private int totalCost = 0; + private boolean isClosed = false; + + /** + * EN: Here we could collect and store payment data from the strategy. + *

+ * RU: Здесь мы могли бы забрать и сохранить платежные данные из + * стратегии. + * + * @param strategy given option + */ + public void processOrder(PayStrategy strategy) { + strategy.collectPaymentDetails(); + } + + public void setTotalCost(int cost) { + this.totalCost += cost; + } + + public int getTotalCost() { + return totalCost; + } + + public boolean isClosed() { + return isClosed; + } + + public void setClosed() { + isClosed = true; + } +} \ No newline at end of file diff --git a/src/refactoring_guru/strategy/example/strategies/CreditCard.java b/src/refactoring_guru/strategy/example/strategies/CreditCard.java index 20a09d5..717135d 100644 --- a/src/refactoring_guru/strategy/example/strategies/CreditCard.java +++ b/src/refactoring_guru/strategy/example/strategies/CreditCard.java @@ -2,28 +2,22 @@ /** * EN: Dummy credit card class. - * + *

* RU: Очень наивная реализация кредитной карты. */ public class CreditCard { - private int amount; - private String number; - private String date; - private String cvv; + private int amount; - CreditCard(String number, String date, String cvv) { - this.amount = 100_000; - this.number = number; - this.date = date; - this.cvv = cvv; - } + public CreditCard() { + this.amount = 100_000; + } - public void setAmount(int amount) { - this.amount = amount; - } + public void setAmount(int amount) { + this.amount = amount; + } - public int getAmount() { - return amount; - } + public int getAmount() { + return amount; + } } diff --git a/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java b/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java index 8deea76..e201254 100644 --- a/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java +++ b/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java @@ -6,58 +6,46 @@ /** * EN: Concrete strategy. Implements credit card payment method. - * + *

* RU: Конкретная стратегия. Реализует оплату корзины интернет магазина * кредитной картой клиента. */ public class PayByCreditCard implements PayStrategy { - private final BufferedReader READER = new BufferedReader(new InputStreamReader(System.in)); - private CreditCard card; - - /** - * EN: Collect credit card data. - * - * RU: Собираем данные карты клиента. - */ - @Override - public void collectPaymentDetails() { - try { - System.out.print("Enter the card number: "); - String number = READER.readLine(); - System.out.print("Enter the card expiration date 'mm/yy': "); - String date = READER.readLine(); - System.out.print("Enter the CVV code: "); - String cvv = READER.readLine(); - card = new CreditCard(number, date, cvv); - - // EN: Validate credit card number... - // - // RU: Валидируем номер карты... - - } catch (IOException ex) { - ex.printStackTrace(); - } + private CreditCard card; + + /** + * EN: Collect credit card data. + *

+ * RU: Собираем данные карты клиента. + */ + @Override + public void collectPaymentDetails() { + System.out.print("Enter the card number: "); + System.out.print("Enter the card expiration date 'mm/yy': "); + System.out.print("Enter the CVV code: "); + + card = new CreditCard(); + } + + /** + * EN: After card validation we can charge customer's credit card. + *

+ * RU: После проверки карты мы можем совершить оплату. Если клиент + * продолжает покупки, мы не запрашиваем карту заново. + */ + @Override + public boolean pay(int paymentAmount) { + if (cardIsPresent()) { + System.out.println("Paying " + paymentAmount + " using Credit Card."); + card.setAmount(card.getAmount() - paymentAmount); + return true; + } else { + return false; } + } - /** - * EN: After card validation we can charge customer's credit card. - * - * RU: После проверки карты мы можем совершить оплату. Если клиент - * продолжает покупки, мы не запрашиваем карту заново. - */ - @Override - public boolean pay(int paymentAmount) { - if (cardIsPresent()) { - System.out.println("Paying " + paymentAmount + " using Credit Card."); - card.setAmount(card.getAmount() - paymentAmount); - return true; - } else { - return false; - } - } - - private boolean cardIsPresent() { - return card != null; - } + private boolean cardIsPresent() { + return card != null; + } } diff --git a/src/refactoring_guru/strategy/example/strategies/PayByPayPal.java b/src/refactoring_guru/strategy/example/strategies/PayByPayPal.java index fe6b963..3c7c4f0 100644 --- a/src/refactoring_guru/strategy/example/strategies/PayByPayPal.java +++ b/src/refactoring_guru/strategy/example/strategies/PayByPayPal.java @@ -8,69 +8,69 @@ /** * EN: Concrete strategy. Implements PayPal payment method. - * + *

* RU: Конкретная стратегия. Реализует оплату корзины интернет магазина через * платежную систему PayPal. */ public class PayByPayPal implements PayStrategy { - private static final Map DATA_BASE = new HashMap<>(); - private final BufferedReader READER = new BufferedReader(new InputStreamReader(System.in)); - private String email; - private String password; - private boolean signedIn; + private static final Map DATA_BASE = new HashMap<>(); + private final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); + private String email; + private String password; + private boolean signedIn; - static { - DATA_BASE.put("amanda1985", "amanda@ya.com"); - DATA_BASE.put("qwerty", "john@amazon.eu"); - } + static { + DATA_BASE.put("amanda1985", "amanda@ya.com"); + DATA_BASE.put("qwerty", "john@amazon.eu"); + } - /** - * EN: Collect customer's data. - * - * RU: Собираем данные от клиента. - */ - @Override - public void collectPaymentDetails() { - try { - while (!signedIn) { - System.out.print("Enter the user's email: "); - email = READER.readLine(); - System.out.print("Enter the password: "); - password = READER.readLine(); - if (verify()) { - System.out.println("Data verification has been successful."); - } else { - System.out.println("Wrong email or password!"); - } - } - } catch (IOException ex) { - ex.printStackTrace(); + /** + * EN: Collect customer's data. + *

+ * RU: Собираем данные от клиента. + */ + @Override + public void collectPaymentDetails() { + try { + while (!signedIn) { + System.out.print("Enter the user's email: "); + email = bufferedReader.readLine(); + System.out.print("Enter the password: "); + password = bufferedReader.readLine(); + if (verify()) { + System.out.println("Data verification has been successful."); + } else { + System.out.println("Wrong email or password!"); } + } + } catch (IOException ex) { + ex.printStackTrace(); } + } - private boolean verify() { - setSignedIn(email.equals(DATA_BASE.get(password))); - return signedIn; + /** + * EN: Save customer data for future shopping attempts. + *

+ * RU: Если клиент уже вошел в систему, то для следующей оплаты данные + * вводить не придется. + */ + @Override + public boolean pay(int paymentAmount) { + if (signedIn) { + System.out.println("Paying " + paymentAmount + " using PayPal."); + return true; + } else { + return false; } + } - /** - * EN: Save customer data for future shopping attempts. - * - * RU: Если клиент уже вошел в систему, то для следующей оплаты данные - * вводить не придется. - */ - @Override - public boolean pay(int paymentAmount) { - if (signedIn) { - System.out.println("Paying " + paymentAmount + " using PayPal."); - return true; - } else { - return false; - } - } + private boolean verify() { + setSignedIn(email.equals(DATA_BASE.get(password))); + return signedIn; + } - private void setSignedIn(boolean signedIn) { - this.signedIn = signedIn; - } + private void setSignedIn(boolean signedIn) { + this.signedIn = signedIn; + } } diff --git a/src/refactoring_guru/strategy/example/strategies/PayStrategy.java b/src/refactoring_guru/strategy/example/strategies/PayStrategy.java index 45a20c9..28f9806 100644 --- a/src/refactoring_guru/strategy/example/strategies/PayStrategy.java +++ b/src/refactoring_guru/strategy/example/strategies/PayStrategy.java @@ -2,11 +2,12 @@ /** * EN: Common interface for all strategies. - * + *

* RU: Общий интерфейс всех стратегий. */ public interface PayStrategy { - boolean pay(int paymentAmount); - void collectPaymentDetails(); + boolean pay(int paymentAmount); + + void collectPaymentDetails(); } From 83f6331f1b3c3a26599e07a587a1df3a6978de77 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 18:33:34 +0300 Subject: [PATCH 36/45] some changes in Strategy package --- .../strategy/example/Demo.java | 133 ++++++++---------- .../strategy/example/init/PaymentMethod.java | 37 +++++ .../strategy/example/init/Product.java | 29 ++++ 3 files changed, 126 insertions(+), 73 deletions(-) create mode 100644 src/refactoring_guru/strategy/example/init/PaymentMethod.java create mode 100644 src/refactoring_guru/strategy/example/init/Product.java diff --git a/src/refactoring_guru/strategy/example/Demo.java b/src/refactoring_guru/strategy/example/Demo.java index 5182c15..e556297 100644 --- a/src/refactoring_guru/strategy/example/Demo.java +++ b/src/refactoring_guru/strategy/example/Demo.java @@ -1,95 +1,82 @@ package refactoring_guru.strategy.example; +import refactoring_guru.strategy.example.init.PaymentMethod; +import refactoring_guru.strategy.example.init.Product; import refactoring_guru.strategy.example.order.Order; -import refactoring_guru.strategy.example.strategies.PayByCreditCard; -import refactoring_guru.strategy.example.strategies.PayByPayPal; import refactoring_guru.strategy.example.strategies.PayStrategy; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Map; /** * EN: World first console e-commerce application. - * - * RU: Первый в мире консольный интерет магазин. + *

+ * RU: Первый в мире консольный интернет магазин. */ public class Demo { - private static Map priceOnProducts = new HashMap<>(); - private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); - private static Order order = new Order(); - private static PayStrategy strategy; + private static final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); + private static final Order order = new Order(); + private static PayStrategy strategy; - static { - priceOnProducts.put(1, 2200); - priceOnProducts.put(2, 1850); - priceOnProducts.put(3, 1100); - priceOnProducts.put(4, 890); - } + private static final String PRODUCT_SELECTION_TEXT = """ + Please select a product: + 1 - Mother board + 2 - CPU + 3 - HDD + 4 - Memory + """; - public static void main(String[] args) throws IOException { - while (!order.isClosed()) { - int cost; + private static final String PAYMENT_METHOD_TEXT = """ + Please select a payment method: + 1 - PalPay + 2 - Credit Card + """; - String continueChoice; - do { - System.out.print("Please, select a product:" + "\n" + - "1 - Mother board" + "\n" + - "2 - CPU" + "\n" + - "3 - HDD" + "\n" + - "4 - Memory" + "\n"); - int choice = Integer.parseInt(reader.readLine()); - cost = priceOnProducts.get(choice); - System.out.print("Count: "); - int count = Integer.parseInt(reader.readLine()); - order.setTotalCost(cost * count); - System.out.print("Do you wish to continue selecting products? Y/N: "); - continueChoice = reader.readLine(); - } while (continueChoice.equalsIgnoreCase("Y")); + public static void main(String[] args) throws IOException { + while (!order.isClosed()) { + processUserInput(); + processPayment(); + } + } - if (strategy == null) { - System.out.println("Please, select a payment method:" + "\n" + - "1 - PalPay" + "\n" + - "2 - Credit Card"); - String paymentMethod = reader.readLine(); + private static void processUserInput() throws IOException { + String continueChoice = ""; + do { + System.out.print(PRODUCT_SELECTION_TEXT); + try { + int choice = Integer.parseInt(bufferedReader.readLine()); + Product product = Product.fromChoice(choice); + System.out.print("Count: "); + int count = Integer.parseInt(bufferedReader.readLine()); + order.setTotalCost(product.getPrice() * count); + } catch (IllegalArgumentException e) { + System.out.println("Invalid input. Please try again."); + continue; + } + System.out.print("Do you wish to continue selecting products? Y/N: "); + continueChoice = bufferedReader.readLine(); + } while (continueChoice.equalsIgnoreCase("Y")); + } - // EN: Client creates different strategies based on input from - // user, application configuration, etc. - // - // RU: Клиент создаёт различные стратегии на основании - // пользовательских данных, конфигурации и прочих параметров. - if (paymentMethod.equals("1")) { - strategy = new PayByPayPal(); - } else { - strategy = new PayByCreditCard(); - } - } + private static void processPayment() throws IOException { + if (strategy == null) { + System.out.println(PAYMENT_METHOD_TEXT); + var paymentMethod = bufferedReader.readLine(); + strategy = PaymentMethod.fromChoice(Integer.parseInt(paymentMethod)).createStrategy(); + } - // EN: Order object delegates gathering payment data to strategy - // object, since only strategies know what data they need to - // process a payment. - // - // RU: Объект заказа делегирует сбор платёжных данны стратегии, - // т.к. только стратегии знают какие данные им нужны для приёма - // оплаты. - order.processOrder(strategy); + order.processOrder(strategy); - System.out.print("Pay " + order.getTotalCost() + " units or Continue shopping? P/C: "); - String proceed = reader.readLine(); - if (proceed.equalsIgnoreCase("P")) { - // EN: Finally, strategy handles the payment. - // - // RU: И наконец, стратегия запускает приём платежа. - if (strategy.pay(order.getTotalCost())) { - System.out.println("Payment has been successful."); - } else { - System.out.println("FAIL! Please, check your data."); - } - order.setClosed(); - } - } + System.out.print("Pay " + order.getTotalCost() + " units or Continue shopping? P/C: "); + var proceed = bufferedReader.readLine(); + if (proceed.equalsIgnoreCase("P")) { + if (strategy.pay(order.getTotalCost())) { + System.out.println("Payment has been successful."); + } else { + System.out.println("FAIL! Please, check your data."); + } + order.setClosed(); } + } } - diff --git a/src/refactoring_guru/strategy/example/init/PaymentMethod.java b/src/refactoring_guru/strategy/example/init/PaymentMethod.java new file mode 100644 index 0000000..5440424 --- /dev/null +++ b/src/refactoring_guru/strategy/example/init/PaymentMethod.java @@ -0,0 +1,37 @@ +package refactoring_guru.strategy.example.init; + +import refactoring_guru.strategy.example.strategies.PayByCreditCard; +import refactoring_guru.strategy.example.strategies.PayByPayPal; +import refactoring_guru.strategy.example.strategies.PayStrategy; + +public enum PaymentMethod { + PAYPAL(1) { + @Override + public PayStrategy createStrategy() { + return new PayByPayPal(); + } + }, + CREDIT_CARD(2) { + @Override + public PayStrategy createStrategy() { + return new PayByCreditCard(); + } + }; + + private final int choice; + + PaymentMethod(int choice) { + this.choice = choice; + } + + public abstract PayStrategy createStrategy(); + + public static PaymentMethod fromChoice(int choice) { + for (PaymentMethod method : values()) { + if (method.choice == choice) { + return method; + } + } + throw new IllegalArgumentException("Invalid choice: " + choice); + } +} diff --git a/src/refactoring_guru/strategy/example/init/Product.java b/src/refactoring_guru/strategy/example/init/Product.java new file mode 100644 index 0000000..d27849b --- /dev/null +++ b/src/refactoring_guru/strategy/example/init/Product.java @@ -0,0 +1,29 @@ +package refactoring_guru.strategy.example.init; + +public enum Product { + MOTHER_BOARD(1, 2200), + CPU(2, 1850), + HDD(3, 1100), + MEMORY(4, 890); + + private final int choice; + private final int price; + + Product(int choice, int price) { + this.choice = choice; + this.price = price; + } + + public int getPrice() { + return price; + } + + public static Product fromChoice(int choice) { + for (Product product : values()) { + if (product.choice == choice) { + return product; + } + } + throw new IllegalArgumentException("Invalid choice: " + choice); + } +} From fc3b30f8a60bc396832f7f7002bb86db73ebdf8e Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Thu, 5 Oct 2023 18:33:59 +0300 Subject: [PATCH 37/45] remove files --- .../mediator/example/components/List.java | 82 --------- .../memento/example/editor/Canvas.java | 171 ------------------ 2 files changed, 253 deletions(-) delete mode 100644 src/refactoring_guru/mediator/example/components/List.java delete mode 100644 src/refactoring_guru/memento/example/editor/Canvas.java diff --git a/src/refactoring_guru/mediator/example/components/List.java b/src/refactoring_guru/mediator/example/components/List.java deleted file mode 100644 index 3694ce6..0000000 --- a/src/refactoring_guru/mediator/example/components/List.java +++ /dev/null @@ -1,82 +0,0 @@ -package refactoring_guru.mediator.example.components; - -import refactoring_guru.mediator.example.mediator.Mediator; -import refactoring_guru.mediator.example.mediator.Note; - -import javax.swing.*; - -/** - * EN: Concrete components don't talk with each other. They have only one - * communication channel–sending requests to the mediator. - * - * RU: Конкретные компоненты никак не связаны между собой. У них есть только - * один канал общения – через отправку уведомлений посреднику. - */ -@SuppressWarnings("unchecked") -public class List extends JList implements Component { - private Mediator mediator; - private final DefaultListModel LIST_MODEL; - - public List(DefaultListModel listModel) { - super(listModel); - this.LIST_MODEL = listModel; - setModel(listModel); - this.setLayoutOrientation(JList.VERTICAL); - Thread thread = new Thread(new Hide(this)); - thread.start(); - } - - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } - - public void addElement(Note note) { - LIST_MODEL.addElement(note); - int index = LIST_MODEL.size() - 1; - setSelectedIndex(index); - ensureIndexIsVisible(index); - mediator.sendToFilter(LIST_MODEL); - } - - public void deleteElement() { - int index = this.getSelectedIndex(); - try { - LIST_MODEL.remove(index); - mediator.sendToFilter(LIST_MODEL); - } catch (ArrayIndexOutOfBoundsException ignored) {} - } - - public Note getCurrentElement() { - return (Note)getSelectedValue(); - } - - @Override - public String getName() { - return "List"; - } - - private class Hide implements Runnable { - private List list; - - Hide(List list) { - this.list = list; - } - - @Override - public void run() { - while (true) { - try { - Thread.sleep(300); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } - if (list.isSelectionEmpty()) { - mediator.hideElements(true); - } else { - mediator.hideElements(false); - } - } - } - } -} diff --git a/src/refactoring_guru/memento/example/editor/Canvas.java b/src/refactoring_guru/memento/example/editor/Canvas.java deleted file mode 100644 index 06105ed..0000000 --- a/src/refactoring_guru/memento/example/editor/Canvas.java +++ /dev/null @@ -1,171 +0,0 @@ -package refactoring_guru.memento.example.editor; - -import refactoring_guru.memento.example.commands.ColorCommand; -import refactoring_guru.memento.example.commands.MoveCommand; -import refactoring_guru.memento.example.shapes.Shape; - -import javax.swing.*; -import javax.swing.border.Border; -import java.awt.*; -import java.awt.event.*; -import java.awt.image.BufferedImage; - -class Canvas extends java.awt.Canvas { - private Editor editor; - private JFrame frame; - private static final int PADDING = 10; - - Canvas(Editor editor) { - this.editor = editor; - createFrame(); - attachKeyboardListeners(); - attachMouseListeners(); - refresh(); - } - - private void createFrame() { - frame = new JFrame(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - frame.setLocationRelativeTo(null); - - JPanel contentPanel = new JPanel(); - Border padding = BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING); - contentPanel.setBorder(padding); - contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS)); - frame.setContentPane(contentPanel); - - contentPanel.add(new JLabel("Select and drag to move."), BorderLayout.PAGE_END); - contentPanel.add(new JLabel("Right click to change color."), BorderLayout.PAGE_END); - contentPanel.add(new JLabel("Undo: Ctrl+Z, Redo: Ctrl+R"), BorderLayout.PAGE_END); - contentPanel.add(this); - frame.setVisible(true); - contentPanel.setBackground(Color.LIGHT_GRAY); - } - - private void attachKeyboardListeners() { - addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0) { - switch (e.getKeyCode()) { - case KeyEvent.VK_Z: - editor.undo(); - break; - case KeyEvent.VK_R: - editor.redo(); - break; - } - } - } - }); - } - - private void attachMouseListeners() { - MouseAdapter colorizer = new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - if (e.getButton() != MouseEvent.BUTTON3) { - return; - } - Shape target = editor.getShapes().getChildAt(e.getX(), e.getY()); - if (target != null) { - editor.execute(new ColorCommand(editor, new Color((int) (Math.random() * 0x1000000)))); - repaint(); - } - } - }; - addMouseListener(colorizer); - - MouseAdapter selector = new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - if (e.getButton() != MouseEvent.BUTTON1) { - return; - } - - Shape target = editor.getShapes().getChildAt(e.getX(), e.getY()); - boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK; - - if (target == null) { - if (!ctrl) { - editor.getShapes().unSelect(); - } - } else { - if (ctrl) { - if (target.isSelected()) { - target.unSelect(); - } else { - target.select(); - } - } else { - if (!target.isSelected()) { - editor.getShapes().unSelect(); - } - target.select(); - } - } - repaint(); - } - }; - addMouseListener(selector); - - - MouseAdapter dragger = new MouseAdapter() { - MoveCommand moveCommand; - - @Override - public void mouseDragged(MouseEvent e) { - if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) != MouseEvent.BUTTON1_DOWN_MASK) { - return; - } - if (moveCommand == null) { - moveCommand = new MoveCommand(editor); - moveCommand.start(e.getX(), e.getY()); - } - moveCommand.move(e.getX(), e.getY()); - repaint(); - } - - @Override - public void mouseReleased(MouseEvent e) { - if (e.getButton() != MouseEvent.BUTTON1 || moveCommand == null) { - return; - } - moveCommand.stop(e.getX(), e.getY()); - editor.execute(moveCommand); - this.moveCommand = null; - repaint(); - } - }; - addMouseListener(dragger); - addMouseMotionListener(dragger); - } - - public int getWidth() { - return editor.getShapes().getX() + editor.getShapes().getWidth() + PADDING; - } - - public int getHeight() { - return editor.getShapes().getY() + editor.getShapes().getHeight() + PADDING; - } - - void refresh() { - this.setSize(getWidth(), getHeight()); - frame.pack(); - } - - public void update(Graphics g) { - paint(g); - } - - public void paint(Graphics graphics) { - BufferedImage buffer = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB); - Graphics2D ig2 = buffer.createGraphics(); - ig2.setBackground(Color.WHITE); - ig2.clearRect(0, 0, this.getWidth(), this.getHeight()); - - editor.getShapes().paint(buffer.getGraphics()); - - graphics.drawImage(buffer, 0, 0, null); - } -} From 610c3881aac8f274a509dae707fd08c7d9d79928 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Fri, 6 Oct 2023 13:51:25 +0300 Subject: [PATCH 38/45] minor update --- .../strategy/example/strategies/PayByCreditCard.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java b/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java index e201254..187b5d4 100644 --- a/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java +++ b/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java @@ -1,9 +1,5 @@ package refactoring_guru.strategy.example.strategies; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - /** * EN: Concrete strategy. Implements credit card payment method. *

From d24b272938e4205af55d27a18cb631e45d0a8234 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Fri, 6 Oct 2023 22:11:58 +0300 Subject: [PATCH 39/45] some changes in visitor package --- .../visitor/example/Demo.java | 34 +++--- .../visitor/example/shapes/Circle.java | 24 ++-- .../visitor/example/shapes/CompoundShape.java | 58 +++++----- .../visitor/example/shapes/Dot.java | 78 ++++++------- .../visitor/example/shapes/Rectangle.java | 96 ++++++++-------- .../visitor/example/shapes/Shape.java | 8 +- .../visitor/example/visitor/Visitor.java | 8 +- .../example/visitor/XMLExportVisitor.java | 103 +++++++++--------- 8 files changed, 205 insertions(+), 204 deletions(-) diff --git a/src/refactoring_guru/visitor/example/Demo.java b/src/refactoring_guru/visitor/example/Demo.java index 7effa76..71c659c 100644 --- a/src/refactoring_guru/visitor/example/Demo.java +++ b/src/refactoring_guru/visitor/example/Demo.java @@ -4,25 +4,25 @@ import refactoring_guru.visitor.example.visitor.XMLExportVisitor; public class Demo { - public static void main(String[] args) { - Dot dot = new Dot(1, 10, 55); - Circle circle = new Circle(2, 23, 15, 10); - Rectangle rectangle = new Rectangle(3, 10, 17, 20, 30); + public static void main(String[] args) { + Dot dot = new Dot(1, 10, 55); + Circle circle = new Circle(2, 23, 15, 10); + Rectangle rectangle = new Rectangle(3, 10, 17, 20, 30); - CompoundShape compoundShape = new CompoundShape(4); - compoundShape.add(dot); - compoundShape.add(circle); - compoundShape.add(rectangle); + CompoundShape compoundShape = new CompoundShape(4); + compoundShape.add(dot); + compoundShape.add(circle); + compoundShape.add(rectangle); - CompoundShape c = new CompoundShape(5); - c.add(dot); - compoundShape.add(c); + CompoundShape c = new CompoundShape(5); + c.add(dot); + compoundShape.add(c); - export(circle, compoundShape); - } + export(circle, compoundShape); + } - private static void export(Shape... shapes) { - XMLExportVisitor exportVisitor = new XMLExportVisitor(); - System.out.println(exportVisitor.export(shapes)); - } + private static void export(Shape... shapes) { + XMLExportVisitor exportVisitor = new XMLExportVisitor(); + System.out.println(exportVisitor.export(shapes)); + } } diff --git a/src/refactoring_guru/visitor/example/shapes/Circle.java b/src/refactoring_guru/visitor/example/shapes/Circle.java index 908a388..28ca385 100644 --- a/src/refactoring_guru/visitor/example/shapes/Circle.java +++ b/src/refactoring_guru/visitor/example/shapes/Circle.java @@ -3,19 +3,19 @@ import refactoring_guru.visitor.example.visitor.Visitor; public class Circle extends Dot { - private int radius; + private final int radius; - public Circle(int id, int x, int y, int radius) { - super(id, x, y); - this.radius = radius; - } + public Circle(int id, int x, int y, int radius) { + super(id, x, y); + this.radius = radius; + } - @Override - public String accept(Visitor visitor) { - return visitor.visitCircle(this); - } + @Override + public String accept(Visitor visitor) { + return visitor.visitCircle(this); + } - public int getRadius() { - return radius; - } + public int getRadius() { + return radius; + } } diff --git a/src/refactoring_guru/visitor/example/shapes/CompoundShape.java b/src/refactoring_guru/visitor/example/shapes/CompoundShape.java index bd8b32b..097f42f 100644 --- a/src/refactoring_guru/visitor/example/shapes/CompoundShape.java +++ b/src/refactoring_guru/visitor/example/shapes/CompoundShape.java @@ -6,33 +6,33 @@ import java.util.List; public class CompoundShape implements Shape { - public int id; - public List children = new ArrayList<>(); - - public CompoundShape(int id) { - this.id = id; - } - - @Override - public void move(int x, int y) { - // move shape - } - - @Override - public void draw() { - // draw shape - } - - public int getId() { - return id; - } - - @Override - public String accept(Visitor visitor) { - return visitor.visitCompoundGraphic(this); - } - - public void add(Shape shape) { - children.add(shape); - } + public int id; + public List children = new ArrayList<>(); + + public CompoundShape(int id) { + this.id = id; + } + + @Override + public void move(int x, int y) { + // move shape + } + + @Override + public void draw() { + // draw shape + } + + public int getId() { + return id; + } + + @Override + public String accept(Visitor visitor) { + return visitor.visitCompoundGraphic(this); + } + + public void add(Shape shape) { + children.add(shape); + } } diff --git a/src/refactoring_guru/visitor/example/shapes/Dot.java b/src/refactoring_guru/visitor/example/shapes/Dot.java index 5e37a85..a4bffc7 100644 --- a/src/refactoring_guru/visitor/example/shapes/Dot.java +++ b/src/refactoring_guru/visitor/example/shapes/Dot.java @@ -3,43 +3,43 @@ import refactoring_guru.visitor.example.visitor.Visitor; public class Dot implements Shape { - private int id; - private int x; - private int y; - - public Dot() { - } - - public Dot(int id, int x, int y) { - this.id = id; - this.x = x; - this.y = y; - } - - @Override - public void move(int x, int y) { - // move shape - } - - @Override - public void draw() { - // draw shape - } - - @Override - public String accept(Visitor visitor) { - return visitor.visitDot(this); - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } - - public int getId() { - return id; - } + private int id; + private int x; + private int y; + + public Dot() { + } + + public Dot(int id, int x, int y) { + this.id = id; + this.x = x; + this.y = y; + } + + @Override + public void move(int x, int y) { + // move shape + } + + @Override + public void draw() { + // draw shape + } + + @Override + public String accept(Visitor visitor) { + return visitor.visitDot(this); + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getId() { + return id; + } } diff --git a/src/refactoring_guru/visitor/example/shapes/Rectangle.java b/src/refactoring_guru/visitor/example/shapes/Rectangle.java index d439065..5bbb144 100644 --- a/src/refactoring_guru/visitor/example/shapes/Rectangle.java +++ b/src/refactoring_guru/visitor/example/shapes/Rectangle.java @@ -3,52 +3,52 @@ import refactoring_guru.visitor.example.visitor.Visitor; public class Rectangle implements Shape { - private int id; - private int x; - private int y; - private int width; - private int height; - - public Rectangle(int id, int x, int y, int width, int height) { - this.id = id; - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } - - @Override - public String accept(Visitor visitor) { - return visitor.visitRectangle(this); - } - - @Override - public void move(int x, int y) { - // move shape - } - - @Override - public void draw() { - // draw shape - } - - public int getId() { - return id; - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } + private final int id; + private final int x; + private final int y; + private final int width; + private final int height; + + public Rectangle(int id, int x, int y, int width, int height) { + this.id = id; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + @Override + public String accept(Visitor visitor) { + return visitor.visitRectangle(this); + } + + @Override + public void move(int x, int y) { + // move shape + } + + @Override + public void draw() { + // draw shape + } + + public int getId() { + return id; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } } diff --git a/src/refactoring_guru/visitor/example/shapes/Shape.java b/src/refactoring_guru/visitor/example/shapes/Shape.java index e190136..4c4a633 100644 --- a/src/refactoring_guru/visitor/example/shapes/Shape.java +++ b/src/refactoring_guru/visitor/example/shapes/Shape.java @@ -3,7 +3,9 @@ import refactoring_guru.visitor.example.visitor.Visitor; public interface Shape { - void move(int x, int y); - void draw(); - String accept(Visitor visitor); + void move(int x, int y); + + void draw(); + + String accept(Visitor visitor); } diff --git a/src/refactoring_guru/visitor/example/visitor/Visitor.java b/src/refactoring_guru/visitor/example/visitor/Visitor.java index 60d0ecf..e0d8683 100644 --- a/src/refactoring_guru/visitor/example/visitor/Visitor.java +++ b/src/refactoring_guru/visitor/example/visitor/Visitor.java @@ -6,11 +6,11 @@ import refactoring_guru.visitor.example.shapes.Rectangle; public interface Visitor { - String visitDot(Dot dot); + String visitDot(Dot dot); - String visitCircle(Circle circle); + String visitCircle(Circle circle); - String visitRectangle(Rectangle rectangle); + String visitRectangle(Rectangle rectangle); - String visitCompoundGraphic(CompoundShape cg); + String visitCompoundGraphic(CompoundShape cg); } diff --git a/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java b/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java index a1e41e8..b276fe8 100644 --- a/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java +++ b/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java @@ -4,58 +4,57 @@ public class XMLExportVisitor implements Visitor { - public String export(Shape... args) { - StringBuilder sb = new StringBuilder(); - sb.append("" + "\n"); - for (Shape shape : args) { - sb.append(shape.accept(this)).append("\n"); - } - return sb.toString(); + public String export(Shape... args) { + StringBuilder sb = new StringBuilder(); + sb.append("" + "\n"); + for (Shape shape : args) { + sb.append(shape.accept(this)).append("\n"); } - - public String visitDot(Dot d) { - return "" + "\n" + - " " + d.getId() + "" + "\n" + - " " + d.getX() + "" + "\n" + - " " + d.getY() + "" + "\n" + - ""; - } - - public String visitCircle(Circle c) { - return "" + "\n" + - " " + c.getId() + "" + "\n" + - " " + c.getX() + "" + "\n" + - " " + c.getY() + "" + "\n" + - " " + c.getRadius() + "" + "\n" + - ""; - } - - public String visitRectangle(Rectangle r) { - return "" + "\n" + - " " + r.getId() + "" + "\n" + - " " + r.getX() + "" + "\n" + - " " + r.getY() + "" + "\n" + - " " + r.getWidth() + "" + "\n" + - " " + r.getHeight() + "" + "\n" + - ""; + return sb.toString(); + } + + public String visitDot(Dot d) { + return "" + "\n" + + " " + d.getId() + "" + "\n" + + " " + d.getX() + "" + "\n" + + " " + d.getY() + "" + "\n" + + ""; + } + + public String visitCircle(Circle c) { + return "" + "\n" + + " " + c.getId() + "" + "\n" + + " " + c.getX() + "" + "\n" + + " " + c.getY() + "" + "\n" + + " " + c.getRadius() + "" + "\n" + + ""; + } + + public String visitRectangle(Rectangle r) { + return "" + "\n" + + " " + r.getId() + "" + "\n" + + " " + r.getX() + "" + "\n" + + " " + r.getY() + "" + "\n" + + " " + r.getWidth() + "" + "\n" + + " " + r.getHeight() + "" + "\n" + + ""; + } + + public String visitCompoundGraphic(CompoundShape cg) { + return "" + "\n" + + " " + cg.getId() + "" + "\n" + + _visitCompoundGraphic(cg) + + ""; + } + + private String _visitCompoundGraphic(CompoundShape cg) { + StringBuilder sb = new StringBuilder(); + for (Shape shape : cg.children) { + String obj = shape.accept(this); + // Proper indentation for sub-objects. + obj = " " + obj.replace("\n", "\n ") + "\n"; + sb.append(obj); } - - public String visitCompoundGraphic(CompoundShape cg) { - return "" + "\n" + - " " + cg.getId() + "" + "\n" + - _visitCompoundGraphic(cg) + - ""; - } - - private String _visitCompoundGraphic(CompoundShape cg) { - StringBuilder sb = new StringBuilder(); - for (Shape shape : cg.children) { - String obj = shape.accept(this); - // Proper indentation for sub-objects. - obj = " " + obj.replace("\n", "\n ") + "\n"; - sb.append(obj); - } - return sb.toString(); - } - + return sb.toString(); + } } From 7d7cbe2c5b6579db22a899a0677d60902852ef9d Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Fri, 6 Oct 2023 22:12:35 +0300 Subject: [PATCH 40/45] some changes in template method package --- .../template_method/example/Demo.java | 63 ++++++++++-------- .../example/networks/Facebook.java | 65 +++++++----------- .../example/networks/Network.java | 55 +++++++--------- .../example/networks/Twitter.java | 66 ++++++++----------- 4 files changed, 110 insertions(+), 139 deletions(-) diff --git a/src/refactoring_guru/template_method/example/Demo.java b/src/refactoring_guru/template_method/example/Demo.java index dd2735c..9429362 100644 --- a/src/refactoring_guru/template_method/example/Demo.java +++ b/src/refactoring_guru/template_method/example/Demo.java @@ -10,37 +10,44 @@ /** * EN: Demo class. Everything comes together here. - * + *

* RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - public static void main(String[] args) throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); - Network network = null; - System.out.print("Input user name: "); - String userName = reader.readLine(); - System.out.print("Input password: "); - String password = reader.readLine(); + public static void main(String[] args) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { + System.out.print("Input username: "); + String userName = reader.readLine(); + System.out.print("Input password: "); + String password = reader.readLine(); + System.out.print("Input message: "); + String message = reader.readLine(); - // EN: Enter the message. - // - // RU: Вводим сообщение. - System.out.print("Input message: "); - String message = reader.readLine(); - - System.out.println("\nChoose social network for posting message.\n" + - "1 - Facebook\n" + - "2 - Twitter"); - int choice = Integer.parseInt(reader.readLine()); - - // EN: Create proper network object and send the message. - // - // RU: Создаем сетевые объекты и публикуем пост. - if (choice == 1) { - network = new Facebook(userName, password); - } else if (choice == 2) { - network = new Twitter(userName, password); - } - network.post(message); + Network network = getNetwork(reader, userName, password); + if (network != null) { + network.logIn(userName, password); + network.sendData(message.getBytes()); + network.logOut(); + } + } catch (IOException e) { + e.printStackTrace(); } + } + + private static Network getNetwork(BufferedReader reader, String userName, String password) throws IOException { + System.out.println(""" + Choose social network for posting a message. + 1 - Facebook + 2 - Twitter + """); + int choice = Integer.parseInt(reader.readLine()); + return switch (choice) { + case 1 -> new Facebook(userName, password); + case 2 -> new Twitter(userName, password); + default -> { + System.out.println("Invalid choice. Please run the program again."); + yield null; + } + }; + } } diff --git a/src/refactoring_guru/template_method/example/networks/Facebook.java b/src/refactoring_guru/template_method/example/networks/Facebook.java index 740b59e..d7baee0 100644 --- a/src/refactoring_guru/template_method/example/networks/Facebook.java +++ b/src/refactoring_guru/template_method/example/networks/Facebook.java @@ -2,52 +2,37 @@ /** * EN: Class of social network - * + *

* RU: Класс социальной сети. */ public class Facebook extends Network { - public Facebook(String userName, String password) { - this.userName = userName; - this.password = password; - } + public Facebook(String userName, String password) { + super(userName, password); + } - public boolean logIn(String userName, String password) { - System.out.println("\nChecking user's parameters"); - System.out.println("Name: " + this.userName); - System.out.print("Password: "); - for (int i = 0; i < this.password.length(); i++) { - System.out.print("*"); - } - simulateNetworkLatency(); - System.out.println("\n\nLogIn success on Facebook"); - return true; - } + @Override + public void logIn(String userName, String password) { + simulateNetworkLatency(); + System.out.println("\n\nLogIn success on Facebook"); + } - public boolean sendData(byte[] data) { - boolean messagePosted = true; - if (messagePosted) { - System.out.println("Message: '" + new String(data) + "' was posted on Facebook"); - return true; - } else { - return false; - } - } + @Override + public void sendData(byte[] data) { + System.out.println("Message: '" + new String(data) + "' was posted on Facebook"); + } - public void logOut() { - System.out.println("User: '" + userName + "' was logged out from Facebook"); - } + @Override + public void logOut() { + System.out.println("User: '" + getUserName() + "' was logged out from Facebook"); + } - private void simulateNetworkLatency() { - try { - int i = 0; - System.out.println(); - while (i < 10) { - System.out.print("."); - Thread.sleep(500); - i++; - } - } catch (InterruptedException ex) { - ex.printStackTrace(); - } + protected void simulateNetworkLatency() { + try { + System.out.println("Simulating network latency..."); + Thread.sleep(5000); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + throw new RuntimeException(ex); } + } } diff --git a/src/refactoring_guru/template_method/example/networks/Network.java b/src/refactoring_guru/template_method/example/networks/Network.java index 1d85461..e5fb145 100644 --- a/src/refactoring_guru/template_method/example/networks/Network.java +++ b/src/refactoring_guru/template_method/example/networks/Network.java @@ -2,38 +2,31 @@ /** * EN: Base class of social network. - * + *

* RU: Базовый класс социальной сети. */ public abstract class Network { - String userName; - String password; - - Network() {} - - /** - * EN: Publish the data to whatever network. - * - * RU: Публикация данных в любой сети. - */ - public boolean post(String message) { - // EN: Authenticate before posting. Every network uses a different - // authentication method. - // - // RU: Проверка данных пользователя перед постом в соцсеть. Каждая сеть - // для проверки использует разные методы. - if (logIn(this.userName, this.password)) { - // EN: Send the post data. - // - // RU: Отправка данных. - boolean result = sendData(message.getBytes()); - logOut(); - return result; - } - return false; - } - - abstract boolean logIn(String userName, String password); - abstract boolean sendData(byte[] data); - abstract void logOut(); + public final String userName; + public final String password; + + protected Network(String userName, String password) { + this.userName = userName; + this.password = password; + } + + public String getUserName() { + return userName; + } + + public String getPassword() { + return password; + } + + public abstract void logIn(String userName, String password); + + public abstract void sendData(byte[] data); + + public abstract void logOut(); + + protected abstract void simulateNetworkLatency(); } \ No newline at end of file diff --git a/src/refactoring_guru/template_method/example/networks/Twitter.java b/src/refactoring_guru/template_method/example/networks/Twitter.java index d5eae2a..340cad0 100644 --- a/src/refactoring_guru/template_method/example/networks/Twitter.java +++ b/src/refactoring_guru/template_method/example/networks/Twitter.java @@ -2,53 +2,39 @@ /** * EN: Class of social network - * + *

* RU: Класс социальной сети. */ public class Twitter extends Network { - public Twitter(String userName, String password) { - this.userName = userName; - this.password = password; - } + public Twitter(String userName, String password) { + super(userName, password); + } - public boolean logIn(String userName, String password) { - System.out.println("\nChecking user's parameters"); - System.out.println("Name: " + this.userName); - System.out.print("Password: "); - for (int i = 0; i < this.password.length(); i++) { - System.out.print("*"); - } - simulateNetworkLatency(); - System.out.println("\n\nLogIn success on Twitter"); - return true; - } + @Override + public void logIn(String userName, String password) { + simulateNetworkLatency(); + System.out.println("\n\nLogIn success on Twitter"); + } - public boolean sendData(byte[] data) { - boolean messagePosted = true; - if (messagePosted) { - System.out.println("Message: '" + new String(data) + "' was posted on Twitter"); - return true; - } else { - return false; - } - } + @Override + public void sendData(byte[] data) { + System.out.println("Message: '" + new String(data) + "' it was posted on Twitter"); + } - public void logOut() { - System.out.println("User: '" + userName + "' was logged out from Twitter"); - } + @Override + public void logOut() { + System.out.println("User: '" + getUserName() + "' was logged out from Twitter"); + } - private void simulateNetworkLatency() { - try { - int i = 0; - System.out.println(); - while (i < 10) { - System.out.print("."); - Thread.sleep(500); - i++; - } - } catch (InterruptedException ex) { - ex.printStackTrace(); - } + @Override + protected void simulateNetworkLatency() { + try { + System.out.println("Simulating network latency..."); + Thread.sleep(5000); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + throw new RuntimeException(ex); } + } } From ba7b7dc3b2d9730abe23cd6727a2b4931f53ec50 Mon Sep 17 00:00:00 2001 From: Kalin Ivanov Date: Mon, 9 Oct 2023 10:59:50 +0300 Subject: [PATCH 41/45] convert Rectangle class to a record --- .../visitor/example/shapes/Rectangle.java | 35 +------------------ .../example/visitor/XMLExportVisitor.java | 10 +++--- 2 files changed, 6 insertions(+), 39 deletions(-) diff --git a/src/refactoring_guru/visitor/example/shapes/Rectangle.java b/src/refactoring_guru/visitor/example/shapes/Rectangle.java index 5bbb144..ce987d6 100644 --- a/src/refactoring_guru/visitor/example/shapes/Rectangle.java +++ b/src/refactoring_guru/visitor/example/shapes/Rectangle.java @@ -2,20 +2,7 @@ import refactoring_guru.visitor.example.visitor.Visitor; -public class Rectangle implements Shape { - private final int id; - private final int x; - private final int y; - private final int width; - private final int height; - - public Rectangle(int id, int x, int y, int width, int height) { - this.id = id; - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } +public record Rectangle(int id, int x, int y, int width, int height) implements Shape { @Override public String accept(Visitor visitor) { @@ -31,24 +18,4 @@ public void move(int x, int y) { public void draw() { // draw shape } - - public int getId() { - return id; - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } } diff --git a/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java b/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java index b276fe8..531b133 100644 --- a/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java +++ b/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java @@ -32,11 +32,11 @@ public String visitCircle(Circle c) { public String visitRectangle(Rectangle r) { return "" + "\n" + - " " + r.getId() + "" + "\n" + - " " + r.getX() + "" + "\n" + - " " + r.getY() + "" + "\n" + - " " + r.getWidth() + "" + "\n" + - " " + r.getHeight() + "" + "\n" + + " " + r.id() + "" + "\n" + + " " + r.x() + "" + "\n" + + " " + r.y() + "" + "\n" + + " " + r.width() + "" + "\n" + + " " + r.height() + "" + "\n" + ""; } From e3a69fba5ef3797eeb05f447edf448fb9ea093c9 Mon Sep 17 00:00:00 2001 From: Alexander Shvets Date: Mon, 9 Oct 2023 11:23:59 +0200 Subject: [PATCH 42/45] Revert "Java Code Refactor and "EXIT_ON_CLOSE" Fix" --- README.md | 25 +- .../abstract_factory/example/Demo.java | 44 +-- .../example/app/Application.java | 22 +- .../example/buttons/Button.java | 8 +- .../example/buttons/MacOSButton.java | 14 +- .../example/buttons/WindowsButton.java | 14 +- .../example/checkboxes/Checkbox.java | 4 +- .../example/checkboxes/MacOSCheckbox.java | 14 +- .../example/checkboxes/WindowsCheckbox.java | 14 +- .../example/factories/GUIFactory.java | 7 +- .../example/factories/MacOSFactory.java | 18 +- .../example/factories/WindowsFactory.java | 18 +- .../adapter/example/Demo.java | 53 ++- .../example/adapters/SquarePegAdapter.java | 29 +- .../adapter/example/round/RoundHole.java | 23 +- .../adapter/example/round/RoundPeg.java | 19 +- .../adapter/example/square/SquarePeg.java | 23 +- src/refactoring_guru/bridge/example/Demo.java | 30 +- .../bridge/example/devices/Device.java | 16 +- .../bridge/example/devices/Radio.java | 104 ++--- .../bridge/example/devices/Tv.java | 104 ++--- .../example/remotes/AdvancedRemote.java | 16 +- .../bridge/example/remotes/BasicRemote.java | 81 ++-- .../bridge/example/remotes/Remote.java | 10 +- .../builder/example/Demo.java | 48 ++- .../builder/example/builders/Builder.java | 19 +- .../builder/example/builders/CarBuilder.java | 80 ++-- .../example/builders/CarManualBuilder.java | 76 ++-- .../builder/example/cars/Car.java | 86 ++--- .../builder/example/cars/CarType.java | 2 +- .../builder/example/cars/Manual.java | 60 +-- .../builder/example/components/Engine.java | 68 ++-- .../example/components/GPSNavigator.java | 22 +- .../example/components/Transmission.java | 4 +- .../example/components/TripComputer.java | 28 +- .../builder/example/director/Director.java | 48 +-- .../example/Credentials.java | 4 - .../chain_of_responsibility/example/Demo.java | 72 ++-- .../example/middleware/Middleware.java | 63 ++-- .../middleware/RoleCheckMiddleware.java | 13 +- .../middleware/ThrottlingMiddleware.java | 86 ++--- .../middleware/UserExistsMiddleware.java | 30 +- .../example/server/Server.java | 84 +++-- .../command/example/Demo.java | 8 +- .../command/example/commands/Command.java | 24 +- .../example/commands/CommandHistory.java | 21 +- .../command/example/commands/CopyCommand.java | 16 +- .../command/example/commands/CutCommand.java | 34 +- .../example/commands/PasteCommand.java | 22 +- .../command/example/editor/Editor.java | 104 +++-- .../composite/example/Demo.java | 35 +- .../composite/example/editor/ImageEditor.java | 102 +++-- .../composite/example/shapes/BaseShape.java | 169 +++++---- .../composite/example/shapes/Circle.java | 35 +- .../example/shapes/CompoundShape.java | 230 ++++++------ .../composite/example/shapes/Dot.java | 33 +- .../composite/example/shapes/Rectangle.java | 40 +- .../composite/example/shapes/Shape.java | 29 +- .../decorator/example/Demo.java | 31 +- .../decorators/CompressionDecorator.java | 94 ++--- .../example/decorators/DataSource.java | 4 +- .../decorators/DataSourceDecorator.java | 24 +- .../decorators/EncryptionDecorator.java | 46 +-- .../example/decorators/FileDataSource.java | 51 ++- src/refactoring_guru/facade/example/Demo.java | 11 +- .../example/facade/VideoConversionFacade.java | 25 +- .../AudioMixer.java | 8 +- .../BitrateReader.java | 24 +- .../CodecFactory.java | 25 +- .../MPEG4CompressionCodec.java | 3 +- .../OggCompressionCodec.java | 2 +- .../some_complex_media_library/VideoFile.java | 24 +- .../factory_method/example/Demo.java | 62 +-- .../example/buttons/Button.java | 7 +- .../example/buttons/HtmlButton.java | 16 +- .../example/buttons/WindowsButton.java | 58 +-- .../example/factory/Dialog.java | 30 +- .../example/factory/HtmlDialog.java | 10 +- .../example/factory/WindowsDialog.java | 10 +- .../flyweight/example/Demo.java | 51 ++- .../flyweight/example/forest/Forest.java | 22 +- .../flyweight/example/trees/Tree.java | 22 +- .../flyweight/example/trees/TreeFactory.java | 20 +- .../flyweight/example/trees/TreeType.java | 24 +- .../iterator/example/Demo.java | 78 ++-- .../example/iterators/FacebookIterator.java | 90 ++--- .../example/iterators/LinkedInIterator.java | 90 ++--- .../example/iterators/ProfileIterator.java | 6 +- .../iterator/example/profile/Profile.java | 89 ++--- .../example/social_networks/Facebook.java | 128 ++++--- .../example/social_networks/LinkedIn.java | 115 +++--- .../social_networks/SocialNetwork.java | 4 +- .../example/spammer/SocialSpammer.java | 44 +-- .../mediator/example/Demo.java | 36 +- .../example/components/AddButton.java | 34 +- .../example/components/Component.java | 7 +- .../example/components/DeleteButton.java | 36 +- .../mediator/example/components/Filter.java | 86 +++-- .../mediator/example/components/InitList.java | 74 ---- .../mediator/example/components/List.java | 82 ++++ .../example/components/SaveButton.java | 34 +- .../mediator/example/components/TextBox.java | 28 +- .../mediator/example/components/Title.java | 28 +- .../mediator/example/mediator/Editor.java | 330 ++++++++-------- .../mediator/example/mediator/Mediator.java | 34 +- .../mediator/example/mediator/Note.java | 44 +-- .../memento/example/Demo.java | 34 +- .../example/commands/ColorCommand.java | 30 +- .../memento/example/commands/Command.java | 5 +- .../memento/example/commands/MoveCommand.java | 70 ++-- .../memento/example/editor/Canvas.java | 171 +++++++++ .../memento/example/editor/Editor.java | 94 ++--- .../memento/example/editor/Frame.java | 188 ---------- .../memento/example/editor/FrameMemento.java | 5 - .../memento/example/history/History.java | 101 +++-- .../memento/example/history/Memento.java | 20 +- .../memento/example/shapes/BaseShape.java | 227 +++++------ .../memento/example/shapes/Circle.java | 36 +- .../memento/example/shapes/CompoundShape.java | 354 +++++++++--------- .../memento/example/shapes/Dot.java | 35 +- .../memento/example/shapes/Rectangle.java | 40 +- .../memento/example/shapes/Shape.java | 44 +-- .../observer/example/Demo.java | 19 +- .../observer/example/editor/Editor.java | 30 +- .../listeners/EmailNotificationListener.java | 21 +- .../example/listeners/EventListener.java | 2 +- .../example/listeners/LogOpenListener.java | 21 +- .../example/publisher/EventManager.java | 36 +- .../prototype/caching/Demo.java | 40 +- .../caching/cache/BundledShapeCache.java | 56 +-- .../prototype/example/Demo.java | 74 ++-- .../prototype/example/shapes/Circle.java | 39 +- .../prototype/example/shapes/Rectangle.java | 45 +-- .../prototype/example/shapes/Shape.java | 41 +- src/refactoring_guru/proxy/example/Demo.java | 59 ++- .../proxy/example/downloader/Renderer.java | 27 -- .../example/downloader/YouTubeDownloader.java | 42 +-- .../example/proxy/YouTubeCacheProxy.java | 52 +-- .../ThirdPartyYouTubeClass.java | 96 +++-- .../ThirdPartyYouTubeLib.java | 6 +- .../some_cool_media_library/Video.java | 16 +- .../non_thread_safe/DemoMultiThread.java | 46 ++- .../non_thread_safe/DemoSingleThread.java | 22 +- .../example/non_thread_safe/Singleton.java | 38 +- .../example/thread_safe/DemoMultiThread.java | 46 ++- .../example/thread_safe/Singleton.java | 95 +++-- src/refactoring_guru/state/example/Demo.java | 12 +- .../state/example/states/LockedState.java | 53 ++- .../state/example/states/PlayingState.java | 44 +-- .../state/example/states/ReadyState.java | 47 ++- .../state/example/states/State.java | 35 +- .../state/example/ui/Player.java | 105 +++--- src/refactoring_guru/state/example/ui/UI.java | 72 ++-- .../strategy/example/Demo.java | 133 ++++--- .../strategy/example/init/PaymentMethod.java | 37 -- .../strategy/example/init/Product.java | 29 -- .../strategy/example/order/Order.java | 61 ++- .../example/strategies/CreditCard.java | 28 +- .../example/strategies/PayByCreditCard.java | 86 +++-- .../example/strategies/PayByPayPal.java | 104 ++--- .../example/strategies/PayStrategy.java | 7 +- .../template_method/example/Demo.java | 63 ++-- .../example/networks/Facebook.java | 65 ++-- .../example/networks/Network.java | 55 +-- .../example/networks/Twitter.java | 66 ++-- .../visitor/example/Demo.java | 34 +- .../visitor/example/shapes/Circle.java | 24 +- .../visitor/example/shapes/CompoundShape.java | 58 +-- .../visitor/example/shapes/Dot.java | 78 ++-- .../visitor/example/shapes/Rectangle.java | 65 +++- .../visitor/example/shapes/Shape.java | 8 +- .../visitor/example/visitor/Visitor.java | 8 +- .../example/visitor/XMLExportVisitor.java | 103 ++--- 173 files changed, 4292 insertions(+), 4317 deletions(-) delete mode 100644 src/refactoring_guru/chain_of_responsibility/example/Credentials.java delete mode 100644 src/refactoring_guru/mediator/example/components/InitList.java create mode 100644 src/refactoring_guru/mediator/example/components/List.java create mode 100644 src/refactoring_guru/memento/example/editor/Canvas.java delete mode 100644 src/refactoring_guru/memento/example/editor/Frame.java delete mode 100644 src/refactoring_guru/memento/example/editor/FrameMemento.java delete mode 100644 src/refactoring_guru/proxy/example/downloader/Renderer.java delete mode 100644 src/refactoring_guru/strategy/example/init/PaymentMethod.java delete mode 100644 src/refactoring_guru/strategy/example/init/Product.java diff --git a/README.md b/README.md index 332d61d..25603de 100644 --- a/README.md +++ b/README.md @@ -34,14 +34,16 @@ Here's a style guide which might help you to keep your changes consistent with o 1. All code should meet the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html) -2. Try to wrap the code at 80th's character. It helps to list the code on the website without scrollbars. +2. Try to hard wrap the code at 80th's character. It helps to list the code on the website without scrollbars. -3. Examples should match the following package convention: refactoring_guru.{pattern}.{example_name}. Example: +3. Examples should match following package convention: refactoring_guru.{pattern}.{example_name}. Example: ```java package refactoring_guru.factory_method.ui_example.buttons; - class Button { ... } + class Button { + ... + ``` 4. Places classes into separate files. @@ -50,24 +52,29 @@ Here's a style guide which might help you to keep your changes consistent with o ```java package refactoring_guru.factory_method.example.buttons; - class Button { ... } - + class Button { + ... + ``` + + ```java package refactoring_guru.factory_method.example.factories; import Button; - class Factory { ... } + class Factory { + ... + ``` 6. Comments may or may not have language tags in them, such as this: ```java /** * EN: All products families have the same varieties (MacOS/Windows). - *

+ * * This is a MacOS variant of a button. - *

+ * * RU: Все семейства продуктов имеют одни и те же вариации (MacOS/Windows). - *

+ * * Это вариант кнопки под MacOS. */ ``` diff --git a/src/refactoring_guru/abstract_factory/example/Demo.java b/src/refactoring_guru/abstract_factory/example/Demo.java index bbecf84..e732848 100644 --- a/src/refactoring_guru/abstract_factory/example/Demo.java +++ b/src/refactoring_guru/abstract_factory/example/Demo.java @@ -7,40 +7,34 @@ /** * EN: Demo class. Everything comes together here. - *

+ * * RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - public static void main(String[] args) { - Application app = configureApplication(); - app.paint(); - } /** - * EN: Configures the application with the appropriate GUI factory based on the OS. - * Dynamically selects the factory type depending on the current system configuration. - *

- * RU: Конфигурирует приложение с соответствующей фабрикой GUI на основе ОС. - * Динамически выбирает тип фабрики в зависимости от текущей системной конфигурации. + * EN: Application picks the factory type and creates it in run time + * (usually at initialization stage), depending on the configuration or + * environment variables. * - * @return An instance of the Application configured with the appropriate GUI factory. + * RU: Приложение выбирает тип и создаёт конкретные фабрики динамически + * исходя из конфигурации или окружения. */ private static Application configureApplication() { - GUIFactory factory = getOSGUIFactory(); - return new Application(factory); + Application app; + GUIFactory factory; + String osName = System.getProperty("os.name").toLowerCase(); + if (osName.contains("mac")) { + factory = new MacOSFactory(); + } else { + factory = new WindowsFactory(); + } + app = new Application(factory); + return app; } - /** - * EN: Determines the appropriate GUI factory based on the operating system. - * Checks the current system's OS property to decide which factory to instantiate. - *

- * RU: Определяет соответствующую фабрику GUI на основе операционной системы. - * Проверяет свойство OS текущей системы, чтобы решить, какую фабрику создать. - * - * @return The GUIFactory instance corresponding to the detected operating system. - */ - private static GUIFactory getOSGUIFactory() { - String osName = System.getProperty("os.name").toLowerCase(); - return osName.contains("mac") ? new MacOSFactory() : new WindowsFactory(); + public static void main(String[] args) { + Application app = configureApplication(); + app.paint(); } } diff --git a/src/refactoring_guru/abstract_factory/example/app/Application.java b/src/refactoring_guru/abstract_factory/example/app/Application.java index 1a4e7a7..06db4e9 100644 --- a/src/refactoring_guru/abstract_factory/example/app/Application.java +++ b/src/refactoring_guru/abstract_factory/example/app/Application.java @@ -7,22 +7,22 @@ /** * EN: Factory users don't care which concrete factory they use since they work * with factories and products through abstract interfaces. - *

+ * * RU: Код, использующий фабрику, не волнует с какой конкретно фабрикой он * работает. Все получатели продуктов работают с продуктами через абстрактный * интерфейс. */ public class Application { - private final Button button; - private final Checkbox checkbox; + private Button button; + private Checkbox checkbox; - public Application(GUIFactory factory) { - button = factory.createButton(); - checkbox = factory.createCheckbox(); - } + public Application(GUIFactory factory) { + button = factory.createButton(); + checkbox = factory.createCheckbox(); + } - public void paint() { - button.paint(); - checkbox.paint(); - } + public void paint() { + button.paint(); + checkbox.paint(); + } } diff --git a/src/refactoring_guru/abstract_factory/example/buttons/Button.java b/src/refactoring_guru/abstract_factory/example/buttons/Button.java index 1fb126d..ce81a4f 100644 --- a/src/refactoring_guru/abstract_factory/example/buttons/Button.java +++ b/src/refactoring_guru/abstract_factory/example/buttons/Button.java @@ -4,15 +4,15 @@ * EN: Abstract Factory assumes that you have several families of products, * structured into separate class hierarchies (Button/Checkbox). All products of * the same family have the common interface. - *

+ * * This is the common interface for buttons family. - *

+ * * RU: Паттерн предполагает, что у вас есть несколько семейств продуктов, * находящихся в отдельных иерархиях классов (Button/Checkbox). Продукты одного * семейства должны иметь общий интерфейс. - *

+ * * Это — общий интерфейс для семейства продуктов кнопок. */ public interface Button { - void paint(); + void paint(); } diff --git a/src/refactoring_guru/abstract_factory/example/buttons/MacOSButton.java b/src/refactoring_guru/abstract_factory/example/buttons/MacOSButton.java index 3f8e61b..23734f4 100644 --- a/src/refactoring_guru/abstract_factory/example/buttons/MacOSButton.java +++ b/src/refactoring_guru/abstract_factory/example/buttons/MacOSButton.java @@ -2,17 +2,17 @@ /** * EN: All products families have the same varieties (MacOS/Windows). - *

+ * * This is a MacOS variant of a button. - *

+ * * RU: Все семейства продуктов имеют одни и те же вариации (MacOS/Windows). - *

+ * * Это вариант кнопки под MacOS. */ public class MacOSButton implements Button { - @Override - public void paint() { - System.out.println("You have created MacOSButton."); - } + @Override + public void paint() { + System.out.println("You have created MacOSButton."); + } } diff --git a/src/refactoring_guru/abstract_factory/example/buttons/WindowsButton.java b/src/refactoring_guru/abstract_factory/example/buttons/WindowsButton.java index 93b7c77..00a8990 100644 --- a/src/refactoring_guru/abstract_factory/example/buttons/WindowsButton.java +++ b/src/refactoring_guru/abstract_factory/example/buttons/WindowsButton.java @@ -2,17 +2,17 @@ /** * EN: All products families have the same varieties (MacOS/Windows). - *

+ * * This is another variant of a button. - *

+ * * RU: Все семейства продуктов имеют одни и те же вариации (MacOS/Windows). - *

+ * * Это вариант кнопки под Windows. */ public class WindowsButton implements Button { - @Override - public void paint() { - System.out.println("You have created WindowsButton."); - } + @Override + public void paint() { + System.out.println("You have created WindowsButton."); + } } diff --git a/src/refactoring_guru/abstract_factory/example/checkboxes/Checkbox.java b/src/refactoring_guru/abstract_factory/example/checkboxes/Checkbox.java index 89938b4..df6853a 100644 --- a/src/refactoring_guru/abstract_factory/example/checkboxes/Checkbox.java +++ b/src/refactoring_guru/abstract_factory/example/checkboxes/Checkbox.java @@ -3,10 +3,10 @@ /** * EN: Checkboxes is the second product family. It has the same variants as * buttons. - *

+ * * RU: Чекбоксы — это второе семейство продуктов. Оно имеет те же вариации, что * и кнопки. */ public interface Checkbox { - void paint(); + void paint(); } diff --git a/src/refactoring_guru/abstract_factory/example/checkboxes/MacOSCheckbox.java b/src/refactoring_guru/abstract_factory/example/checkboxes/MacOSCheckbox.java index 59c86ca..22d5445 100644 --- a/src/refactoring_guru/abstract_factory/example/checkboxes/MacOSCheckbox.java +++ b/src/refactoring_guru/abstract_factory/example/checkboxes/MacOSCheckbox.java @@ -2,17 +2,17 @@ /** * EN: All products families have the same varieties (MacOS/Windows). - *

+ * * This is a variant of a checkbox. - *

+ * * RU: Все семейства продуктов имеют одинаковые вариации (MacOS/Windows). - *

+ * * Вариация чекбокса под MacOS. */ public class MacOSCheckbox implements Checkbox { - @Override - public void paint() { - System.out.println("You have created MacOSCheckbox."); - } + @Override + public void paint() { + System.out.println("You have created MacOSCheckbox."); + } } diff --git a/src/refactoring_guru/abstract_factory/example/checkboxes/WindowsCheckbox.java b/src/refactoring_guru/abstract_factory/example/checkboxes/WindowsCheckbox.java index cef39c6..e5387b4 100644 --- a/src/refactoring_guru/abstract_factory/example/checkboxes/WindowsCheckbox.java +++ b/src/refactoring_guru/abstract_factory/example/checkboxes/WindowsCheckbox.java @@ -2,17 +2,17 @@ /** * EN: All products families have the same varieties (MacOS/Windows). - *

+ * * This is another variant of a checkbox. - *

+ * * RU: Все семейства продуктов имеют одинаковые вариации (MacOS/Windows). - *

+ * * Вариация чекбокса под Windows. */ public class WindowsCheckbox implements Checkbox { - @Override - public void paint() { - System.out.println("You have created WindowsCheckbox."); - } + @Override + public void paint() { + System.out.println("You have created WindowsCheckbox."); + } } diff --git a/src/refactoring_guru/abstract_factory/example/factories/GUIFactory.java b/src/refactoring_guru/abstract_factory/example/factories/GUIFactory.java index 4bbbe7d..80708ef 100644 --- a/src/refactoring_guru/abstract_factory/example/factories/GUIFactory.java +++ b/src/refactoring_guru/abstract_factory/example/factories/GUIFactory.java @@ -5,11 +5,10 @@ /** * EN: Abstract factory knows about all (abstract) product types. - *

+ * * RU: Абстрактная фабрика знает обо всех (абстрактных) типах продуктов. */ public interface GUIFactory { - Button createButton(); - - Checkbox createCheckbox(); + Button createButton(); + Checkbox createCheckbox(); } diff --git a/src/refactoring_guru/abstract_factory/example/factories/MacOSFactory.java b/src/refactoring_guru/abstract_factory/example/factories/MacOSFactory.java index a3d1cf7..2b957ec 100644 --- a/src/refactoring_guru/abstract_factory/example/factories/MacOSFactory.java +++ b/src/refactoring_guru/abstract_factory/example/factories/MacOSFactory.java @@ -8,18 +8,18 @@ /** * EN: Each concrete factory extends basic factory and responsible for creating * products of a single variety. - *

+ * * RU: Каждая конкретная фабрика знает и создаёт только продукты своей вариации. */ public class MacOSFactory implements GUIFactory { - @Override - public Button createButton() { - return new MacOSButton(); - } + @Override + public Button createButton() { + return new MacOSButton(); + } - @Override - public Checkbox createCheckbox() { - return new MacOSCheckbox(); - } + @Override + public Checkbox createCheckbox() { + return new MacOSCheckbox(); + } } diff --git a/src/refactoring_guru/abstract_factory/example/factories/WindowsFactory.java b/src/refactoring_guru/abstract_factory/example/factories/WindowsFactory.java index f6d9403..d3475b3 100644 --- a/src/refactoring_guru/abstract_factory/example/factories/WindowsFactory.java +++ b/src/refactoring_guru/abstract_factory/example/factories/WindowsFactory.java @@ -8,18 +8,18 @@ /** * EN: Each concrete factory extends basic factory and responsible for creating * products of a single variety. - *

+ * * RU: Каждая конкретная фабрика знает и создаёт только продукты своей вариации. */ public class WindowsFactory implements GUIFactory { - @Override - public Button createButton() { - return new WindowsButton(); - } + @Override + public Button createButton() { + return new WindowsButton(); + } - @Override - public Checkbox createCheckbox() { - return new WindowsCheckbox(); - } + @Override + public Checkbox createCheckbox() { + return new WindowsCheckbox(); + } } diff --git a/src/refactoring_guru/adapter/example/Demo.java b/src/refactoring_guru/adapter/example/Demo.java index 762bb38..e886891 100644 --- a/src/refactoring_guru/adapter/example/Demo.java +++ b/src/refactoring_guru/adapter/example/Demo.java @@ -7,37 +7,36 @@ /** * EN: Somewhere in client code... - *

+ * * RU: Где-то в клиентском коде... */ public class Demo { - public static void main(String[] args) { - demonstrateRoundPegAndHole(); - demonstrateAdapterForSquarePeg(); - } + public static void main(String[] args) { + // EN: Round fits round, no surprise. + // + // RU: Круглое к круглому — всё работает. + RoundHole hole = new RoundHole(5); + RoundPeg rpeg = new RoundPeg(5); + if (hole.fits(rpeg)) { + System.out.println("Round peg r5 fits round hole r5."); + } - private static void demonstrateRoundPegAndHole() { - RoundHole roundHole = new RoundHole(5); - RoundPeg roundPeg = new RoundPeg(5); + SquarePeg smallSqPeg = new SquarePeg(2); + SquarePeg largeSqPeg = new SquarePeg(20); + // EN: hole.fits(smallSqPeg); // Won't compile. + // + // RU: hole.fits(smallSqPeg); // Не скомпилируется. - if (roundHole.fits(roundPeg)) { - System.out.println("Round peg r5 fits round hole r5."); + // EN: Adapter solves the problem. + // + // RU: Адаптер решит проблему. + SquarePegAdapter smallSqPegAdapter = new SquarePegAdapter(smallSqPeg); + SquarePegAdapter largeSqPegAdapter = new SquarePegAdapter(largeSqPeg); + if (hole.fits(smallSqPegAdapter)) { + System.out.println("Square peg w2 fits round hole r5."); + } + if (!hole.fits(largeSqPegAdapter)) { + System.out.println("Square peg w20 does not fit into round hole r5."); + } } - } - - private static void demonstrateAdapterForSquarePeg() { - RoundHole roundHole = new RoundHole(5); - - SquarePeg smallSqPeg = new SquarePeg(2); - SquarePegAdapter smallSqPegAdapter = new SquarePegAdapter(smallSqPeg); - if (roundHole.fits(smallSqPegAdapter)) { - System.out.println("Square peg w2 fits round hole r5."); - } - - SquarePeg largeSqPeg = new SquarePeg(20); - SquarePegAdapter largeSqPegAdapter = new SquarePegAdapter(largeSqPeg); - if (!roundHole.fits(largeSqPegAdapter)) { - System.out.println("Square peg w20 does not fit into round hole r5."); - } - } } diff --git a/src/refactoring_guru/adapter/example/adapters/SquarePegAdapter.java b/src/refactoring_guru/adapter/example/adapters/SquarePegAdapter.java index df6df48..7f9dfff 100644 --- a/src/refactoring_guru/adapter/example/adapters/SquarePegAdapter.java +++ b/src/refactoring_guru/adapter/example/adapters/SquarePegAdapter.java @@ -5,25 +5,24 @@ /** * EN: Adapter allows fitting square pegs into round holes. - *

+ * * RU: Адаптер позволяет использовать КвадратныеКолышки и КруглыеОтверстия * вместе. */ public class SquarePegAdapter extends RoundPeg { - private final SquarePeg squarePeg; + private SquarePeg peg; - public SquarePegAdapter(SquarePeg peg) { - this.squarePeg = peg; - } + public SquarePegAdapter(SquarePeg peg) { + this.peg = peg; + } - /** - * Calculate a minimum circle radius, which can fit this square peg - *

- * Рассчитываем минимальный радиус, в который пролезет этот колышек. - * @return result of computation - */ - @Override - public double getRadius() { - return (Math.sqrt(Math.pow((squarePeg.width() / 2), 2) * 2)); - } + @Override + public double getRadius() { + double result; + // EN: Calculate a minimum circle radius, which can fit this peg. + // + // RU: Рассчитываем минимальный радиус, в который пролезет этот колышек. + result = (Math.sqrt(Math.pow((peg.getWidth() / 2), 2) * 2)); + return result; + } } diff --git a/src/refactoring_guru/adapter/example/round/RoundHole.java b/src/refactoring_guru/adapter/example/round/RoundHole.java index 00d573e..35b2025 100644 --- a/src/refactoring_guru/adapter/example/round/RoundHole.java +++ b/src/refactoring_guru/adapter/example/round/RoundHole.java @@ -2,14 +2,23 @@ /** * EN: RoundHoles are compatible with RoundPegs. - *

+ * * RU: КруглоеОтверстие совместимо с КруглымиКолышками. */ -public record RoundHole(double radius) { +public class RoundHole { + private double radius; - public boolean fits(RoundPeg peg) { - boolean result; - result = (this.radius() >= peg.getRadius()); - return result; - } + public RoundHole(double radius) { + this.radius = radius; + } + + public double getRadius() { + return radius; + } + + public boolean fits(RoundPeg peg) { + boolean result; + result = (this.getRadius() >= peg.getRadius()); + return result; + } } diff --git a/src/refactoring_guru/adapter/example/round/RoundPeg.java b/src/refactoring_guru/adapter/example/round/RoundPeg.java index 50565a0..d103827 100644 --- a/src/refactoring_guru/adapter/example/round/RoundPeg.java +++ b/src/refactoring_guru/adapter/example/round/RoundPeg.java @@ -2,20 +2,19 @@ /** * EN: RoundPegs are compatible with RoundHoles. - *

+ * * RU: КруглыеКолышки совместимы с КруглымиОтверстиями. */ public class RoundPeg { - private double radius; + private double radius; - public RoundPeg() { - } + public RoundPeg() {} - public RoundPeg(double radius) { - this.radius = radius; - } + public RoundPeg(double radius) { + this.radius = radius; + } - public double getRadius() { - return radius; - } + public double getRadius() { + return radius; + } } diff --git a/src/refactoring_guru/adapter/example/square/SquarePeg.java b/src/refactoring_guru/adapter/example/square/SquarePeg.java index 033639b..57221a2 100644 --- a/src/refactoring_guru/adapter/example/square/SquarePeg.java +++ b/src/refactoring_guru/adapter/example/square/SquarePeg.java @@ -3,16 +3,25 @@ /** * EN: SquarePegs are not compatible with RoundHoles (they were implemented by * previous development team). But we have to integrate them into our program. - *

+ * * RU: КвадратныеКолышки несовместимы с КруглымиОтверстиями (они остались в * проекте после бывших разработчиков). Но мы должны как-то интегрировать их в * нашу систему. */ -public record SquarePeg(double width) { +public class SquarePeg { + private double width; - public double getSquare() { - double result; - result = Math.pow(this.width, 2); - return result; - } + public SquarePeg(double width) { + this.width = width; + } + + public double getWidth() { + return width; + } + + public double getSquare() { + double result; + result = Math.pow(this.width, 2); + return result; + } } diff --git a/src/refactoring_guru/bridge/example/Demo.java b/src/refactoring_guru/bridge/example/Demo.java index 081bf00..6ce44d0 100644 --- a/src/refactoring_guru/bridge/example/Demo.java +++ b/src/refactoring_guru/bridge/example/Demo.java @@ -7,21 +7,21 @@ import refactoring_guru.bridge.example.remotes.BasicRemote; public class Demo { - public static void main(String[] args) { - testDevice(new Tv()); - testDevice(new Radio()); - } + public static void main(String[] args) { + testDevice(new Tv()); + testDevice(new Radio()); + } - public static void testDevice(Device device) { - System.out.println("Tests with basic remote."); - BasicRemote basicRemote = new BasicRemote(device); - basicRemote.power(); - device.printStatus(); + public static void testDevice(Device device) { + System.out.println("Tests with basic remote."); + BasicRemote basicRemote = new BasicRemote(device); + basicRemote.power(); + device.printStatus(); - System.out.println("Tests with advanced remote."); - AdvancedRemote advancedRemote = new AdvancedRemote(device); - advancedRemote.power(); - advancedRemote.mute(); - device.printStatus(); - } + System.out.println("Tests with advanced remote."); + AdvancedRemote advancedRemote = new AdvancedRemote(device); + advancedRemote.power(); + advancedRemote.mute(); + device.printStatus(); + } } diff --git a/src/refactoring_guru/bridge/example/devices/Device.java b/src/refactoring_guru/bridge/example/devices/Device.java index f693e99..1520dd3 100644 --- a/src/refactoring_guru/bridge/example/devices/Device.java +++ b/src/refactoring_guru/bridge/example/devices/Device.java @@ -1,19 +1,19 @@ package refactoring_guru.bridge.example.devices; public interface Device { - boolean isEnabled(); + boolean isEnabled(); - void enable(); + void enable(); - void disable(); + void disable(); - int getVolume(); + int getVolume(); - void setVolume(int percent); + void setVolume(int percent); - int getChannel(); + int getChannel(); - void setChannel(int channel); + void setChannel(int channel); - void printStatus(); + void printStatus(); } diff --git a/src/refactoring_guru/bridge/example/devices/Radio.java b/src/refactoring_guru/bridge/example/devices/Radio.java index 0b53929..b0b227a 100644 --- a/src/refactoring_guru/bridge/example/devices/Radio.java +++ b/src/refactoring_guru/bridge/example/devices/Radio.java @@ -1,54 +1,58 @@ package refactoring_guru.bridge.example.devices; public class Radio implements Device { - private boolean on = false; - private int volume = 30; - private int channel = 1; - - @Override - public boolean isEnabled() { - return on; - } - - @Override - public void enable() { - on = true; - } - - @Override - public void disable() { - on = false; - } - - @Override - public int getVolume() { - return volume; - } - - @Override - public void setVolume(int volume) { - if (volume > 100) { - this.volume = 100; - } else this.volume = Math.max(volume, 0); - } - - @Override - public int getChannel() { - return channel; - } - - @Override - public void setChannel(int channel) { - this.channel = channel; - } - - @Override - public void printStatus() { - System.out.println("------------------------------------"); - System.out.println("| I'm radio."); - System.out.println("| I'm " + (on ? "enabled" : "disabled")); - System.out.println("| Current volume is " + volume + "%"); - System.out.println("| Current channel is " + channel); - System.out.println("------------------------------------\n"); - } + private boolean on = false; + private int volume = 30; + private int channel = 1; + + @Override + public boolean isEnabled() { + return on; + } + + @Override + public void enable() { + on = true; + } + + @Override + public void disable() { + on = false; + } + + @Override + public int getVolume() { + return volume; + } + + @Override + public void setVolume(int volume) { + if (volume > 100) { + this.volume = 100; + } else if (volume < 0) { + this.volume = 0; + } else { + this.volume = volume; + } + } + + @Override + public int getChannel() { + return channel; + } + + @Override + public void setChannel(int channel) { + this.channel = channel; + } + + @Override + public void printStatus() { + System.out.println("------------------------------------"); + System.out.println("| I'm radio."); + System.out.println("| I'm " + (on ? "enabled" : "disabled")); + System.out.println("| Current volume is " + volume + "%"); + System.out.println("| Current channel is " + channel); + System.out.println("------------------------------------\n"); + } } diff --git a/src/refactoring_guru/bridge/example/devices/Tv.java b/src/refactoring_guru/bridge/example/devices/Tv.java index 9477463..b3705cd 100644 --- a/src/refactoring_guru/bridge/example/devices/Tv.java +++ b/src/refactoring_guru/bridge/example/devices/Tv.java @@ -1,54 +1,58 @@ package refactoring_guru.bridge.example.devices; public class Tv implements Device { - private boolean on = false; - private int volume = 30; - private int channel = 1; - - @Override - public boolean isEnabled() { - return on; - } - - @Override - public void enable() { - on = true; - } - - @Override - public void disable() { - on = false; - } - - @Override - public int getVolume() { - return volume; - } - - @Override - public void setVolume(int volume) { - if (volume > 100) { - this.volume = 100; - } else this.volume = Math.max(volume, 0); - } - - @Override - public int getChannel() { - return channel; - } - - @Override - public void setChannel(int channel) { - this.channel = channel; - } - - @Override - public void printStatus() { - System.out.println("------------------------------------"); - System.out.println("| I'm TV set."); - System.out.println("| I'm " + (on ? "enabled" : "disabled")); - System.out.println("| Current volume is " + volume + "%"); - System.out.println("| Current channel is " + channel); - System.out.println("------------------------------------\n"); - } + private boolean on = false; + private int volume = 30; + private int channel = 1; + + @Override + public boolean isEnabled() { + return on; + } + + @Override + public void enable() { + on = true; + } + + @Override + public void disable() { + on = false; + } + + @Override + public int getVolume() { + return volume; + } + + @Override + public void setVolume(int volume) { + if (volume > 100) { + this.volume = 100; + } else if (volume < 0) { + this.volume = 0; + } else { + this.volume = volume; + } + } + + @Override + public int getChannel() { + return channel; + } + + @Override + public void setChannel(int channel) { + this.channel = channel; + } + + @Override + public void printStatus() { + System.out.println("------------------------------------"); + System.out.println("| I'm TV set."); + System.out.println("| I'm " + (on ? "enabled" : "disabled")); + System.out.println("| Current volume is " + volume + "%"); + System.out.println("| Current channel is " + channel); + System.out.println("------------------------------------\n"); + } } diff --git a/src/refactoring_guru/bridge/example/remotes/AdvancedRemote.java b/src/refactoring_guru/bridge/example/remotes/AdvancedRemote.java index 437fadf..17c7155 100644 --- a/src/refactoring_guru/bridge/example/remotes/AdvancedRemote.java +++ b/src/refactoring_guru/bridge/example/remotes/AdvancedRemote.java @@ -4,12 +4,12 @@ public class AdvancedRemote extends BasicRemote { - public AdvancedRemote(Device device) { - super.device = device; - } - - public void mute() { - System.out.println("Remote: mute"); - device.setVolume(0); - } + public AdvancedRemote(Device device) { + super.device = device; + } + + public void mute() { + System.out.println("Remote: mute"); + device.setVolume(0); + } } diff --git a/src/refactoring_guru/bridge/example/remotes/BasicRemote.java b/src/refactoring_guru/bridge/example/remotes/BasicRemote.java index c0016d8..5f9dcb4 100644 --- a/src/refactoring_guru/bridge/example/remotes/BasicRemote.java +++ b/src/refactoring_guru/bridge/example/remotes/BasicRemote.java @@ -3,46 +3,45 @@ import refactoring_guru.bridge.example.devices.Device; public class BasicRemote implements Remote { - protected Device device; - - public BasicRemote() { - } - - public BasicRemote(Device device) { - this.device = device; - } - - @Override - public void power() { - System.out.println("Remote: power toggle"); - if (device.isEnabled()) { - device.disable(); - } else { - device.enable(); + protected Device device; + + public BasicRemote() {} + + public BasicRemote(Device device) { + this.device = device; + } + + @Override + public void power() { + System.out.println("Remote: power toggle"); + if (device.isEnabled()) { + device.disable(); + } else { + device.enable(); + } + } + + @Override + public void volumeDown() { + System.out.println("Remote: volume down"); + device.setVolume(device.getVolume() - 10); + } + + @Override + public void volumeUp() { + System.out.println("Remote: volume up"); + device.setVolume(device.getVolume() + 10); + } + + @Override + public void channelDown() { + System.out.println("Remote: channel down"); + device.setChannel(device.getChannel() - 1); + } + + @Override + public void channelUp() { + System.out.println("Remote: channel up"); + device.setChannel(device.getChannel() + 1); } - } - - @Override - public void volumeDown() { - System.out.println("Remote: volume down"); - device.setVolume(device.getVolume() - 10); - } - - @Override - public void volumeUp() { - System.out.println("Remote: volume up"); - device.setVolume(device.getVolume() + 10); - } - - @Override - public void channelDown() { - System.out.println("Remote: channel down"); - device.setChannel(device.getChannel() - 1); - } - - @Override - public void channelUp() { - System.out.println("Remote: channel up"); - device.setChannel(device.getChannel() + 1); - } } diff --git a/src/refactoring_guru/bridge/example/remotes/Remote.java b/src/refactoring_guru/bridge/example/remotes/Remote.java index dd7288d..0f5e78b 100644 --- a/src/refactoring_guru/bridge/example/remotes/Remote.java +++ b/src/refactoring_guru/bridge/example/remotes/Remote.java @@ -1,13 +1,13 @@ package refactoring_guru.bridge.example.remotes; public interface Remote { - void power(); + void power(); - void volumeDown(); + void volumeDown(); - void volumeUp(); + void volumeUp(); - void channelDown(); + void channelDown(); - void channelUp(); + void channelUp(); } diff --git a/src/refactoring_guru/builder/example/Demo.java b/src/refactoring_guru/builder/example/Demo.java index f68799f..6d3f348 100644 --- a/src/refactoring_guru/builder/example/Demo.java +++ b/src/refactoring_guru/builder/example/Demo.java @@ -8,30 +8,42 @@ /** * EN: Demo class. Everything comes together here. - * EN: Director gets the concrete builder object from the client - * (application code). That's because the application knows better which - * builder to use to get a specific product. - *

+ * * RU: Демо-класс. Здесь всё сводится воедино. - * RU: Директор получает объект конкретного строителя от клиента - * (приложения). Приложение само знает какой строитель использовать, - * чтобы получить нужный продукт. */ public class Demo { - public static void main(String[] args) { - Director director = new Director(); + public static void main(String[] args) { + Director director = new Director(); - CarBuilder builder = new CarBuilder(); - director.constructSportsCar(builder); + // EN: Director gets the concrete builder object from the client + // (application code). That's because application knows better which + // builder to use to get a specific product. + // + // RU: Директор получает объект конкретного строителя от клиента + // (приложения). Приложение само знает какой строитель использовать, + // чтобы получить нужный продукт. + CarBuilder builder = new CarBuilder(); + director.constructSportsCar(builder); - Car car = builder.getResult(); - System.out.println("Car built:\n" + car.getCarType()); + // EN: The final product is often retrieved from a builder object, since + // Director is not aware and not dependent on concrete builders and + // products. + // + // RU: Готовый продукт возвращает строитель, так как Директор чаще всего + // не знает и не зависит от конкретных классов строителей и продуктов. + Car car = builder.getResult(); + System.out.println("Car built:\n" + car.getCarType()); - CarManualBuilder manualBuilder = new CarManualBuilder(); - director.constructSportsCar(manualBuilder); - Manual carManual = manualBuilder.getResult(); - System.out.println("\nCar manual built:\n" + carManual.print()); - } + CarManualBuilder manualBuilder = new CarManualBuilder(); + + // EN: Director may know several building recipes. + // + // RU: Директор может знать больше одного рецепта строительства. + director.constructSportsCar(manualBuilder); + Manual carManual = manualBuilder.getResult(); + System.out.println("\nCar manual built:\n" + carManual.print()); + } + } diff --git a/src/refactoring_guru/builder/example/builders/Builder.java b/src/refactoring_guru/builder/example/builders/Builder.java index 33770da..f81dd60 100644 --- a/src/refactoring_guru/builder/example/builders/Builder.java +++ b/src/refactoring_guru/builder/example/builders/Builder.java @@ -8,20 +8,15 @@ /** * EN: Builder interface defines all possible ways to configure a product. - *

+ * * RU: Интерфейс Строителя объявляет все возможные этапы и шаги конфигурации * продукта. */ public interface Builder { - void setCarType(CarType type); - - void setSeats(int seats); - - void setEngine(Engine engine); - - void setTransmission(Transmission transmission); - - void setTripComputer(TripComputer tripComputer); - - void setGPSNavigator(GPSNavigator gpsNavigator); + void setCarType(CarType type); + void setSeats(int seats); + void setEngine(Engine engine); + void setTransmission(Transmission transmission); + void setTripComputer(TripComputer tripComputer); + void setGPSNavigator(GPSNavigator gpsNavigator); } diff --git a/src/refactoring_guru/builder/example/builders/CarBuilder.java b/src/refactoring_guru/builder/example/builders/CarBuilder.java index ed3c4e9..2f618f3 100644 --- a/src/refactoring_guru/builder/example/builders/CarBuilder.java +++ b/src/refactoring_guru/builder/example/builders/CarBuilder.java @@ -9,47 +9,47 @@ /** * EN: Concrete builders implement steps defined in the common interface. - *

+ * * RU: Конкретные строители реализуют шаги, объявленные в общем интерфейсе. */ public class CarBuilder implements Builder { - private CarType type; - private int seats; - private Engine engine; - private Transmission transmission; - private TripComputer tripComputer; - private GPSNavigator gpsNavigator; - - public void setCarType(CarType type) { - this.type = type; - } - - @Override - public void setSeats(int seats) { - this.seats = seats; - } - - @Override - public void setEngine(Engine engine) { - this.engine = engine; - } - - @Override - public void setTransmission(Transmission transmission) { - this.transmission = transmission; - } - - @Override - public void setTripComputer(TripComputer tripComputer) { - this.tripComputer = tripComputer; - } - - @Override - public void setGPSNavigator(GPSNavigator gpsNavigator) { - this.gpsNavigator = gpsNavigator; - } - - public Car getResult() { - return new Car(type, seats, engine, transmission, tripComputer, gpsNavigator); - } + private CarType type; + private int seats; + private Engine engine; + private Transmission transmission; + private TripComputer tripComputer; + private GPSNavigator gpsNavigator; + + public void setCarType(CarType type) { + this.type = type; + } + + @Override + public void setSeats(int seats) { + this.seats = seats; + } + + @Override + public void setEngine(Engine engine) { + this.engine = engine; + } + + @Override + public void setTransmission(Transmission transmission) { + this.transmission = transmission; + } + + @Override + public void setTripComputer(TripComputer tripComputer) { + this.tripComputer = tripComputer; + } + + @Override + public void setGPSNavigator(GPSNavigator gpsNavigator) { + this.gpsNavigator = gpsNavigator; + } + + public Car getResult() { + return new Car(type, seats, engine, transmission, tripComputer, gpsNavigator); + } } diff --git a/src/refactoring_guru/builder/example/builders/CarManualBuilder.java b/src/refactoring_guru/builder/example/builders/CarManualBuilder.java index 11083bd..48ad164 100644 --- a/src/refactoring_guru/builder/example/builders/CarManualBuilder.java +++ b/src/refactoring_guru/builder/example/builders/CarManualBuilder.java @@ -8,59 +8,59 @@ import refactoring_guru.builder.example.components.TripComputer; /** - * EN: Unlike other creation patterns, Builder can construct unrelated + * EN: Unlike other creational patterns, Builder can construct unrelated * products, which don't have the common interface. - *

+ * * In this case we build a user manual for a car, using the same steps as we * built a car. This allows to produce manuals for specific car models, * configured with different features. - *

+ * * RU: В отличие от других создающих паттернов, Строители могут создавать * совершенно разные продукты, не имеющие общего интерфейса. - *

+ * * В данном случае мы производим руководство пользователя автомобиля с помощью * тех же шагов, что и сами автомобили. Это устройство позволит создавать * руководства под конкретные модели автомобилей, содержащие те или иные фичи. */ -public class CarManualBuilder implements Builder { - private CarType type; - private int seats; - private Engine engine; - private Transmission transmission; - private TripComputer tripComputer; - private GPSNavigator gpsNavigator; +public class CarManualBuilder implements Builder{ + private CarType type; + private int seats; + private Engine engine; + private Transmission transmission; + private TripComputer tripComputer; + private GPSNavigator gpsNavigator; - @Override - public void setCarType(CarType type) { - this.type = type; - } + @Override + public void setCarType(CarType type) { + this.type = type; + } - @Override - public void setSeats(int seats) { - this.seats = seats; - } + @Override + public void setSeats(int seats) { + this.seats = seats; + } - @Override - public void setEngine(Engine engine) { - this.engine = engine; - } + @Override + public void setEngine(Engine engine) { + this.engine = engine; + } - @Override - public void setTransmission(Transmission transmission) { - this.transmission = transmission; - } + @Override + public void setTransmission(Transmission transmission) { + this.transmission = transmission; + } - @Override - public void setTripComputer(TripComputer tripComputer) { - this.tripComputer = tripComputer; - } + @Override + public void setTripComputer(TripComputer tripComputer) { + this.tripComputer = tripComputer; + } - @Override - public void setGPSNavigator(GPSNavigator gpsNavigator) { - this.gpsNavigator = gpsNavigator; - } + @Override + public void setGPSNavigator(GPSNavigator gpsNavigator) { + this.gpsNavigator = gpsNavigator; + } - public Manual getResult() { - return new Manual(type, seats, engine, transmission, tripComputer, gpsNavigator); - } + public Manual getResult() { + return new Manual(type, seats, engine, transmission, tripComputer, gpsNavigator); + } } diff --git a/src/refactoring_guru/builder/example/cars/Car.java b/src/refactoring_guru/builder/example/cars/Car.java index 969b221..e4b6d23 100644 --- a/src/refactoring_guru/builder/example/cars/Car.java +++ b/src/refactoring_guru/builder/example/cars/Car.java @@ -7,60 +7,60 @@ /** * EN: Car is a product class. - *

+ * * RU: Автомобиль — это класс продукта. */ public class Car { - private final CarType carType; - private final int seats; - private final Engine engine; - private final Transmission transmission; - private final TripComputer tripComputer; - private final GPSNavigator gpsNavigator; - private double fuel = 0; + private final CarType carType; + private final int seats; + private final Engine engine; + private final Transmission transmission; + private final TripComputer tripComputer; + private final GPSNavigator gpsNavigator; + private double fuel = 0; - public Car(CarType carType, int seats, Engine engine, Transmission transmission, - TripComputer tripComputer, GPSNavigator gpsNavigator) { - this.carType = carType; - this.seats = seats; - this.engine = engine; - this.transmission = transmission; - this.tripComputer = tripComputer; - if (this.tripComputer != null) { - this.tripComputer.setCar(this); + public Car(CarType carType, int seats, Engine engine, Transmission transmission, + TripComputer tripComputer, GPSNavigator gpsNavigator) { + this.carType = carType; + this.seats = seats; + this.engine = engine; + this.transmission = transmission; + this.tripComputer = tripComputer; + if (this.tripComputer != null) { + this.tripComputer.setCar(this); + } + this.gpsNavigator = gpsNavigator; } - this.gpsNavigator = gpsNavigator; - } - public CarType getCarType() { - return carType; - } + public CarType getCarType() { + return carType; + } - public double getFuel() { - return fuel; - } + public double getFuel() { + return fuel; + } - public void setFuel(double fuel) { - this.fuel = fuel; - } + public void setFuel(double fuel) { + this.fuel = fuel; + } - public int getSeats() { - return seats; - } + public int getSeats() { + return seats; + } - public Engine getEngine() { - return engine; - } + public Engine getEngine() { + return engine; + } - public Transmission getTransmission() { - return transmission; - } + public Transmission getTransmission() { + return transmission; + } - public TripComputer getTripComputer() { - return tripComputer; - } + public TripComputer getTripComputer() { + return tripComputer; + } - public GPSNavigator getGpsNavigator() { - return gpsNavigator; - } + public GPSNavigator getGpsNavigator() { + return gpsNavigator; + } } diff --git a/src/refactoring_guru/builder/example/cars/CarType.java b/src/refactoring_guru/builder/example/cars/CarType.java index 81cc741..2f8ee89 100644 --- a/src/refactoring_guru/builder/example/cars/CarType.java +++ b/src/refactoring_guru/builder/example/cars/CarType.java @@ -1,5 +1,5 @@ package refactoring_guru.builder.example.cars; public enum CarType { - CITY_CAR, SPORTS_CAR, SUV + CITY_CAR, SPORTS_CAR, SUV } diff --git a/src/refactoring_guru/builder/example/cars/Manual.java b/src/refactoring_guru/builder/example/cars/Manual.java index 236366e..466ea8d 100644 --- a/src/refactoring_guru/builder/example/cars/Manual.java +++ b/src/refactoring_guru/builder/example/cars/Manual.java @@ -8,36 +8,44 @@ /** * EN: Car manual is another product. Note that it does not have the same * ancestor as a Car. They are not related. - *

+ * * RU: Руководство автомобиля — это второй продукт. Заметьте, что руководство и * сам автомобиль не имеют общего родительского класса. По сути, они независимы. */ public class Manual { - private final CarType carType; - private final int seats; - private final Engine engine; - private final Transmission transmission; - private final TripComputer tripComputer; - private final GPSNavigator gpsNavigator; + private final CarType carType; + private final int seats; + private final Engine engine; + private final Transmission transmission; + private final TripComputer tripComputer; + private final GPSNavigator gpsNavigator; - public Manual(CarType carType, int seats, Engine engine, Transmission transmission, - TripComputer tripComputer, GPSNavigator gpsNavigator) { - this.carType = carType; - this.seats = seats; - this.engine = engine; - this.transmission = transmission; - this.tripComputer = tripComputer; - this.gpsNavigator = gpsNavigator; - } + public Manual(CarType carType, int seats, Engine engine, Transmission transmission, + TripComputer tripComputer, GPSNavigator gpsNavigator) { + this.carType = carType; + this.seats = seats; + this.engine = engine; + this.transmission = transmission; + this.tripComputer = tripComputer; + this.gpsNavigator = gpsNavigator; + } - public String print() { - return String.join("\n", - "Type of car: " + carType, - "Count of seats: " + seats, - "Engine: volume - " + engine.getVolume() + "; mileage - " + engine.getMileage(), - "Transmission: " + transmission, - "Trip Computer: " + (tripComputer != null ? "Functional" : "N/A"), - "GPS Navigator: " + (gpsNavigator != null ? "Functional" : "N/A") - ); - } + public String print() { + String info = ""; + info += "Type of car: " + carType + "\n"; + info += "Count of seats: " + seats + "\n"; + info += "Engine: volume - " + engine.getVolume() + "; mileage - " + engine.getMileage() + "\n"; + info += "Transmission: " + transmission + "\n"; + if (this.tripComputer != null) { + info += "Trip Computer: Functional" + "\n"; + } else { + info += "Trip Computer: N/A" + "\n"; + } + if (this.gpsNavigator != null) { + info += "GPS Navigator: Functional" + "\n"; + } else { + info += "GPS Navigator: N/A" + "\n"; + } + return info; + } } diff --git a/src/refactoring_guru/builder/example/components/Engine.java b/src/refactoring_guru/builder/example/components/Engine.java index f26dbc9..41956cc 100644 --- a/src/refactoring_guru/builder/example/components/Engine.java +++ b/src/refactoring_guru/builder/example/components/Engine.java @@ -2,44 +2,44 @@ /** * EN: Just another feature of a car. - *

+ * * RU: Одна из фишек автомобиля. */ public class Engine { - private final double volume; - private double mileage; - private boolean started; - - public Engine(double volume, double mileage) { - this.volume = volume; - this.mileage = mileage; - } - - public void on() { - started = true; - } - - public void off() { - started = false; - } - - public boolean isStarted() { - return started; - } - - public void go(double mileage) { - if (started) { - this.mileage += mileage; - } else { - System.err.println("Cannot go(), you must start engine first!"); + private final double volume; + private double mileage; + private boolean started; + + public Engine(double volume, double mileage) { + this.volume = volume; + this.mileage = mileage; + } + + public void on() { + started = true; } - } - public double getVolume() { - return volume; - } + public void off() { + started = false; + } + + public boolean isStarted() { + return started; + } - public double getMileage() { - return mileage; - } + public void go(double mileage) { + if (started) { + this.mileage += mileage; + } else { + System.err.println("Cannot go(), you must start engine first!"); + } + } + + public double getVolume() { + return volume; + } + + public double getMileage() { + return mileage; + } } diff --git a/src/refactoring_guru/builder/example/components/GPSNavigator.java b/src/refactoring_guru/builder/example/components/GPSNavigator.java index 8929488..68f4cc1 100644 --- a/src/refactoring_guru/builder/example/components/GPSNavigator.java +++ b/src/refactoring_guru/builder/example/components/GPSNavigator.java @@ -2,21 +2,21 @@ /** * EN: Just another feature of a car. - *

+ * * RU: Одна из фишек автомобиля. */ public class GPSNavigator { - private final String route; + private String route; - public GPSNavigator() { - this.route = "221b, Baker Street, London to Scotland Yard, 8-10 Broadway, London"; - } + public GPSNavigator() { + this.route = "221b, Baker Street, London to Scotland Yard, 8-10 Broadway, London"; + } - public GPSNavigator(String manualRoute) { - this.route = manualRoute; - } + public GPSNavigator(String manualRoute) { + this.route = manualRoute; + } - public String getRoute() { - return route; - } + public String getRoute() { + return route; + } } diff --git a/src/refactoring_guru/builder/example/components/Transmission.java b/src/refactoring_guru/builder/example/components/Transmission.java index 6a84893..2815235 100644 --- a/src/refactoring_guru/builder/example/components/Transmission.java +++ b/src/refactoring_guru/builder/example/components/Transmission.java @@ -2,9 +2,9 @@ /** * EN: Just another feature of a car. - *

+ * * RU: Одна из фишек автомобиля. */ public enum Transmission { - SINGLE_SPEED, MANUAL, AUTOMATIC, SEMI_AUTOMATIC + SINGLE_SPEED, MANUAL, AUTOMATIC, SEMI_AUTOMATIC } diff --git a/src/refactoring_guru/builder/example/components/TripComputer.java b/src/refactoring_guru/builder/example/components/TripComputer.java index ab36aa1..5617845 100644 --- a/src/refactoring_guru/builder/example/components/TripComputer.java +++ b/src/refactoring_guru/builder/example/components/TripComputer.java @@ -4,26 +4,26 @@ /** * EN: Just another feature of a car. - *

+ * * RU: Одна из фишек автомобиля. */ public class TripComputer { - private Car car; + private Car car; - public void setCar(Car car) { - this.car = car; - } + public void setCar(Car car) { + this.car = car; + } - public void showFuelLevel() { - System.out.println("Fuel level: " + car.getFuel()); - } + public void showFuelLevel() { + System.out.println("Fuel level: " + car.getFuel()); + } - public void showStatus() { - if (this.car.getEngine().isStarted()) { - System.out.println("Car is started"); - } else { - System.out.println("The Car isn't started"); + public void showStatus() { + if (this.car.getEngine().isStarted()) { + System.out.println("Car is started"); + } else { + System.out.println("Car isn't started"); + } } - } } diff --git a/src/refactoring_guru/builder/example/director/Director.java b/src/refactoring_guru/builder/example/director/Director.java index 49baee2..f5f8284 100644 --- a/src/refactoring_guru/builder/example/director/Director.java +++ b/src/refactoring_guru/builder/example/director/Director.java @@ -11,36 +11,36 @@ * EN: Director defines the order of building steps. It works with a builder * object through common Builder interface. Therefore it may not know what * product is being built. - *

+ * * RU: Директор знает в какой последовательности заставлять работать строителя. * Он работает с ним через общий интерфейс Строителя. Из-за этого, он может не * знать какой конкретно продукт сейчас строится. */ public class Director { - public void constructSportsCar(Builder builder) { - builder.setCarType(CarType.SPORTS_CAR); - builder.setSeats(2); - builder.setEngine(new Engine(3.0, 0)); - builder.setTransmission(Transmission.SEMI_AUTOMATIC); - builder.setTripComputer(new TripComputer()); - builder.setGPSNavigator(new GPSNavigator()); - } + public void constructSportsCar(Builder builder) { + builder.setCarType(CarType.SPORTS_CAR); + builder.setSeats(2); + builder.setEngine(new Engine(3.0, 0)); + builder.setTransmission(Transmission.SEMI_AUTOMATIC); + builder.setTripComputer(new TripComputer()); + builder.setGPSNavigator(new GPSNavigator()); + } - public void constructCityCar(Builder builder) { - builder.setCarType(CarType.CITY_CAR); - builder.setSeats(2); - builder.setEngine(new Engine(1.2, 0)); - builder.setTransmission(Transmission.AUTOMATIC); - builder.setTripComputer(new TripComputer()); - builder.setGPSNavigator(new GPSNavigator()); - } + public void constructCityCar(Builder builder) { + builder.setCarType(CarType.CITY_CAR); + builder.setSeats(2); + builder.setEngine(new Engine(1.2, 0)); + builder.setTransmission(Transmission.AUTOMATIC); + builder.setTripComputer(new TripComputer()); + builder.setGPSNavigator(new GPSNavigator()); + } - public void constructSUV(Builder builder) { - builder.setCarType(CarType.SUV); - builder.setSeats(4); - builder.setEngine(new Engine(2.5, 0)); - builder.setTransmission(Transmission.MANUAL); - builder.setGPSNavigator(new GPSNavigator()); - } + public void constructSUV(Builder builder) { + builder.setCarType(CarType.SUV); + builder.setSeats(4); + builder.setEngine(new Engine(2.5, 0)); + builder.setTransmission(Transmission.MANUAL); + builder.setGPSNavigator(new GPSNavigator()); + } } diff --git a/src/refactoring_guru/chain_of_responsibility/example/Credentials.java b/src/refactoring_guru/chain_of_responsibility/example/Credentials.java deleted file mode 100644 index daa41ad..0000000 --- a/src/refactoring_guru/chain_of_responsibility/example/Credentials.java +++ /dev/null @@ -1,4 +0,0 @@ -package refactoring_guru.chain_of_responsibility.example; - -public record Credentials(String email, String password) { -} diff --git a/src/refactoring_guru/chain_of_responsibility/example/Demo.java b/src/refactoring_guru/chain_of_responsibility/example/Demo.java index 42d0bf8..1934e61 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/Demo.java +++ b/src/refactoring_guru/chain_of_responsibility/example/Demo.java @@ -9,52 +9,48 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.util.Optional; /** * EN: Demo class. Everything comes together here. - *

+ * * RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - private static Server server; - - public static void main(String[] args) { - init(); - while(!attemptLogin()) { - System.out.println("Error reading input. Try again."); - } - } - - private static void init() { - server = new Server(); - server.register("admin@example.com", "admin_pass"); - server.register("user@example.com", "user_pass"); - - Middleware middleware = Middleware.link( + private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + private static Server server; + + private static void init() { + server = new Server(); + server.register("admin@example.com", "admin_pass"); + server.register("user@example.com", "user_pass"); + + // EN: All checks are linked. Client can build various chains using the + // same components. + // + // RU: Проверки связаны в одну цепь. Клиент может строить различные + // цепи, используя одни и те же компоненты. + Middleware middleware = Middleware.link( new ThrottlingMiddleware(2), new UserExistsMiddleware(server), new RoleCheckMiddleware() - ); - - server.setMiddleware(middleware); - } - - private static boolean attemptLogin() { - return Optional.ofNullable(getCredentials()) - .map(credentials -> server.logIn(credentials.email(), credentials.password())) - .orElse(false); - } - - private static Credentials getCredentials() { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { - System.out.print("Enter email: "); - String email = reader.readLine(); - System.out.print("Input password: "); - String password = reader.readLine(); - return new Credentials(email, password); - } catch (IOException e) { - return null; + ); + + // EN: Server gets a chain from client code. + // + // RU: Сервер получает цепочку от клиентского кода. + server.setMiddleware(middleware); + } + + public static void main(String[] args) throws IOException { + init(); + + boolean success; + do { + System.out.print("Enter email: "); + String email = reader.readLine(); + System.out.print("Input password: "); + String password = reader.readLine(); + success = server.logIn(email, password); + } while (!success); } - } } diff --git a/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java b/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java index 8e1d1bf..bd4d7bf 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java +++ b/src/refactoring_guru/chain_of_responsibility/example/middleware/Middleware.java @@ -2,41 +2,44 @@ /** * EN: Base middleware class. - *

+ * * RU: Базовый класс цепочки. */ public abstract class Middleware { - private Middleware next; + private Middleware next; - /** - * EN: Builds chains of middleware objects. - *

- * RU: Помогает строить цепь из объектов-проверок. - */ - public static Middleware link(Middleware first, Middleware... chain) { - Middleware head = first; - for (Middleware nextInChain : chain) { - head.next = nextInChain; - head = nextInChain; + /** + * EN: Builds chains of middleware objects. + * + * RU: Помогает строить цепь из объектов-проверок. + */ + public static Middleware link(Middleware first, Middleware... chain) { + Middleware head = first; + for (Middleware nextInChain: chain) { + head.next = nextInChain; + head = nextInChain; + } + return first; } - return first; - } - /** - * EN: Subclasses will implement this method with concrete checks. - *

- * RU: Подклассы реализуют в этом методе конкретные проверки. - */ - public abstract boolean check(String email, String password); + /** + * EN: Subclasses will implement this method with concrete checks. + * + * RU: Подклассы реализуют в этом методе конкретные проверки. + */ + public abstract boolean check(String email, String password); - /** - * EN: Runs check on the next object in chain or ends traversing if we're in - * last object in chain. - *

- * RU: Запускает проверку в следующем объекте или завершает проверку, если - * мы в последнем элементе цепи. - */ - protected boolean checkNext(String email, String password) { - return next == null || next.check(email, password); - } + /** + * EN: Runs check on the next object in chain or ends traversing if we're in + * last object in chain. + * + * RU: Запускает проверку в следующем объекте или завершает проверку, если + * мы в последнем элементе цепи. + */ + protected boolean checkNext(String email, String password) { + if (next == null) { + return true; + } + return next.check(email, password); + } } diff --git a/src/refactoring_guru/chain_of_responsibility/example/middleware/RoleCheckMiddleware.java b/src/refactoring_guru/chain_of_responsibility/example/middleware/RoleCheckMiddleware.java index bbecc68..1315883 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/middleware/RoleCheckMiddleware.java +++ b/src/refactoring_guru/chain_of_responsibility/example/middleware/RoleCheckMiddleware.java @@ -2,11 +2,16 @@ /** * EN: ConcreteHandler. Checks a user's role. - *

+ * * RU: Конкретный элемент цепи обрабатывает запрос по-своему. */ public class RoleCheckMiddleware extends Middleware { - public boolean check(String email, String password) { - return email.equals("admin@example.com") || checkNext(email, password); - } + public boolean check(String email, String password) { + if (email.equals("admin@example.com")) { + System.out.println("Hello, admin!"); + return true; + } + System.out.println("Hello, user!"); + return checkNext(email, password); + } } diff --git a/src/refactoring_guru/chain_of_responsibility/example/middleware/ThrottlingMiddleware.java b/src/refactoring_guru/chain_of_responsibility/example/middleware/ThrottlingMiddleware.java index 7a63c39..78341f2 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/middleware/ThrottlingMiddleware.java +++ b/src/refactoring_guru/chain_of_responsibility/example/middleware/ThrottlingMiddleware.java @@ -1,63 +1,47 @@ package refactoring_guru.chain_of_responsibility.example.middleware; -import java.util.Optional; - /** * EN: ConcreteHandler. Checks whether there are too many failed login requests. - *

+ * * RU: Конкретный элемент цепи обрабатывает запрос по-своему. */ public class ThrottlingMiddleware extends Middleware { - private final int requestPerMinute; - private int request; - private long currentTime; - - public ThrottlingMiddleware(int requestPerMinute) { - this.requestPerMinute = requestPerMinute; - this.currentTime = System.currentTimeMillis(); - } + private int requestPerMinute; + private int request; + private long currentTime; - /** - * EN: Please, not that checkNext() call can be inserted both in the - * beginning of this method and in the end. - *

- * This gives much more flexibility than a simple loop over all middleware - * objects. For instance, an element of a chain can change the order of - * checks by running its check after all other checks. - *

- * RU: Обратите внимание, вызов checkNext() можно вставить как в начале - * этого метода, так и в середине или в конце. - *

- * Это даёт еще один уровень гибкости по сравнению с проверками в цикле. - * Например, элемент цепи может пропустить все остальные проверки вперёд и - * запустить свою проверку в конце. - */ - public boolean check(String email, String password) { - return resetIfTimeElapsed() - .filter(this::withinRateLimit) - .map(ignored -> checkNext(email, password)) - .orElseThrow(() -> { - System.out.println("Request limit exceeded!"); - return new RuntimeException("Request limit exceeded!"); - }); - } - - private Optional resetIfTimeElapsed() { - long now = System.currentTimeMillis(); - if (now > currentTime + 60_000) { - request = 0; - currentTime = now; + public ThrottlingMiddleware(int requestPerMinute) { + this.requestPerMinute = requestPerMinute; + this.currentTime = System.currentTimeMillis(); } - request++; - return Optional.of(true); - } - @Override - protected boolean checkNext(String email, String password) { - return true; - } + /** + * EN: Please, not that checkNext() call can be inserted both in the + * beginning of this method and in the end. + * + * This gives much more flexibility than a simple loop over all middleware + * objects. For instance, an element of a chain can change the order of + * checks by running its check after all other checks. + * + * RU: Обратите внимание, вызов checkNext() можно вставить как в начале + * этого метода, так и в середине или в конце. + * + * Это даёт еще один уровень гибкости по сравнению с проверками в цикле. + * Например, элемент цепи может пропустить все остальные проверки вперёд и + * запустить свою проверку в конце. + */ + public boolean check(String email, String password) { + if (System.currentTimeMillis() > currentTime + 60_000) { + request = 0; + currentTime = System.currentTimeMillis(); + } - private boolean withinRateLimit(Boolean ignored) { - return request <= requestPerMinute; - } + request++; + + if (request > requestPerMinute) { + System.out.println("Request limit exceeded!"); + Thread.currentThread().stop(); + } + return checkNext(email, password); + } } diff --git a/src/refactoring_guru/chain_of_responsibility/example/middleware/UserExistsMiddleware.java b/src/refactoring_guru/chain_of_responsibility/example/middleware/UserExistsMiddleware.java index 5e64477..005d0a6 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/middleware/UserExistsMiddleware.java +++ b/src/refactoring_guru/chain_of_responsibility/example/middleware/UserExistsMiddleware.java @@ -4,25 +4,25 @@ /** * EN: ConcreteHandler. Checks whether a user with the given credentials exists. - *

+ * * RU: Конкретный элемент цепи обрабатывает запрос по-своему. */ public class UserExistsMiddleware extends Middleware { - private final Server server; + private Server server; - public UserExistsMiddleware(Server server) { - this.server = server; - } - - public boolean check(String email, String password) { - if (!server.hasEmail(email)) { - System.out.println("This email is not registered!"); - return false; + public UserExistsMiddleware(Server server) { + this.server = server; } - if (!server.isValidPassword(email, password)) { - System.out.println("Wrong password!"); - return false; + + public boolean check(String email, String password) { + if (!server.hasEmail(email)) { + System.out.println("This email is not registered!"); + return false; + } + if (!server.isValidPassword(email, password)) { + System.out.println("Wrong password!"); + return false; + } + return checkNext(email, password); } - return checkNext(email, password); - } } diff --git a/src/refactoring_guru/chain_of_responsibility/example/server/Server.java b/src/refactoring_guru/chain_of_responsibility/example/server/Server.java index 5be51c5..52f0be2 100644 --- a/src/refactoring_guru/chain_of_responsibility/example/server/Server.java +++ b/src/refactoring_guru/chain_of_responsibility/example/server/Server.java @@ -7,44 +7,54 @@ /** * EN: Server class. - *

+ * * RU: Класс сервера. */ public class Server { - private final Map users = new HashMap<>(); - private Middleware middleware; - - /** - * EN: Client passes a chain of object to server. This improves flexibility - * and makes testing the server class easier. - *

- * RU: Клиент подаёт готовую цепочку в сервер. Это увеличивает гибкость и - * упрощает тестирование класса сервера. - */ - public void setMiddleware(Middleware middleware) { - this.middleware = middleware; - } - - /** - * EN: Server gets email and password from client and sends the - * authorization request to the chain. - *

- * RU: Сервер получает email и пароль от клиента и запускает проверку - * авторизации у цепочки. - */ - public boolean logIn(String email, String password) { - return middleware.check(email, password); - } - - public void register(String email, String password) { - users.put(email, password); - } - - public boolean hasEmail(String email) { - return users.containsKey(email); - } - - public boolean isValidPassword(String email, String password) { - return users.get(email).equals(password); - } + private Map users = new HashMap<>(); + private Middleware middleware; + + /** + * EN: Client passes a chain of object to server. This improves flexibility + * and makes testing the server class easier. + * + * RU: Клиент подаёт готовую цепочку в сервер. Это увеличивает гибкость и + * упрощает тестирование класса сервера. + */ + public void setMiddleware(Middleware middleware) { + this.middleware = middleware; + } + + /** + * EN: Server gets email and password from client and sends the + * authorization request to the chain. + * + * RU: Сервер получает email и пароль от клиента и запускает проверку + * авторизации у цепочки. + */ + public boolean logIn(String email, String password) { + if (middleware.check(email, password)) { + System.out.println("Authorization have been successful!"); + + // EN: Do something useful here for authorized users. + // + // RU: Здесь должен быть какой-то полезный код, работающий для + // авторизированных пользователей. + + return true; + } + return false; + } + + public void register(String email, String password) { + users.put(email, password); + } + + public boolean hasEmail(String email) { + return users.containsKey(email); + } + + public boolean isValidPassword(String email, String password) { + return users.get(email).equals(password); + } } diff --git a/src/refactoring_guru/command/example/Demo.java b/src/refactoring_guru/command/example/Demo.java index 56b748b..7fa1d5a 100644 --- a/src/refactoring_guru/command/example/Demo.java +++ b/src/refactoring_guru/command/example/Demo.java @@ -3,8 +3,8 @@ import refactoring_guru.command.example.editor.Editor; public class Demo { - public static void main(String[] args) { - Editor editor = new Editor(); - editor.init(); - } + public static void main(String[] args) { + Editor editor = new Editor(); + editor.init(); + } } diff --git a/src/refactoring_guru/command/example/commands/Command.java b/src/refactoring_guru/command/example/commands/Command.java index 88d7775..9a6c680 100644 --- a/src/refactoring_guru/command/example/commands/Command.java +++ b/src/refactoring_guru/command/example/commands/Command.java @@ -3,20 +3,20 @@ import refactoring_guru.command.example.editor.Editor; public abstract class Command { - public Editor editor; - private String backup; + public Editor editor; + private String backup; - Command(Editor editor) { - this.editor = editor; - } + Command(Editor editor) { + this.editor = editor; + } - void backup() { - backup = editor.textField.getText(); - } + void backup() { + backup = editor.textField.getText(); + } - public void undo() { - editor.textField.setText(backup); - } + public void undo() { + editor.textField.setText(backup); + } - public abstract boolean execute(); + public abstract boolean execute(); } diff --git a/src/refactoring_guru/command/example/commands/CommandHistory.java b/src/refactoring_guru/command/example/commands/CommandHistory.java index 843232e..5d578d6 100644 --- a/src/refactoring_guru/command/example/commands/CommandHistory.java +++ b/src/refactoring_guru/command/example/commands/CommandHistory.java @@ -1,20 +1,17 @@ package refactoring_guru.command.example.commands; -import java.util.ArrayDeque; -import java.util.Deque; +import java.util.Stack; public class CommandHistory { - private final Deque history = new ArrayDeque<>(); + private Stack history = new Stack<>(); - public void push(Command c) { - history.push(c); - } + public void push(Command c) { + history.push(c); + } - public Command pop() { - return history.pop(); - } + public Command pop() { + return history.pop(); + } - public boolean isEmpty() { - return history.isEmpty(); - } + public boolean isEmpty() { return history.isEmpty(); } } diff --git a/src/refactoring_guru/command/example/commands/CopyCommand.java b/src/refactoring_guru/command/example/commands/CopyCommand.java index 3f74b51..5d4d47b 100644 --- a/src/refactoring_guru/command/example/commands/CopyCommand.java +++ b/src/refactoring_guru/command/example/commands/CopyCommand.java @@ -4,13 +4,13 @@ public class CopyCommand extends Command { - public CopyCommand(Editor editor) { - super(editor); - } + public CopyCommand(Editor editor) { + super(editor); + } - @Override - public boolean execute() { - editor.clipboard = editor.textField.getSelectedText(); - return false; - } + @Override + public boolean execute() { + editor.clipboard = editor.textField.getSelectedText(); + return false; + } } diff --git a/src/refactoring_guru/command/example/commands/CutCommand.java b/src/refactoring_guru/command/example/commands/CutCommand.java index 902061b..495d9ab 100644 --- a/src/refactoring_guru/command/example/commands/CutCommand.java +++ b/src/refactoring_guru/command/example/commands/CutCommand.java @@ -4,24 +4,24 @@ public class CutCommand extends Command { - public CutCommand(Editor editor) { - super(editor); - } + public CutCommand(Editor editor) { + super(editor); + } - @Override - public boolean execute() { - if (editor.textField.getSelectedText().isEmpty()) return false; + @Override + public boolean execute() { + if (editor.textField.getSelectedText().isEmpty()) return false; - backup(); - String source = editor.textField.getText(); - editor.clipboard = editor.textField.getSelectedText(); - editor.textField.setText(cutString(source)); - return true; - } + backup(); + String source = editor.textField.getText(); + editor.clipboard = editor.textField.getSelectedText(); + editor.textField.setText(cutString(source)); + return true; + } - private String cutString(String source) { - String start = source.substring(0, editor.textField.getSelectionStart()); - String end = source.substring(editor.textField.getSelectionEnd()); - return start + end; - } + private String cutString(String source) { + String start = source.substring(0, editor.textField.getSelectionStart()); + String end = source.substring(editor.textField.getSelectionEnd()); + return start + end; + } } diff --git a/src/refactoring_guru/command/example/commands/PasteCommand.java b/src/refactoring_guru/command/example/commands/PasteCommand.java index 17aee5c..e787346 100644 --- a/src/refactoring_guru/command/example/commands/PasteCommand.java +++ b/src/refactoring_guru/command/example/commands/PasteCommand.java @@ -4,18 +4,16 @@ public class PasteCommand extends Command { - public PasteCommand(Editor editor) { - super(editor); - } - - @Override - public boolean execute() { - if (editor.clipboard == null || editor.clipboard.isEmpty()) { - return false; + public PasteCommand(Editor editor) { + super(editor); } - backup(); - editor.textField.insert(editor.clipboard, editor.textField.getCaretPosition()); - return true; - } + @Override + public boolean execute() { + if (editor.clipboard == null || editor.clipboard.isEmpty()) return false; + + backup(); + editor.textField.insert(editor.clipboard, editor.textField.getCaretPosition()); + return true; + } } diff --git a/src/refactoring_guru/command/example/editor/Editor.java b/src/refactoring_guru/command/example/editor/Editor.java index 9065c01..87b241b 100644 --- a/src/refactoring_guru/command/example/editor/Editor.java +++ b/src/refactoring_guru/command/example/editor/Editor.java @@ -4,53 +4,75 @@ import javax.swing.*; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public class Editor { - public JTextArea textField; - public String clipboard; - private final CommandHistory history = new CommandHistory(); + public JTextArea textField; + public String clipboard; + private CommandHistory history = new CommandHistory(); - public void init() { - JFrame frame = new JFrame("Text editor (type & use buttons, Luke!)"); - JPanel content = new JPanel(); - frame.setContentPane(content); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); - textField = new JTextArea(); - textField.setLineWrap(true); - content.add(textField); - JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER)); - JButton ctrlC = new JButton("Ctrl+C"); - JButton ctrlX = new JButton("Ctrl+X"); - JButton ctrlV = new JButton("Ctrl+V"); - JButton ctrlZ = new JButton("Ctrl+Z"); - Editor editor = this; - ctrlC.addActionListener(e -> executeCommand(new CopyCommand(editor))); - ctrlX.addActionListener(e -> executeCommand(new CutCommand(editor))); - ctrlV.addActionListener(e -> executeCommand(new PasteCommand(editor))); - ctrlZ.addActionListener(e -> undo()); - buttons.add(ctrlC); - buttons.add(ctrlX); - buttons.add(ctrlV); - buttons.add(ctrlZ); - content.add(buttons); - frame.setSize(450, 200); - frame.setLocationRelativeTo(null); - frame.setVisible(true); - } + public void init() { + JFrame frame = new JFrame("Text editor (type & use buttons, Luke!)"); + JPanel content = new JPanel(); + frame.setContentPane(content); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); + textField = new JTextArea(); + textField.setLineWrap(true); + content.add(textField); + JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER)); + JButton ctrlC = new JButton("Ctrl+C"); + JButton ctrlX = new JButton("Ctrl+X"); + JButton ctrlV = new JButton("Ctrl+V"); + JButton ctrlZ = new JButton("Ctrl+Z"); + Editor editor = this; + ctrlC.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + executeCommand(new CopyCommand(editor)); + } + }); + ctrlX.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + executeCommand(new CutCommand(editor)); + } + }); + ctrlV.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + executeCommand(new PasteCommand(editor)); + } + }); + ctrlZ.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + undo(); + } + }); + buttons.add(ctrlC); + buttons.add(ctrlX); + buttons.add(ctrlV); + buttons.add(ctrlZ); + content.add(buttons); + frame.setSize(450, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } - private void executeCommand(Command command) { - if (command.execute()) { - history.push(command); + private void executeCommand(Command command) { + if (command.execute()) { + history.push(command); + } } - } - private void undo() { - if (history.isEmpty()) return; + private void undo() { + if (history.isEmpty()) return; - Command command = history.pop(); - if (command != null) { - command.undo(); + Command command = history.pop(); + if (command != null) { + command.undo(); + } } - } } diff --git a/src/refactoring_guru/composite/example/Demo.java b/src/refactoring_guru/composite/example/Demo.java index 9d810b1..0e27c73 100644 --- a/src/refactoring_guru/composite/example/Demo.java +++ b/src/refactoring_guru/composite/example/Demo.java @@ -9,25 +9,24 @@ import java.awt.*; public class Demo { - public static void main(String[] args) { - ImageEditor editor = new ImageEditor(); - createAndLoadShapes(editor); - } + public static void main(String[] args) { + ImageEditor editor = new ImageEditor(); - private static void createAndLoadShapes(ImageEditor editor) { - Circle blueCircle = new Circle(10, 10, 10, Color.BLUE); + editor.loadShapes( + new Circle(10, 10, 10, Color.BLUE), - Circle redCircle = new Circle(110, 110, 50, Color.RED); - Dot redDot = new Dot(160, 160, Color.RED); - CompoundShape redCompound = new CompoundShape(redCircle, redDot); + new CompoundShape( + new Circle(110, 110, 50, Color.RED), + new Dot(160, 160, Color.RED) + ), - Rectangle greenRectangle = new Rectangle(250, 250, 100, 100, Color.GREEN); - Dot dot1 = new Dot(240, 240, Color.GREEN); - Dot dot2 = new Dot(240, 360, Color.GREEN); - Dot dot3 = new Dot(360, 360, Color.GREEN); - Dot dot4 = new Dot(360, 240, Color.GREEN); - CompoundShape greenCompound = new CompoundShape(greenRectangle, dot1, dot2, dot3, dot4); - - editor.loadShapes(blueCircle, redCompound, greenCompound); - } + new CompoundShape( + new Rectangle(250, 250, 100, 100, Color.GREEN), + new Dot(240, 240, Color.GREEN), + new Dot(240, 360, Color.GREEN), + new Dot(360, 360, Color.GREEN), + new Dot(360, 240, Color.GREEN) + ) + ); + } } \ No newline at end of file diff --git a/src/refactoring_guru/composite/example/editor/ImageEditor.java b/src/refactoring_guru/composite/example/editor/ImageEditor.java index 8975b70..dfc7277 100644 --- a/src/refactoring_guru/composite/example/editor/ImageEditor.java +++ b/src/refactoring_guru/composite/example/editor/ImageEditor.java @@ -10,69 +10,67 @@ import java.awt.event.MouseEvent; public class ImageEditor { - private final EditorCanvas canvas; - private final CompoundShape allShapes = new CompoundShape(); + private EditorCanvas canvas; + private CompoundShape allShapes = new CompoundShape(); - public ImageEditor() { - canvas = new EditorCanvas(); - } + public ImageEditor() { + canvas = new EditorCanvas(); + } + + public void loadShapes(Shape... shapes) { + allShapes.clear(); + allShapes.add(shapes); + canvas.refresh(); + } - public void loadShapes(Shape... shapes) { - allShapes.clear(); - allShapes.add(shapes); - canvas.refresh(); - } + private class EditorCanvas extends Canvas { + JFrame frame; - private class EditorCanvas extends Canvas { - private static final int PADDING = 10; - JFrame frame; + private static final int PADDING = 10; - EditorCanvas() { - createFrame(); - refresh(); - addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - allShapes.unSelect(); - allShapes.selectChildAt(e.getX(), e.getY()); - e.getComponent().repaint(); + EditorCanvas() { + createFrame(); + refresh(); + addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + allShapes.unSelect(); + allShapes.selectChildAt(e.getX(), e.getY()); + e.getComponent().repaint(); + } + }); } - }); - } - void createFrame() { - frame = new JFrame(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - frame.setLocationRelativeTo(null); + void createFrame() { + frame = new JFrame(); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frame.setLocationRelativeTo(null); - JPanel contentPanel = new JPanel(); - Border padding = BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING); - contentPanel.setBorder(padding); - frame.setContentPane(contentPanel); + JPanel contentPanel = new JPanel(); + Border padding = BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING); + contentPanel.setBorder(padding); + frame.setContentPane(contentPanel); - frame.add(this); - frame.setVisible(true); - frame.getContentPane().setBackground(Color.LIGHT_GRAY); - } + frame.add(this); + frame.setVisible(true); + frame.getContentPane().setBackground(Color.LIGHT_GRAY); + } - @Override - public int getWidth() { - return allShapes.getX() + allShapes.getWidth() + PADDING; - } + public int getWidth() { + return allShapes.getX() + allShapes.getWidth() + PADDING; + } - @Override - public int getHeight() { - return allShapes.getY() + allShapes.getHeight() + PADDING; - } + public int getHeight() { + return allShapes.getY() + allShapes.getHeight() + PADDING; + } - void refresh() { - this.setSize(getWidth(), getHeight()); - frame.pack(); - } + void refresh() { + this.setSize(getWidth(), getHeight()); + frame.pack(); + } - @Override - public void paint(Graphics graphics) { - allShapes.paint(graphics); + public void paint(Graphics graphics) { + allShapes.paint(graphics); + } } - } } diff --git a/src/refactoring_guru/composite/example/shapes/BaseShape.java b/src/refactoring_guru/composite/example/shapes/BaseShape.java index 6e1b421..f0f5552 100644 --- a/src/refactoring_guru/composite/example/shapes/BaseShape.java +++ b/src/refactoring_guru/composite/example/shapes/BaseShape.java @@ -3,88 +3,91 @@ import java.awt.*; abstract class BaseShape implements Shape { - public int x; - public int y; - public Color color; - private boolean selected = false; - - BaseShape(int x, int y, Color color) { - this.x = x; - this.y = y; - this.color = color; - } - - @Override - public int getX() { - return x; - } - - @Override - public int getY() { - return y; - } - - @Override - public int getWidth() { - return 0; - } - - @Override - public int getHeight() { - return 0; - } - - @Override - public void move(int x, int y) { - this.x += x; - this.y += y; - } - - @Override - public boolean isInsideBounds(int x, int y) { - return x > getX() && x < (getX() + getWidth()) && - y > getY() && y < (getY() + getHeight()); - } - - @Override - public void select() { - selected = true; - } - - @Override - public void unSelect() { - selected = false; - } - - @Override - public boolean isSelected() { - return selected; - } - - void enableSelectionStyle(Graphics graphics) { - graphics.setColor(Color.LIGHT_GRAY); - - Graphics2D g2 = (Graphics2D) graphics; - float[] dash1 = {2.0f}; - g2.setStroke(new BasicStroke(1.0f, - BasicStroke.CAP_BUTT, - BasicStroke.JOIN_MITER, - 2.0f, dash1, 0.0f)); - } - - void disableSelectionStyle(Graphics graphics) { - graphics.setColor(color); - Graphics2D g2 = (Graphics2D) graphics; - g2.setStroke(new BasicStroke()); - } - - - @Override - public void paint(Graphics graphics) { - if (isSelected()) { - enableSelectionStyle(graphics); - } else { - disableSelectionStyle(graphics); + public int x; + public int y; + public Color color; + private boolean selected = false; + + BaseShape(int x, int y, Color color) { + this.x = x; + this.y = y; + this.color = color; + } + + @Override + public int getX() { + return x; + } + + @Override + public int getY() { + return y; + } + + @Override + public int getWidth() { + return 0; + } + + @Override + public int getHeight() { + return 0; + } + + @Override + public void move(int x, int y) { + this.x += x; + this.y += y; + } + + @Override + public boolean isInsideBounds(int x, int y) { + return x > getX() && x < (getX() + getWidth()) && + y > getY() && y < (getY() + getHeight()); + } + + @Override + public void select() { + selected = true; + } + + @Override + public void unSelect() { + selected = false; + } + + @Override + public boolean isSelected() { + return selected; + } + + void enableSelectionStyle(Graphics graphics) { + graphics.setColor(Color.LIGHT_GRAY); + + Graphics2D g2 = (Graphics2D) graphics; + float[] dash1 = {2.0f}; + g2.setStroke(new BasicStroke(1.0f, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, + 2.0f, dash1, 0.0f)); + } + + void disableSelectionStyle(Graphics graphics) { + graphics.setColor(color); + Graphics2D g2 = (Graphics2D) graphics; + g2.setStroke(new BasicStroke()); + } + + + @Override + public void paint(Graphics graphics) { + if (isSelected()) { + enableSelectionStyle(graphics); + } + else { + disableSelectionStyle(graphics); + } + + // ... } - } } diff --git a/src/refactoring_guru/composite/example/shapes/Circle.java b/src/refactoring_guru/composite/example/shapes/Circle.java index f9b8c1a..98fd6db 100644 --- a/src/refactoring_guru/composite/example/shapes/Circle.java +++ b/src/refactoring_guru/composite/example/shapes/Circle.java @@ -3,26 +3,25 @@ import java.awt.*; public class Circle extends BaseShape { - public int radius; + public int radius; - public Circle(int x, int y, int radius, Color color) { - super(x, y, color); - this.radius = radius; - } + public Circle(int x, int y, int radius, Color color) { + super(x, y, color); + this.radius = radius; + } - @Override - public int getWidth() { - return radius * 2; - } + @Override + public int getWidth() { + return radius * 2; + } - @Override - public int getHeight() { - return radius * 2; - } + @Override + public int getHeight() { + return radius * 2; + } - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.drawOval(x, y, getWidth() - 1, getHeight() - 1); - } + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.drawOval(x, y, getWidth() - 1, getHeight() - 1); + } } diff --git a/src/refactoring_guru/composite/example/shapes/CompoundShape.java b/src/refactoring_guru/composite/example/shapes/CompoundShape.java index 2bba432..ee9562a 100644 --- a/src/refactoring_guru/composite/example/shapes/CompoundShape.java +++ b/src/refactoring_guru/composite/example/shapes/CompoundShape.java @@ -6,132 +6,134 @@ import java.util.List; public class CompoundShape extends BaseShape { - protected List children = new ArrayList<>(); - - public CompoundShape(Shape... components) { - super(0, 0, Color.BLACK); - add(components); - } - - public void add(Shape component) { - children.add(component); - } - - public void add(Shape... components) { - children.addAll(Arrays.asList(components)); - } - - public void remove(Shape child) { - children.remove(child); - } - - public void remove(Shape... components) { - children.removeAll(Arrays.asList(components)); - } - - public void clear() { - children.clear(); - } - - @Override - public int getX() { - checkNoEmpty(children); - int x = children.get(0).getX(); - for (Shape child : children) { - if (child.getX() < x) { - x = child.getX(); - } + protected List children = new ArrayList<>(); + + public CompoundShape(Shape... components) { + super(0, 0, Color.BLACK); + add(components); + } + + public void add(Shape component) { + children.add(component); + } + + public void add(Shape... components) { + children.addAll(Arrays.asList(components)); + } + + public void remove(Shape child) { + children.remove(child); + } + + public void remove(Shape... components) { + children.removeAll(Arrays.asList(components)); } - return x; - } - - @Override - public int getY() { - checkNoEmpty(children); - int y = children.get(0).getY(); - for (Shape child : children) { - if (child.getY() < y) { - y = child.getY(); - } + + public void clear() { + children.clear(); } - return y; - } - - @Override - public int getWidth() { - int maxWidth = 0; - int x = getX(); - - for (Shape child : children) { - int childRelativeX = child.getX() - x; - int childWidth = childRelativeX + child.getWidth(); - maxWidth = Math.max(maxWidth, childWidth); + + @Override + public int getX() { + if (children.size() == 0) { + return 0; + } + int x = children.get(0).getX(); + for (Shape child : children) { + if (child.getX() < x) { + x = child.getX(); + } + } + return x; } - return maxWidth; - } - - @Override - public int getHeight() { - int maxHeight = 0; - int y = getY(); - - for (Shape child : children) { - int childRelativeY = child.getY() - y; - int childHeight = childRelativeY + child.getHeight(); - maxHeight = Math.max(maxHeight, childHeight); + + @Override + public int getY() { + if (children.size() == 0) { + return 0; + } + int y = children.get(0).getY(); + for (Shape child : children) { + if (child.getY() < y) { + y = child.getY(); + } + } + return y; } - return maxHeight; - } - @Override - public void move(int x, int y) { - for (Shape child : children) { - child.move(x, y); + @Override + public int getWidth() { + int maxWidth = 0; + int x = getX(); + for (Shape child : children) { + int childsRelativeX = child.getX() - x; + int childWidth = childsRelativeX + child.getWidth(); + if (childWidth > maxWidth) { + maxWidth = childWidth; + } + } + return maxWidth; } - } - - @Override - public boolean isInsideBounds(int x, int y) { - for (Shape child : children) { - if (child.isInsideBounds(x, y)) { - return true; - } + + @Override + public int getHeight() { + int maxHeight = 0; + int y = getY(); + for (Shape child : children) { + int childsRelativeY = child.getY() - y; + int childHeight = childsRelativeY + child.getHeight(); + if (childHeight > maxHeight) { + maxHeight = childHeight; + } + } + return maxHeight; } - return false; - } - - @Override - public void unSelect() { - super.unSelect(); - for (Shape child : children) { - child.unSelect(); + + @Override + public void move(int x, int y) { + for (Shape child : children) { + child.move(x, y); + } } - } - public void selectChildAt(int x, int y) { - for (Shape child : children) { - if (child.isInsideBounds(x, y)) { - child.select(); - } + @Override + public boolean isInsideBounds(int x, int y) { + for (Shape child : children) { + if (child.isInsideBounds(x, y)) { + return true; + } + } + return false; } - } - - @Override - public void paint(Graphics graphics) { - if (isSelected()) { - enableSelectionStyle(graphics); - graphics.drawRect(getX() - 1, getY() - 1, getWidth() + 1, getHeight() + 1); - disableSelectionStyle(graphics); + + @Override + public void unSelect() { + super.unSelect(); + for (Shape child : children) { + child.unSelect(); + } } - for (Shape child : children) { - child.paint(graphics); + public boolean selectChildAt(int x, int y) { + for (Shape child : children) { + if (child.isInsideBounds(x, y)) { + child.select(); + return true; + } + } + return false; } - } - private static void checkNoEmpty(List children) { - if (children.isEmpty()) { - throw new IllegalArgumentException("The List is empty "); - } - } + @Override + public void paint(Graphics graphics) { + if (isSelected()) { + enableSelectionStyle(graphics); + graphics.drawRect(getX() - 1, getY() - 1, getWidth() + 1, getHeight() + 1); + disableSelectionStyle(graphics); + } + + for (Shape child : children) { + child.paint(graphics); + } + } } diff --git a/src/refactoring_guru/composite/example/shapes/Dot.java b/src/refactoring_guru/composite/example/shapes/Dot.java index 1e4a680..205326a 100644 --- a/src/refactoring_guru/composite/example/shapes/Dot.java +++ b/src/refactoring_guru/composite/example/shapes/Dot.java @@ -3,24 +3,25 @@ import java.awt.*; public class Dot extends BaseShape { + private final int DOT_SIZE = 3; - public Dot(int x, int y, Color color) { - super(x, y, color); - } + public Dot(int x, int y, Color color) { + super(x, y, color); + } - @Override - public int getWidth() { - return 3; - } + @Override + public int getWidth() { + return DOT_SIZE; + } - @Override - public int getHeight() { - return 3; - } + @Override + public int getHeight() { + return DOT_SIZE; + } - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.fillRect(x - 1, y - 1, getWidth(), getHeight()); - } + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.fillRect(x - 1, y - 1, getWidth(), getHeight()); + } } diff --git a/src/refactoring_guru/composite/example/shapes/Rectangle.java b/src/refactoring_guru/composite/example/shapes/Rectangle.java index d699590..4a2b73f 100644 --- a/src/refactoring_guru/composite/example/shapes/Rectangle.java +++ b/src/refactoring_guru/composite/example/shapes/Rectangle.java @@ -3,28 +3,28 @@ import java.awt.*; public class Rectangle extends BaseShape { - public int width; - public int height; + public int width; + public int height; - public Rectangle(int x, int y, int width, int height, Color color) { - super(x, y, color); - this.width = width; - this.height = height; - } + public Rectangle(int x, int y, int width, int height, Color color) { + super(x, y, color); + this.width = width; + this.height = height; + } - @Override - public int getWidth() { - return width; - } + @Override + public int getWidth() { + return width; + } - @Override - public int getHeight() { - return height; - } + @Override + public int getHeight() { + return height; + } - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.drawRect(x, y, getWidth() - 1, getHeight() - 1); - } + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.drawRect(x, y, getWidth() - 1, getHeight() - 1); + } } diff --git a/src/refactoring_guru/composite/example/shapes/Shape.java b/src/refactoring_guru/composite/example/shapes/Shape.java index d209ec7..746cf83 100644 --- a/src/refactoring_guru/composite/example/shapes/Shape.java +++ b/src/refactoring_guru/composite/example/shapes/Shape.java @@ -3,23 +3,14 @@ import java.awt.*; public interface Shape { - int getX(); - - int getY(); - - int getWidth(); - - int getHeight(); - - void move(int x, int y); - - boolean isInsideBounds(int x, int y); - - void select(); - - void unSelect(); - - boolean isSelected(); - - void paint(Graphics graphics); + int getX(); + int getY(); + int getWidth(); + int getHeight(); + void move(int x, int y); + boolean isInsideBounds(int x, int y); + void select(); + void unSelect(); + boolean isSelected(); + void paint(Graphics graphics); } diff --git a/src/refactoring_guru/decorator/example/Demo.java b/src/refactoring_guru/decorator/example/Demo.java index 84a7303..cb58725 100644 --- a/src/refactoring_guru/decorator/example/Demo.java +++ b/src/refactoring_guru/decorator/example/Demo.java @@ -3,22 +3,19 @@ import refactoring_guru.decorator.example.decorators.*; public class Demo { - public static void main(String[] args) { - init(); - } + public static void main(String[] args) { + String salaryRecords = "Name,Salary\nJohn Smith,100000\nSteven Jobs,912000"; + DataSourceDecorator encoded = new CompressionDecorator( + new EncryptionDecorator( + new FileDataSource("out/OutputDemo.txt"))); + encoded.writeData(salaryRecords); + DataSource plain = new FileDataSource("out/OutputDemo.txt"); - private static void init() { - DataSourceDecorator encoded = new CompressionDecorator( - new EncryptionDecorator( - new FileDataSource("out/OutputDemo.txt"))); - encoded.writeData("Name, salary\nJohn Smith, 100000\nSteven Jobs\n"); - DataSource plain = new FileDataSource("out/OutputDemo.txt"); - - System.out.println("- Input ----------------"); - System.out.println("Name, salary\nJohn Smith, 100000\nSteven Jobs\n"); - System.out.println("- Encoded --------------"); - System.out.println(plain.readData()); - System.out.println("- Decoded --------------"); - System.out.println(encoded.readData()); - } + System.out.println("- Input ----------------"); + System.out.println(salaryRecords); + System.out.println("- Encoded --------------"); + System.out.println(plain.readData()); + System.out.println("- Decoded --------------"); + System.out.println(encoded.readData()); + } } diff --git a/src/refactoring_guru/decorator/example/decorators/CompressionDecorator.java b/src/refactoring_guru/decorator/example/decorators/CompressionDecorator.java index 6af5261..fc63691 100644 --- a/src/refactoring_guru/decorator/example/decorators/CompressionDecorator.java +++ b/src/refactoring_guru/decorator/example/decorators/CompressionDecorator.java @@ -10,60 +10,60 @@ import java.util.zip.InflaterInputStream; public class CompressionDecorator extends DataSourceDecorator { - private int compLevel = 6; + private int compLevel = 6; - public CompressionDecorator(DataSource source) { - super(source); - } + public CompressionDecorator(DataSource source) { + super(source); + } - public int getCompressionLevel() { - return compLevel; - } + public int getCompressionLevel() { + return compLevel; + } - public void setCompressionLevel(int value) { - compLevel = value; - } + public void setCompressionLevel(int value) { + compLevel = value; + } - @Override - public void writeData(String data) { - super.writeData(compress(data)); - } + @Override + public void writeData(String data) { + super.writeData(compress(data)); + } - @Override - public String readData() { - return decompress(super.readData()); - } + @Override + public String readData() { + return decompress(super.readData()); + } - private String compress(String stringData) { - byte[] data = stringData.getBytes(); - try { - ByteArrayOutputStream bout = new ByteArrayOutputStream(512); - DeflaterOutputStream dos = new DeflaterOutputStream(bout, new Deflater(compLevel)); - dos.write(data); - dos.close(); - bout.close(); - return Base64.getEncoder().encodeToString(bout.toByteArray()); - } catch (IOException ex) { - return null; + private String compress(String stringData) { + byte[] data = stringData.getBytes(); + try { + ByteArrayOutputStream bout = new ByteArrayOutputStream(512); + DeflaterOutputStream dos = new DeflaterOutputStream(bout, new Deflater(compLevel)); + dos.write(data); + dos.close(); + bout.close(); + return Base64.getEncoder().encodeToString(bout.toByteArray()); + } catch (IOException ex) { + return null; + } } - } - private String decompress(String stringData) { - byte[] data = Base64.getDecoder().decode(stringData); - try { - InputStream in = new ByteArrayInputStream(data); - InflaterInputStream iin = new InflaterInputStream(in); - ByteArrayOutputStream bout = new ByteArrayOutputStream(512); - int b; - while ((b = iin.read()) != -1) { - bout.write(b); - } - in.close(); - iin.close(); - bout.close(); - return bout.toString(); - } catch (IOException ex) { - return null; + private String decompress(String stringData) { + byte[] data = Base64.getDecoder().decode(stringData); + try { + InputStream in = new ByteArrayInputStream(data); + InflaterInputStream iin = new InflaterInputStream(in); + ByteArrayOutputStream bout = new ByteArrayOutputStream(512); + int b; + while ((b = iin.read()) != -1) { + bout.write(b); + } + in.close(); + iin.close(); + bout.close(); + return new String(bout.toByteArray()); + } catch (IOException ex) { + return null; + } } - } } diff --git a/src/refactoring_guru/decorator/example/decorators/DataSource.java b/src/refactoring_guru/decorator/example/decorators/DataSource.java index 1d2c360..b26cd07 100644 --- a/src/refactoring_guru/decorator/example/decorators/DataSource.java +++ b/src/refactoring_guru/decorator/example/decorators/DataSource.java @@ -1,7 +1,7 @@ package refactoring_guru.decorator.example.decorators; public interface DataSource { - void writeData(String data); + void writeData(String data); - String readData(); + String readData(); } diff --git a/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java b/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java index 02b02e3..f126d93 100644 --- a/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java +++ b/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java @@ -1,19 +1,19 @@ package refactoring_guru.decorator.example.decorators; public class DataSourceDecorator implements DataSource { - private final DataSource dataSource; + private DataSource wrappee; - DataSourceDecorator(DataSource source) { - this.dataSource = source; - } + DataSourceDecorator(DataSource source) { + this.wrappee = source; + } - @Override - public void writeData(String data) { - dataSource.writeData(data); - } + @Override + public void writeData(String data) { + wrappee.writeData(data); + } - @Override - public String readData() { - return dataSource.readData(); - } + @Override + public String readData() { + return wrappee.readData(); + } } diff --git a/src/refactoring_guru/decorator/example/decorators/EncryptionDecorator.java b/src/refactoring_guru/decorator/example/decorators/EncryptionDecorator.java index 0835af1..2b8821c 100644 --- a/src/refactoring_guru/decorator/example/decorators/EncryptionDecorator.java +++ b/src/refactoring_guru/decorator/example/decorators/EncryptionDecorator.java @@ -4,33 +4,33 @@ public class EncryptionDecorator extends DataSourceDecorator { - public EncryptionDecorator(DataSource source) { - super(source); - } + public EncryptionDecorator(DataSource source) { + super(source); + } - @Override - public void writeData(String data) { - super.writeData(encode(data)); - } + @Override + public void writeData(String data) { + super.writeData(encode(data)); + } - @Override - public String readData() { - return decode(super.readData()); - } + @Override + public String readData() { + return decode(super.readData()); + } - private String encode(String data) { - byte[] result = data.getBytes(); - for (int i = 0; i < result.length; i++) { - result[i] += (byte) 1; + private String encode(String data) { + byte[] result = data.getBytes(); + for (int i = 0; i < result.length; i++) { + result[i] += (byte) 1; + } + return Base64.getEncoder().encodeToString(result); } - return Base64.getEncoder().encodeToString(result); - } - private String decode(String data) { - byte[] result = Base64.getDecoder().decode(data); - for (int i = 0; i < result.length; i++) { - result[i] -= (byte) 1; + private String decode(String data) { + byte[] result = Base64.getDecoder().decode(data); + for (int i = 0; i < result.length; i++) { + result[i] -= (byte) 1; + } + return new String(result); } - return new String(result); - } } diff --git a/src/refactoring_guru/decorator/example/decorators/FileDataSource.java b/src/refactoring_guru/decorator/example/decorators/FileDataSource.java index 97665f6..8b19251 100644 --- a/src/refactoring_guru/decorator/example/decorators/FileDataSource.java +++ b/src/refactoring_guru/decorator/example/decorators/FileDataSource.java @@ -1,36 +1,35 @@ package refactoring_guru.decorator.example.decorators; -import java.io.BufferedWriter; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.io.*; public class FileDataSource implements DataSource { - private final String name; + private String name; - public FileDataSource(String name) { - this.name = name; - } + public FileDataSource(String name) { + this.name = name; + } - @Override - public void writeData(String data) { - Path path = Paths.get(name); - try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { - writer.write(data, 0, data.length()); - } catch (IOException ex) { - throw new RuntimeException("Failed to write data to file: " + name, ex); + @Override + public void writeData(String data) { + File file = new File(name); + try (OutputStream fos = new FileOutputStream(file)) { + fos.write(data.getBytes(), 0, data.length()); + } catch (IOException ex) { + System.out.println(ex.getMessage()); + } } - } - @Override - public String readData() { - Path path = Paths.get(name); - try { - return Files.readString(path); - } catch (IOException ex) { - throw new RuntimeException("Failed to read data from file: " + name, ex); + @Override + public String readData() { + char[] buffer = null; + File file = new File(name); + try (FileReader reader = new FileReader(file)) { + buffer = new char[(int) file.length()]; + reader.read(buffer); + } catch (IOException ex) { + System.out.println(ex.getMessage()); + } + return new String(buffer); } - } } + diff --git a/src/refactoring_guru/facade/example/Demo.java b/src/refactoring_guru/facade/example/Demo.java index 1f1efe6..eb1c8e1 100644 --- a/src/refactoring_guru/facade/example/Demo.java +++ b/src/refactoring_guru/facade/example/Demo.java @@ -2,9 +2,12 @@ import refactoring_guru.facade.example.facade.VideoConversionFacade; +import java.io.File; + public class Demo { - public static void main(String[] args) { - VideoConversionFacade converter = new VideoConversionFacade(); - converter.convertVideo("youtubevideo.ogg"); - } + public static void main(String[] args) { + VideoConversionFacade converter = new VideoConversionFacade(); + File mp4Video = converter.convertVideo("youtubevideo.ogg", "mp4"); + // ... + } } diff --git a/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java b/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java index ef6c3d2..5ae11d0 100644 --- a/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java +++ b/src/refactoring_guru/facade/example/facade/VideoConversionFacade.java @@ -5,13 +5,20 @@ import java.io.File; public class VideoConversionFacade { - public void convertVideo(String fileName) { - System.out.println("VideoConversionFacade: conversion started."); - VideoFile file = new VideoFile(fileName); - - VideoFile buffer = BitrateReader.read(file); - VideoFile intermediateResult = BitrateReader.convert(buffer); - File result = (new AudioMixer()).fix(intermediateResult); - System.out.println("VideoConversionFacade: conversion completed."); - } + public File convertVideo(String fileName, String format) { + System.out.println("VideoConversionFacade: conversion started."); + VideoFile file = new VideoFile(fileName); + Codec sourceCodec = CodecFactory.extract(file); + Codec destinationCodec; + if (format.equals("mp4")) { + destinationCodec = new MPEG4CompressionCodec(); + } else { + destinationCodec = new OggCompressionCodec(); + } + VideoFile buffer = BitrateReader.read(file, sourceCodec); + VideoFile intermediateResult = BitrateReader.convert(buffer, destinationCodec); + File result = (new AudioMixer()).fix(intermediateResult); + System.out.println("VideoConversionFacade: conversion completed."); + return result; + } } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/AudioMixer.java b/src/refactoring_guru/facade/example/some_complex_media_library/AudioMixer.java index e334ac8..399145d 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/AudioMixer.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/AudioMixer.java @@ -3,8 +3,8 @@ import java.io.File; public class AudioMixer { - public File fix(VideoFile result) { - System.out.println("AudioMixer: fixing audio..."); - return new File("tmp"); - } + public File fix(VideoFile result){ + System.out.println("AudioMixer: fixing audio..."); + return new File("tmp"); + } } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/BitrateReader.java b/src/refactoring_guru/facade/example/some_complex_media_library/BitrateReader.java index 148ace5..cc2d57f 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/BitrateReader.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/BitrateReader.java @@ -1,17 +1,13 @@ package refactoring_guru.facade.example.some_complex_media_library; -public final class BitrateReader { - - private BitrateReader() { - } - - public static VideoFile read(VideoFile file) { - System.out.println("BitrateReader: reading file..."); - return file; - } - - public static VideoFile convert(VideoFile buffer) { - System.out.println("BitrateReader: writing file..."); - return buffer; - } +public class BitrateReader { + public static VideoFile read(VideoFile file, Codec codec) { + System.out.println("BitrateReader: reading file..."); + return file; + } + + public static VideoFile convert(VideoFile buffer, Codec codec) { + System.out.println("BitrateReader: writing file..."); + return buffer; + } } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/CodecFactory.java b/src/refactoring_guru/facade/example/some_complex_media_library/CodecFactory.java index b9e17f6..69a7c4d 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/CodecFactory.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/CodecFactory.java @@ -1,18 +1,15 @@ package refactoring_guru.facade.example.some_complex_media_library; -public final class CodecFactory { - - private CodecFactory() { - } - - public static Codec extract(VideoFile file) { - var type = file.getCodecType(); - if (type.equals("mp4")) { - System.out.println("CodecFactory: extracting mpeg audio..."); - return new MPEG4CompressionCodec(); - } else { - System.out.println("CodecFactory: extracting ogg audio..."); - return new OggCompressionCodec(); +public class CodecFactory { + public static Codec extract(VideoFile file) { + String type = file.getCodecType(); + if (type.equals("mp4")) { + System.out.println("CodecFactory: extracting mpeg audio..."); + return new MPEG4CompressionCodec(); + } + else { + System.out.println("CodecFactory: extracting ogg audio..."); + return new OggCompressionCodec(); + } } - } } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/MPEG4CompressionCodec.java b/src/refactoring_guru/facade/example/some_complex_media_library/MPEG4CompressionCodec.java index 7bfc78d..e9e0d29 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/MPEG4CompressionCodec.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/MPEG4CompressionCodec.java @@ -1,5 +1,6 @@ package refactoring_guru.facade.example.some_complex_media_library; public class MPEG4CompressionCodec implements Codec { - public String type = "mp4"; + public String type = "mp4"; + } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/OggCompressionCodec.java b/src/refactoring_guru/facade/example/some_complex_media_library/OggCompressionCodec.java index 81a7c7c..42f200f 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/OggCompressionCodec.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/OggCompressionCodec.java @@ -1,5 +1,5 @@ package refactoring_guru.facade.example.some_complex_media_library; public class OggCompressionCodec implements Codec { - public String type = "ogg"; + public String type = "ogg"; } diff --git a/src/refactoring_guru/facade/example/some_complex_media_library/VideoFile.java b/src/refactoring_guru/facade/example/some_complex_media_library/VideoFile.java index a4a9cae..243035a 100644 --- a/src/refactoring_guru/facade/example/some_complex_media_library/VideoFile.java +++ b/src/refactoring_guru/facade/example/some_complex_media_library/VideoFile.java @@ -1,19 +1,19 @@ package refactoring_guru.facade.example.some_complex_media_library; public class VideoFile { - private final String name; - private final String codecType; + private String name; + private String codecType; - public VideoFile(String name) { - this.name = name; - this.codecType = name.substring(name.indexOf(".") + 1); - } + public VideoFile(String name) { + this.name = name; + this.codecType = name.substring(name.indexOf(".") + 1); + } - public String getCodecType() { - return codecType; - } + public String getCodecType() { + return codecType; + } - public String getName() { - return name; - } + public String getName() { + return name; + } } diff --git a/src/refactoring_guru/factory_method/example/Demo.java b/src/refactoring_guru/factory_method/example/Demo.java index 0b4ed7a..dde90cf 100644 --- a/src/refactoring_guru/factory_method/example/Demo.java +++ b/src/refactoring_guru/factory_method/example/Demo.java @@ -6,42 +6,42 @@ /** * EN: Demo class. Everything comes together here. - *

+ * * RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - private static Dialog dialog; + private static Dialog dialog; - public static void main(String[] args) { - configure(); - runBusinessLogic(); - } + public static void main(String[] args) { + configure(); + runBusinessLogic(); + } - /** - * EN: The concrete factory is usually chosen depending on configuration or - * environment options. - *

- * RU: Приложение создаёт определённую фабрику в зависимости от конфигурации - * или окружения. - */ - static void configure() { - if (System.getProperty("os.name").equals("Windows 10")) { - dialog = new WindowsDialog(); - } else { - dialog = new HtmlDialog(); + /** + * EN: The concrete factory is usually chosen depending on configuration or + * environment options. + * + * RU: Приложение создаёт определённую фабрику в зависимости от конфигурации + * или окружения. + */ + static void configure() { + if (System.getProperty("os.name").equals("Windows 10")) { + dialog = new WindowsDialog(); + } else { + dialog = new HtmlDialog(); + } } - } - /** - * EN: All of the client code should work with factories and products - * through abstract interfaces. This way it does not care which factory it - * works with and what kind of product it returns. - *

- * RU: Весь остальной клиентский код работает с фабрикой и продуктами только - * через общий интерфейс, поэтому для него неважно какая фабрика была - * создана. - */ - static void runBusinessLogic() { - dialog.renderWindow(); - } + /** + * EN: All of the client code should work with factories and products + * through abstract interfaces. This way it does not care which factory it + * works with and what kind of product it returns. + * + * RU: Весь остальной клиентский код работает с фабрикой и продуктами только + * через общий интерфейс, поэтому для него неважно какая фабрика была + * создана. + */ + static void runBusinessLogic() { + dialog.renderWindow(); + } } diff --git a/src/refactoring_guru/factory_method/example/buttons/Button.java b/src/refactoring_guru/factory_method/example/buttons/Button.java index 1ae0454..02bef0f 100644 --- a/src/refactoring_guru/factory_method/example/buttons/Button.java +++ b/src/refactoring_guru/factory_method/example/buttons/Button.java @@ -2,11 +2,10 @@ /** * EN: Common interface for all buttons. - *

+ * * RU: Общий интерфейс для всех продуктов. */ public interface Button { - void render(); - - void onClick(); + void render(); + void onClick(); } diff --git a/src/refactoring_guru/factory_method/example/buttons/HtmlButton.java b/src/refactoring_guru/factory_method/example/buttons/HtmlButton.java index e5d480f..ee44f0b 100644 --- a/src/refactoring_guru/factory_method/example/buttons/HtmlButton.java +++ b/src/refactoring_guru/factory_method/example/buttons/HtmlButton.java @@ -2,17 +2,17 @@ /** * EN: HTML button implementation. - *

+ * * RU: Реализация HTML кнопок. */ public class HtmlButton implements Button { - public void render() { - System.out.println(""); - onClick(); - } + public void render() { + System.out.println(""); + onClick(); + } - public void onClick() { - System.out.println("Click! Button says - 'Hello World!'"); - } + public void onClick() { + System.out.println("Click! Button says - 'Hello World!'"); + } } diff --git a/src/refactoring_guru/factory_method/example/buttons/WindowsButton.java b/src/refactoring_guru/factory_method/example/buttons/WindowsButton.java index 347946b..5ad5a03 100644 --- a/src/refactoring_guru/factory_method/example/buttons/WindowsButton.java +++ b/src/refactoring_guru/factory_method/example/buttons/WindowsButton.java @@ -2,40 +2,44 @@ import javax.swing.*; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; /** * EN: Windows button implementation. - *

+ * * RU: Реализация нативных кнопок операционной системы. */ public class WindowsButton implements Button { - JPanel panel = new JPanel(); - JFrame frame = new JFrame(); - JButton button; + JPanel panel = new JPanel(); + JFrame frame = new JFrame(); + JButton button; - public void render() { - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - JLabel label = new JLabel("Hello World!"); - label.setOpaque(true); - label.setBackground(new Color(235, 233, 126)); - label.setFont(new Font("Dialog", Font.BOLD, 44)); - label.setHorizontalAlignment(SwingConstants.CENTER); - panel.setLayout(new FlowLayout(FlowLayout.CENTER)); - frame.getContentPane().add(panel); - panel.add(label); - onClick(); - panel.add(button); + public void render() { + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JLabel label = new JLabel("Hello World!"); + label.setOpaque(true); + label.setBackground(new Color(235, 233, 126)); + label.setFont(new Font("Dialog", Font.BOLD, 44)); + label.setHorizontalAlignment(SwingConstants.CENTER); + panel.setLayout(new FlowLayout(FlowLayout.CENTER)); + frame.getContentPane().add(panel); + panel.add(label); + onClick(); + panel.add(button); - frame.setSize(320, 200); - frame.setVisible(true); - onClick(); - } + frame.setSize(320, 200); + frame.setVisible(true); + onClick(); + } - public void onClick() { - button = new JButton("Exit"); - button.addActionListener(e -> { - frame.setVisible(false); - System.exit(0); - }); - } + public void onClick() { + button = new JButton("Exit"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + frame.setVisible(false); + System.exit(0); + } + }); + } } diff --git a/src/refactoring_guru/factory_method/example/factory/Dialog.java b/src/refactoring_guru/factory_method/example/factory/Dialog.java index 1aaedd1..3e6fcc3 100644 --- a/src/refactoring_guru/factory_method/example/factory/Dialog.java +++ b/src/refactoring_guru/factory_method/example/factory/Dialog.java @@ -6,24 +6,28 @@ * EN: Base factory class. Note that "factory" is merely a role for the class. * It should have some core business logic which needs different products to be * created. - *

+ * * RU: Базовый класс фабрики. Заметьте, что "фабрика" – это всего лишь * дополнительная роль для класса. Он уже имеет какую-то бизнес-логику, в * которой требуется создание разнообразных продуктов. */ public abstract class Dialog { - public void renderWindow() { - Button okButton = createButton(); - okButton.render(); - } + public void renderWindow() { + // EN: ... other code ... + // + // RU: ... остальной код диалога ... - /** - * EN: Subclasses will override this method in order to create specific - * button objects. - *

- * RU: Подклассы будут переопределять этот метод, чтобы создавать конкретные - * объекты продуктов, разные для каждой фабрики. - */ - public abstract Button createButton(); + Button okButton = createButton(); + okButton.render(); + } + + /** + * EN: Subclasses will override this method in order to create specific + * button objects. + * + * RU: Подклассы будут переопределять этот метод, чтобы создавать конкретные + * объекты продуктов, разные для каждой фабрики. + */ + public abstract Button createButton(); } diff --git a/src/refactoring_guru/factory_method/example/factory/HtmlDialog.java b/src/refactoring_guru/factory_method/example/factory/HtmlDialog.java index 0983611..ceaac8b 100644 --- a/src/refactoring_guru/factory_method/example/factory/HtmlDialog.java +++ b/src/refactoring_guru/factory_method/example/factory/HtmlDialog.java @@ -5,13 +5,13 @@ /** * EN: HTML Dialog will produce HTML buttons. - *

+ * * RU: HTML-диалог. */ public class HtmlDialog extends Dialog { - @Override - public Button createButton() { - return new HtmlButton(); - } + @Override + public Button createButton() { + return new HtmlButton(); + } } diff --git a/src/refactoring_guru/factory_method/example/factory/WindowsDialog.java b/src/refactoring_guru/factory_method/example/factory/WindowsDialog.java index c6defc1..3dd8f51 100644 --- a/src/refactoring_guru/factory_method/example/factory/WindowsDialog.java +++ b/src/refactoring_guru/factory_method/example/factory/WindowsDialog.java @@ -5,13 +5,13 @@ /** * EN: Windows Dialog will produce Windows buttons. - *

+ * * RU: Диалог на элементах операционной системы. */ public class WindowsDialog extends Dialog { - @Override - public Button createButton() { - return new WindowsButton(); - } + @Override + public Button createButton() { + return new WindowsButton(); + } } diff --git a/src/refactoring_guru/flyweight/example/Demo.java b/src/refactoring_guru/flyweight/example/Demo.java index 8d5d96d..2f5b9f7 100644 --- a/src/refactoring_guru/flyweight/example/Demo.java +++ b/src/refactoring_guru/flyweight/example/Demo.java @@ -2,36 +2,35 @@ import refactoring_guru.flyweight.example.forest.Forest; -import java.util.Random; +import java.awt.*; public class Demo { - static final int CANVAS_SIZE = 500; - static final int TREES_TO_DRAW = 1000000; - static final int TREE_TYPES = 2; + static int CANVAS_SIZE = 500; + static int TREES_TO_DRAW = 1000000; + static int TREE_TYPES = 2; - public static void main(String[] args) { - Forest forest = new Forest(); - int treesPerType = TREES_TO_DRAW / TREE_TYPES; - Random random = new Random(); + public static void main(String[] args) { + Forest forest = new Forest(); + for (int i = 0; i < Math.floor(TREES_TO_DRAW / TREE_TYPES); i++) { + forest.plantTree(random(0, CANVAS_SIZE), random(0, CANVAS_SIZE), + "Summer Oak", Color.GREEN, "Oak texture stub"); + forest.plantTree(random(0, CANVAS_SIZE), random(0, CANVAS_SIZE), + "Autumn Oak", Color.ORANGE, "Autumn Oak texture stub"); + } + forest.setSize(CANVAS_SIZE, CANVAS_SIZE); + forest.setVisible(true); - for (int i = 0; i < treesPerType; i++) { - forest.plantTree(random.nextInt(CANVAS_SIZE), random.nextInt(CANVAS_SIZE), "Summer Oak"); - forest.plantTree(random.nextInt(CANVAS_SIZE), random.nextInt(CANVAS_SIZE), "Autumn Oak"); + System.out.println(TREES_TO_DRAW + " trees drawn"); + System.out.println("---------------------"); + System.out.println("Memory usage:"); + System.out.println("Tree size (8 bytes) * " + TREES_TO_DRAW); + System.out.println("+ TreeTypes size (~30 bytes) * " + TREE_TYPES + ""); + System.out.println("---------------------"); + System.out.println("Total: " + ((TREES_TO_DRAW * 8 + TREE_TYPES * 30) / 1024 / 1024) + + "MB (instead of " + ((TREES_TO_DRAW * 38) / 1024 / 1024) + "MB)"); } - forest.setSize(CANVAS_SIZE, CANVAS_SIZE); - forest.setVisible(true); - logStatistics(); - } - - private static void logStatistics() { - System.out.println(TREES_TO_DRAW + " trees drawn"); - System.out.println("---------------------"); - System.out.println("Memory usage:"); - System.out.println("Tree size (8 bytes) * " + TREES_TO_DRAW); - System.out.println("+ TreeTypes size (~30 bytes) * " + TREE_TYPES); - System.out.println("---------------------"); - System.out.println("Total: " + ((TREES_TO_DRAW * 8 + TREE_TYPES * 30) / 1024 / 1024) + - "MB (instead of " + ((TREES_TO_DRAW * 38) / 1024 / 1024) + "MB)"); - } + private static int random(int min, int max) { + return min + (int) (Math.random() * ((max - min) + 1)); + } } diff --git a/src/refactoring_guru/flyweight/example/forest/Forest.java b/src/refactoring_guru/flyweight/example/forest/Forest.java index 5fbfb53..7dff7a4 100644 --- a/src/refactoring_guru/flyweight/example/forest/Forest.java +++ b/src/refactoring_guru/flyweight/example/forest/Forest.java @@ -10,18 +10,18 @@ import java.util.List; public class Forest extends JFrame { - private final List trees = new ArrayList<>(); + private List trees = new ArrayList<>(); - public void plantTree(int x, int y, String name) { - TreeType type = TreeFactory.getTreeType(name); - Tree tree = new Tree(x, y, type); - trees.add(tree); - } + public void plantTree(int x, int y, String name, Color color, String otherTreeData) { + TreeType type = TreeFactory.getTreeType(name, color, otherTreeData); + Tree tree = new Tree(x, y, type); + trees.add(tree); + } - @Override - public void paint(Graphics graphics) { - for (Tree tree : trees) { - tree.draw(graphics); + @Override + public void paint(Graphics graphics) { + for (Tree tree : trees) { + tree.draw(graphics); + } } - } } diff --git a/src/refactoring_guru/flyweight/example/trees/Tree.java b/src/refactoring_guru/flyweight/example/trees/Tree.java index 5bb7493..d86e5ea 100644 --- a/src/refactoring_guru/flyweight/example/trees/Tree.java +++ b/src/refactoring_guru/flyweight/example/trees/Tree.java @@ -3,17 +3,17 @@ import java.awt.*; public class Tree { - private final int xCoordinate; - private final int yCoordinate; - private final TreeType treeType; + private int x; + private int y; + private TreeType type; - public Tree(int xCoordinate, int yCoordinate, TreeType treeType) { - this.xCoordinate = xCoordinate; - this.yCoordinate = yCoordinate; - this.treeType = treeType; - } + public Tree(int x, int y, TreeType type) { + this.x = x; + this.y = y; + this.type = type; + } - public void draw(Graphics g) { - treeType.draw(g, xCoordinate, yCoordinate); - } + public void draw(Graphics g) { + type.draw(g, x, y); + } } diff --git a/src/refactoring_guru/flyweight/example/trees/TreeFactory.java b/src/refactoring_guru/flyweight/example/trees/TreeFactory.java index 7a6016c..5f4f9fe 100644 --- a/src/refactoring_guru/flyweight/example/trees/TreeFactory.java +++ b/src/refactoring_guru/flyweight/example/trees/TreeFactory.java @@ -1,16 +1,18 @@ package refactoring_guru.flyweight.example.trees; +import java.awt.*; import java.util.HashMap; import java.util.Map; -public final class TreeFactory { - private static final Map treeTypes = new HashMap<>(); +public class TreeFactory { + static Map treeTypes = new HashMap<>(); - private TreeFactory() throws InstantiationException { - throw new InstantiationException("Cannot create an instance of this class"); - } - - public static TreeType getTreeType(String name) { - return treeTypes.computeIfAbsent(name, k -> getTreeType(name)); - } + public static TreeType getTreeType(String name, Color color, String otherTreeData) { + TreeType result = treeTypes.get(name); + if (result == null) { + result = new TreeType(name, color, otherTreeData); + treeTypes.put(name, result); + } + return result; + } } diff --git a/src/refactoring_guru/flyweight/example/trees/TreeType.java b/src/refactoring_guru/flyweight/example/trees/TreeType.java index 32cea46..73c720b 100644 --- a/src/refactoring_guru/flyweight/example/trees/TreeType.java +++ b/src/refactoring_guru/flyweight/example/trees/TreeType.java @@ -3,16 +3,20 @@ import java.awt.*; public class TreeType { - private final Color color; + private String name; + private Color color; + private String otherTreeData; - public TreeType(Color color) { - this.color = color; - } + public TreeType(String name, Color color, String otherTreeData) { + this.name = name; + this.color = color; + this.otherTreeData = otherTreeData; + } - public void draw(Graphics g, int x, int y) { - g.setColor(Color.BLACK); - g.fillRect(x - 1, y, 3, 5); - g.setColor(color); - g.fillOval(x - 5, y - 10, 10, 10); - } + public void draw(Graphics g, int x, int y) { + g.setColor(Color.BLACK); + g.fillRect(x - 1, y, 3, 5); + g.setColor(color); + g.fillOval(x - 5, y - 10, 10, 10); + } } diff --git a/src/refactoring_guru/iterator/example/Demo.java b/src/refactoring_guru/iterator/example/Demo.java index fb3b9cb..31ff314 100644 --- a/src/refactoring_guru/iterator/example/Demo.java +++ b/src/refactoring_guru/iterator/example/Demo.java @@ -7,58 +7,46 @@ import refactoring_guru.iterator.example.spammer.SocialSpammer; import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Scanner; /** * EN: Demo class. Everything comes together here. - *

+ * * RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - private static final Scanner scanner = new Scanner(System.in); - private static final String ANNA_EMAIL = "anna.smith@bing.com"; - - public static void main(String[] args) { - System.out.println("Please specify the social network to target the spam tool (default: Facebook):"); - System.out.println("1. Facebook"); - System.out.println("2. LinkedIn"); - String choice = scanner.nextLine(); - - SocialNetwork network = (choice.equals("2")) ? new LinkedIn(createTestProfiles()) : new Facebook(createTestProfiles()); - - SocialSpammer spammer = new SocialSpammer(network); - spammer.sendSpamToFriends(ANNA_EMAIL, - "Hey! This is Anna's friend Josh. Can you do me a favor and like this post [link]?"); - spammer.sendSpamToCoworkers(ANNA_EMAIL, - "Hey! This is Anna's boss Jason. Anna told me you would be interested in [link]."); - } - - @SuppressWarnings("all") - private static List createTestProfiles() { - List data = new ArrayList<>(); - data.add(createProfile(ANNA_EMAIL, "Anna Smith", "friends", "mad_max@ya.com", "catwoman@yahoo.com", "coworkers", "sam@amazon.com")); - data.add(createProfile("mad_max@ya.com", "Maximilian", "friends", ANNA_EMAIL, "coworkers", "sam@amazon.com")); - data.add(createProfile("bill@microsoft.eu", "Billie", "coworkers", "avanger@ukr.net")); - data.add(createProfile("avanger@ukr.net", "John Day", "coworkers", "bill@microsoft.eu")); - data.add(createProfile("sam@amazon.com", "Sam Kitting", "coworkers", ANNA_EMAIL, "mad_max@ya.com", "friends", "catwoman@yahoo.com")); - data.add(createProfile("catwoman@yahoo.com", "Liza", "friends", ANNA_EMAIL, "sam@amazon.com")); - return data; - } + public static Scanner scanner = new Scanner(System.in); + + public static void main(String[] args) { + System.out.println("Please specify social network to target spam tool (default:Facebook):"); + System.out.println("1. Facebook"); + System.out.println("2. LinkedIn"); + String choice = scanner.nextLine(); + + SocialNetwork network; + if (choice.equals("2")) { + network = new LinkedIn(createTestProfiles()); + } + else { + network = new Facebook(createTestProfiles()); + } + + SocialSpammer spammer = new SocialSpammer(network); + spammer.sendSpamToFriends("anna.smith@bing.com", + "Hey! This is Anna's friend Josh. Can you do me a favor and like this post [link]?"); + spammer.sendSpamToCoworkers("anna.smith@bing.com", + "Hey! This is Anna's boss Jason. Anna told me you would be interested in [link]."); + } - private static Profile createProfile(String email, String name, String... contacts) { - Map> contactMap = new HashMap<>(); - for (int i = 0; i < contacts.length; i += 2) { - var contactType = contacts[i]; - var contactEmail = contacts[i + 1]; - contactMap.merge(contactType, new ArrayList<>(Collections.singletonList(contactEmail)), (oldList, newList) -> { - oldList.addAll(newList); - return oldList; - }); + public static List createTestProfiles() { + List data = new ArrayList(); + data.add(new Profile("anna.smith@bing.com", "Anna Smith", "friends:mad_max@ya.com", "friends:catwoman@yahoo.com", "coworkers:sam@amazon.com")); + data.add(new Profile("mad_max@ya.com", "Maximilian", "friends:anna.smith@bing.com", "coworkers:sam@amazon.com")); + data.add(new Profile("bill@microsoft.eu", "Billie", "coworkers:avanger@ukr.net")); + data.add(new Profile("avanger@ukr.net", "John Day", "coworkers:bill@microsoft.eu")); + data.add(new Profile("sam@amazon.com", "Sam Kitting", "coworkers:anna.smith@bing.com", "coworkers:mad_max@ya.com", "friends:catwoman@yahoo.com")); + data.add(new Profile("catwoman@yahoo.com", "Liza", "friends:anna.smith@bing.com", "friends:sam@amazon.com")); + return data; } - return new Profile(email, name, contactMap); - } -} +} \ No newline at end of file diff --git a/src/refactoring_guru/iterator/example/iterators/FacebookIterator.java b/src/refactoring_guru/iterator/example/iterators/FacebookIterator.java index c1d471f..1efb222 100644 --- a/src/refactoring_guru/iterator/example/iterators/FacebookIterator.java +++ b/src/refactoring_guru/iterator/example/iterators/FacebookIterator.java @@ -7,53 +7,53 @@ import java.util.List; public class FacebookIterator implements ProfileIterator { - private final Facebook facebook; - private final String type; - private final String email; - private int currentPosition = 0; - private final List emails = new ArrayList<>(); - private final List profiles = new ArrayList<>(); - - public FacebookIterator(Facebook facebook, String type, String email) { - this.facebook = facebook; - this.type = type; - this.email = email; - } - - @Override - public boolean hasNext() { - lazyLoad(); - return currentPosition < emails.size(); - } - - @Override - public Profile getNext() { - if (!hasNext()) { - throw new IllegalArgumentException("Next is null "); + private Facebook facebook; + private String type; + private String email; + private int currentPosition = 0; + private List emails = new ArrayList<>(); + private List profiles = new ArrayList<>(); + + public FacebookIterator(Facebook facebook, String type, String email) { + this.facebook = facebook; + this.type = type; + this.email = email; } - String friendEmail = emails.get(currentPosition); - Profile friendProfile = profiles.get(currentPosition); - if (friendProfile == null) { - friendProfile = facebook.requestProfileFromFacebook(friendEmail); - profiles.set(currentPosition, friendProfile); + private void lazyLoad() { + if (emails.size() == 0) { + List profiles = facebook.requestProfileFriendsFromFacebook(this.email, this.type); + for (String profile : profiles) { + this.emails.add(profile); + this.profiles.add(null); + } + } } - currentPosition++; - return friendProfile; - } - - @Override - public void reset() { - currentPosition = 0; - } - - private void lazyLoad() { - if (emails.isEmpty()) { - List socialProfiles = facebook.requestProfileFriendsFromFacebook(this.email, this.type); - for (String profile : socialProfiles) { - this.emails.add(profile); - this.profiles.add(null); - } + + @Override + public boolean hasNext() { + lazyLoad(); + return currentPosition < emails.size(); + } + + @Override + public Profile getNext() { + if (!hasNext()) { + return null; + } + + String friendEmail = emails.get(currentPosition); + Profile friendProfile = profiles.get(currentPosition); + if (friendProfile == null) { + friendProfile = facebook.requestProfileFromFacebook(friendEmail); + profiles.set(currentPosition, friendProfile); + } + currentPosition++; + return friendProfile; + } + + @Override + public void reset() { + currentPosition = 0; } - } } diff --git a/src/refactoring_guru/iterator/example/iterators/LinkedInIterator.java b/src/refactoring_guru/iterator/example/iterators/LinkedInIterator.java index 48a320d..92d4fcc 100644 --- a/src/refactoring_guru/iterator/example/iterators/LinkedInIterator.java +++ b/src/refactoring_guru/iterator/example/iterators/LinkedInIterator.java @@ -7,53 +7,53 @@ import java.util.List; public class LinkedInIterator implements ProfileIterator { - private final LinkedIn linkedIn; - private final String type; - private final String email; - private int currentPosition = 0; - private final List emails = new ArrayList<>(); - private final List contacts = new ArrayList<>(); - - public LinkedInIterator(LinkedIn linkedIn, String type, String email) { - this.linkedIn = linkedIn; - this.type = type; - this.email = email; - } - - @Override - public boolean hasNext() { - lazyLoad(); - return currentPosition < emails.size(); - } - - @Override - public Profile getNext() { - if (!hasNext()) { - throw new IllegalArgumentException("Next is null "); + private LinkedIn linkedIn; + private String type; + private String email; + private int currentPosition = 0; + private List emails = new ArrayList<>(); + private List contacts = new ArrayList<>(); + + public LinkedInIterator(LinkedIn linkedIn, String type, String email) { + this.linkedIn = linkedIn; + this.type = type; + this.email = email; } - String friendEmail = emails.get(currentPosition); - Profile friendContact = contacts.get(currentPosition); - if (friendContact == null) { - friendContact = linkedIn.requestContactInfoFromLinkedInAPI(friendEmail); - contacts.set(currentPosition, friendContact); + private void lazyLoad() { + if (emails.size() == 0) { + List profiles = linkedIn.requestRelatedContactsFromLinkedInAPI(this.email, this.type); + for (String profile : profiles) { + this.emails.add(profile); + this.contacts.add(null); + } + } } - currentPosition++; - return friendContact; - } - - @Override - public void reset() { - currentPosition = 0; - } - - private void lazyLoad() { - if (emails.isEmpty()) { - List profiles = linkedIn.requestRelatedContactsFromLinkedInAPI(this.email, this.type); - for (String profile : profiles) { - this.emails.add(profile); - this.contacts.add(null); - } + + @Override + public boolean hasNext() { + lazyLoad(); + return currentPosition < emails.size(); + } + + @Override + public Profile getNext() { + if (!hasNext()) { + return null; + } + + String friendEmail = emails.get(currentPosition); + Profile friendContact = contacts.get(currentPosition); + if (friendContact == null) { + friendContact = linkedIn.requestContactInfoFromLinkedInAPI(friendEmail); + contacts.set(currentPosition, friendContact); + } + currentPosition++; + return friendContact; + } + + @Override + public void reset() { + currentPosition = 0; } - } } diff --git a/src/refactoring_guru/iterator/example/iterators/ProfileIterator.java b/src/refactoring_guru/iterator/example/iterators/ProfileIterator.java index 411dd01..f07b7be 100644 --- a/src/refactoring_guru/iterator/example/iterators/ProfileIterator.java +++ b/src/refactoring_guru/iterator/example/iterators/ProfileIterator.java @@ -3,9 +3,9 @@ import refactoring_guru.iterator.example.profile.Profile; public interface ProfileIterator { - boolean hasNext(); + boolean hasNext(); - Profile getNext(); + Profile getNext(); - void reset(); + void reset(); } \ No newline at end of file diff --git a/src/refactoring_guru/iterator/example/profile/Profile.java b/src/refactoring_guru/iterator/example/profile/Profile.java index dd322e4..ed49864 100644 --- a/src/refactoring_guru/iterator/example/profile/Profile.java +++ b/src/refactoring_guru/iterator/example/profile/Profile.java @@ -1,68 +1,49 @@ package refactoring_guru.iterator.example.profile; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class Profile { - private final String name; - private final String email; - private final Map> contacts = new HashMap<>(); + private String name; + private String email; + private Map> contacts = new HashMap<>(); - /** - * Constructs a new Profile. - * - * @param email the email address of the profile - * @param name the name of the profile - * @param contacts the contact list categorized by contact type - */ - public Profile(String email, String name, Map> contacts) { - this.email = email; - this.name = name; - this.contacts.putAll(contacts); - } + public Profile(String email, String name, String... contacts) { + this.email = email; + this.name = name; - /** - * Returns the email address of this profile. - * - * @return the email address - */ - public String getEmail() { - return email; - } + // Parse contact list from a set of "friend:email@gmail.com" pairs. + for (String contact : contacts) { + String[] parts = contact.split(":"); + String contactType = "friend", contactEmail; + if (parts.length == 1) { + contactEmail = parts[0]; + } + else { + contactType = parts[0]; + contactEmail = parts[1]; + } + if (!this.contacts.containsKey(contactType)) { + this.contacts.put(contactType, new ArrayList<>()); + } + this.contacts.get(contactType).add(contactEmail); + } + } - /** - * Returns the name of this profile. - * - * @return the name - */ - public String getName() { - return name; - } + public String getEmail() { + return email; + } - /** - * Returns an unmodifiable list of contacts of the specified type. - * - * @param contactType the type of contacts to retrieve - * @return an unmodifiable list of contacts - */ - public List getContacts(String contactType) { - List contactList = contacts.computeIfAbsent(contactType, k -> new ArrayList<>()); - return Collections.unmodifiableList(contactList); - } + public String getName() { + return name; + } - /** - * Adds a contact to this profile. - * - * @param contactType the type of contact - * @param contactEmail the email address of the contact - */ - public void addContact(String contactType, String contactEmail) { - contacts.merge(contactType, new ArrayList<>(List.of(contactEmail)), (oldList, newList) -> { - oldList.addAll(newList); - return oldList; - }); - } + public List getContacts(String contactType) { + if (!this.contacts.containsKey(contactType)) { + this.contacts.put(contactType, new ArrayList<>()); + } + return contacts.get(contactType); + } } \ No newline at end of file diff --git a/src/refactoring_guru/iterator/example/social_networks/Facebook.java b/src/refactoring_guru/iterator/example/social_networks/Facebook.java index d2e294a..7c6e6f3 100644 --- a/src/refactoring_guru/iterator/example/social_networks/Facebook.java +++ b/src/refactoring_guru/iterator/example/social_networks/Facebook.java @@ -6,77 +6,81 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; public class Facebook implements SocialNetwork { - private final List profiles; + private List profiles; - public Facebook(List cache) { - this.profiles = Objects.requireNonNullElseGet(cache, ArrayList::new); - } + public Facebook(List cache) { + if (cache != null) { + this.profiles = cache; + } else { + this.profiles = new ArrayList<>(); + } + } + + public Profile requestProfileFromFacebook(String profileEmail) { + // EN: Here would be a POST request to one of the Facebook API + // endpoints. Instead, we emulates long network connection, which you + // would expect in the real life... + // + // RU: Здесь бы был POST запрос к одному из адресов API Facebook. Но + // вместо этого мы эмулируем долгое сетевое соединение, прямо как в + // реальной жизни... + simulateNetworkLatency(); + System.out.println("Facebook: Loading profile '" + profileEmail + "' over the network..."); + + // EN: ...and return test data. + // + // RU: ...и возвращаем тестовые данные. + return findProfile(profileEmail); + } - /** - * EN: Here would be a POST request to one of the Facebook API - * endpoints. Instead, we emulates long network connection, which you - * would expect in the real life - *

- * RU: Здесь бы был POST запрос к одному из адресов API Facebook. Но - * вместо этого мы эмулируем долгое сетевое соединение, прямо как в - * реальной жизни - * - * @param profileEmail provided the profile mail - * @return expected result - */ - public Profile requestProfileFromFacebook(String profileEmail) { - simulateNetworkLatency(); - System.out.println("Facebook: Loading profile '" + profileEmail + "' over the network..."); - return findProfile(profileEmail); - } + public List requestProfileFriendsFromFacebook(String profileEmail, String contactType) { + // EN: Here would be a POST request to one of the Facebook API + // endpoints. Instead, we emulates long network connection, which you + // would expect in the real life... + // + // RU: Здесь бы был POST запрос к одному из адресов API Facebook. Но + // вместо этого мы эмулируем долгое сетевое соединение, прямо как в + // реальной жизни... + simulateNetworkLatency(); + System.out.println("Facebook: Loading '" + contactType + "' list of '" + profileEmail + "' over the network..."); - /** - * EN: Here would be a POST request to one of the Facebook API - * endpoints. Instead, we emulates long network connection, which you - * would expect in the real life - *

- * RU: Здесь бы был POST запрос к одному из адресов API Facebook. Но - * вместо этого мы эмулируем долгое сетевое соединение, прямо как в - * реальной жизни - * - * @param profileEmail provided the profile mail - * @param contactType concrete type of given contact - * @return given data - */ - public List requestProfileFriendsFromFacebook(String profileEmail, String contactType) { - simulateNetworkLatency(); - System.out.println("Facebook: Loading '" + contactType + "' list of '" + profileEmail + "' over the network..."); - Profile profile = findProfile(profileEmail); - return profile.getContacts(contactType); - } + // EN: ...and return test data. + // + // RU: ...и возвращаем тестовые данные. + Profile profile = findProfile(profileEmail); + if (profile != null) { + return profile.getContacts(contactType); + } + return null; + } + + private Profile findProfile(String profileEmail) { + for (Profile profile : profiles) { + if (profile.getEmail().equals(profileEmail)) { + return profile; + } + } + return null; + } - private Profile findProfile(String profileEmail) { - for (Profile profile : profiles) { - if (profile.getEmail().equals(profileEmail)) { - return profile; - } + private void simulateNetworkLatency() { + try { + Thread.sleep(2500); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } } - throw new IllegalArgumentException("Profile isn't found"); - } - private void simulateNetworkLatency() { - try { - Thread.sleep(2500); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); + @Override + public ProfileIterator createFriendsIterator(String profileEmail) { + return new FacebookIterator(this, "friends", profileEmail); } - } - @Override - public ProfileIterator createFriendsIterator(String profileEmail) { - return new FacebookIterator(this, "friends", profileEmail); - } + @Override + public ProfileIterator createCoworkersIterator(String profileEmail) { + return new FacebookIterator(this, "coworkers", profileEmail); + } - @Override - public ProfileIterator createCoworkersIterator(String profileEmail) { - return new FacebookIterator(this, "coworkers", profileEmail); - } } \ No newline at end of file diff --git a/src/refactoring_guru/iterator/example/social_networks/LinkedIn.java b/src/refactoring_guru/iterator/example/social_networks/LinkedIn.java index d1938c4..28b1965 100644 --- a/src/refactoring_guru/iterator/example/social_networks/LinkedIn.java +++ b/src/refactoring_guru/iterator/example/social_networks/LinkedIn.java @@ -5,68 +5,81 @@ import refactoring_guru.iterator.example.profile.Profile; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Objects; public class LinkedIn implements SocialNetwork { - private final List contacts; + private List contacts; - public LinkedIn(List cache) { - this.contacts = Objects.requireNonNullElseGet(cache, ArrayList::new); - } + public LinkedIn(List cache) { + if (cache != null) { + this.contacts = cache; + } else { + this.contacts = new ArrayList<>(); + } + } + + public Profile requestContactInfoFromLinkedInAPI(String profileEmail) { + // EN: Here would be a POST request to one of the LinkedIn API + // endpoints. Instead, we emulates long network connection, which you + // would expect in the real life... + // + // RU: Здесь бы был POST запрос к одному из адресов API LinkedIn. Но + // вместо этого мы эмулируем долгое сетевое соединение, прямо как в + // реальной жизни... + simulateNetworkLatency(); + System.out.println("LinkedIn: Loading profile '" + profileEmail + "' over the network..."); + + // EN: ...and return test data. + // + // RU: ...и возвращаем тестовые данные. + return findContact(profileEmail); + } - /** - * EN: Here would be a POST request to one of the LinkedIn API - * endpoints. Instead, we emulates long network connection, which you - * would expect in the real life... - *

- * RU: Здесь бы был POST запрос к одному из адресов API LinkedIn. Но - * вместо этого мы эмулируем долгое сетевое соединение, прямо как в - * реальной жизни - * @param profileEmail the given mail - * @return the data - */ - public Profile requestContactInfoFromLinkedInAPI(String profileEmail) { - simulateNetworkLatency(); - System.out.println("LinkedIn: Loading profile '" + profileEmail + "' over the network..."); - return findContact(profileEmail); - } + public List requestRelatedContactsFromLinkedInAPI(String profileEmail, String contactType) { + // EN: Here would be a POST request to one of the LinkedIn API + // endpoints. Instead, we emulates long network connection, which you + // would expect in the real life. + // + // RU: Здесь бы был POST запрос к одному из адресов API LinkedIn. Но + // вместо этого мы эмулируем долгое сетевое соединение, прямо как в + // реальной жизни... + simulateNetworkLatency(); + System.out.println("LinkedIn: Loading '" + contactType + "' list of '" + profileEmail + "' over the network..."); - public List requestRelatedContactsFromLinkedInAPI(String profileEmail, String contactType) { - simulateNetworkLatency(); - System.out.println("LinkedIn: Loading '" + contactType + "' list of '" + profileEmail + "' over the network..."); - Profile profile = findContact(profileEmail); - if (profile != null) { - return profile.getContacts(contactType); + // EN: ...and return test data. + // + // RU: ...и возвращаем тестовые данные. + Profile profile = findContact(profileEmail); + if (profile != null) { + return profile.getContacts(contactType); + } + return null; } - return Collections.emptyList(); - } - private Profile findContact(String profileEmail) { - for (Profile profile : contacts) { - if (profile.getEmail().equals(profileEmail)) { - return profile; - } + private Profile findContact(String profileEmail) { + for (Profile profile : contacts) { + if (profile.getEmail().equals(profileEmail)) { + return profile; + } + } + return null; } - throw new IllegalArgumentException("Contact isn't found"); - } - private void simulateNetworkLatency() { - try { - Thread.sleep(2500); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); + private void simulateNetworkLatency() { + try { + Thread.sleep(2500); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } } - } - @Override - public ProfileIterator createFriendsIterator(String profileEmail) { - return new LinkedInIterator(this, "friends", profileEmail); - } + @Override + public ProfileIterator createFriendsIterator(String profileEmail) { + return new LinkedInIterator(this, "friends", profileEmail); + } - @Override - public ProfileIterator createCoworkersIterator(String profileEmail) { - return new LinkedInIterator(this, "coworkers", profileEmail); - } + @Override + public ProfileIterator createCoworkersIterator(String profileEmail) { + return new LinkedInIterator(this, "coworkers", profileEmail); + } } diff --git a/src/refactoring_guru/iterator/example/social_networks/SocialNetwork.java b/src/refactoring_guru/iterator/example/social_networks/SocialNetwork.java index c1d0a64..65597af 100644 --- a/src/refactoring_guru/iterator/example/social_networks/SocialNetwork.java +++ b/src/refactoring_guru/iterator/example/social_networks/SocialNetwork.java @@ -3,7 +3,7 @@ import refactoring_guru.iterator.example.iterators.ProfileIterator; public interface SocialNetwork { - ProfileIterator createFriendsIterator(String profileEmail); + ProfileIterator createFriendsIterator(String profileEmail); - ProfileIterator createCoworkersIterator(String profileEmail); + ProfileIterator createCoworkersIterator(String profileEmail); } diff --git a/src/refactoring_guru/iterator/example/spammer/SocialSpammer.java b/src/refactoring_guru/iterator/example/spammer/SocialSpammer.java index 648d848..9e6c99a 100644 --- a/src/refactoring_guru/iterator/example/spammer/SocialSpammer.java +++ b/src/refactoring_guru/iterator/example/spammer/SocialSpammer.java @@ -5,32 +5,32 @@ import refactoring_guru.iterator.example.social_networks.SocialNetwork; public class SocialSpammer { - public SocialNetwork network; - public ProfileIterator iterator; + public SocialNetwork network; + public ProfileIterator iterator; - public SocialSpammer(SocialNetwork network) { - this.network = network; - } + public SocialSpammer(SocialNetwork network) { + this.network = network; + } - public void sendSpamToFriends(String profileEmail, String message) { - System.out.println("\nIterating over friends...\n"); - iterator = network.createFriendsIterator(profileEmail); - while (iterator.hasNext()) { - Profile profile = iterator.getNext(); - sendMessage(profile.getEmail(), message); + public void sendSpamToFriends(String profileEmail, String message) { + System.out.println("\nIterating over friends...\n"); + iterator = network.createFriendsIterator(profileEmail); + while (iterator.hasNext()) { + Profile profile = iterator.getNext(); + sendMessage(profile.getEmail(), message); + } } - } - public void sendSpamToCoworkers(String profileEmail, String message) { - System.out.println("\nIterating over coworkers...\n"); - iterator = network.createCoworkersIterator(profileEmail); - while (iterator.hasNext()) { - Profile profile = iterator.getNext(); - sendMessage(profile.getEmail(), message); + public void sendSpamToCoworkers(String profileEmail, String message) { + System.out.println("\nIterating over coworkers...\n"); + iterator = network.createCoworkersIterator(profileEmail); + while (iterator.hasNext()) { + Profile profile = iterator.getNext(); + sendMessage(profile.getEmail(), message); + } } - } - public void sendMessage(String email, String message) { - System.out.println("Sent a message to: '" + email + "'. Message body: '" + message + "'"); - } + public void sendMessage(String email, String message) { + System.out.println("Sent message to: '" + email + "'. Message body: '" + message + "'"); + } } \ No newline at end of file diff --git a/src/refactoring_guru/mediator/example/Demo.java b/src/refactoring_guru/mediator/example/Demo.java index ec160df..14f5612 100644 --- a/src/refactoring_guru/mediator/example/Demo.java +++ b/src/refactoring_guru/mediator/example/Demo.java @@ -3,38 +3,26 @@ import refactoring_guru.mediator.example.components.*; import refactoring_guru.mediator.example.mediator.Editor; import refactoring_guru.mediator.example.mediator.Mediator; -import refactoring_guru.mediator.example.mediator.Note; import javax.swing.*; /** * EN: Demo class. Everything comes together here. - *

+ * * RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - public static void main(String[] args) { - Mediator mediator = new Editor(); - ListModel noteList = new AbstractListModel<>() { - @Override - public int getSize() { - return 0; - } + public static void main(String[] args) { + Mediator mediator = new Editor(); - @Override - public Note getElementAt(int i) { - return null; - } - }; + mediator.registerComponent(new Title()); + mediator.registerComponent(new TextBox()); + mediator.registerComponent(new AddButton()); + mediator.registerComponent(new DeleteButton()); + mediator.registerComponent(new SaveButton()); + mediator.registerComponent(new List(new DefaultListModel())); + mediator.registerComponent(new Filter()); - mediator.registerComponent(new Title()); - mediator.registerComponent(new TextBox()); - mediator.registerComponent(new AddButton()); - mediator.registerComponent(new DeleteButton()); - mediator.registerComponent(new SaveButton()); - mediator.registerComponent(new InitList(new DefaultListModel<>())); - mediator.registerComponent(new Filter(mediator, noteList)); - - mediator.createGUI(); - } + mediator.createGUI(); + } } diff --git a/src/refactoring_guru/mediator/example/components/AddButton.java b/src/refactoring_guru/mediator/example/components/AddButton.java index eb56fdf..6c351d4 100644 --- a/src/refactoring_guru/mediator/example/components/AddButton.java +++ b/src/refactoring_guru/mediator/example/components/AddButton.java @@ -9,29 +9,29 @@ /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - *

+ * * RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ public class AddButton extends JButton implements Component { - private transient Mediator mediator; + private Mediator mediator; - public AddButton() { - super("Add"); - } + public AddButton() { + super("Add"); + } - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } - @Override - protected void fireActionPerformed(ActionEvent actionEvent) { - mediator.addNewNote(new Note()); - } + @Override + protected void fireActionPerformed(ActionEvent actionEvent) { + mediator.addNewNote(new Note()); + } - @Override - public String getName() { - return "AddButton"; - } + @Override + public String getName() { + return "AddButton"; + } } diff --git a/src/refactoring_guru/mediator/example/components/Component.java b/src/refactoring_guru/mediator/example/components/Component.java index 14ad5a9..780ff40 100644 --- a/src/refactoring_guru/mediator/example/components/Component.java +++ b/src/refactoring_guru/mediator/example/components/Component.java @@ -4,11 +4,10 @@ /** * EN: Common component interface. - *

+ * * RU: Общий интерфейс компонентов. */ public interface Component { - void setMediator(Mediator mediator); - - String getName(); + void setMediator(Mediator mediator); + String getName(); } diff --git a/src/refactoring_guru/mediator/example/components/DeleteButton.java b/src/refactoring_guru/mediator/example/components/DeleteButton.java index b822bf0..b9389a6 100644 --- a/src/refactoring_guru/mediator/example/components/DeleteButton.java +++ b/src/refactoring_guru/mediator/example/components/DeleteButton.java @@ -8,29 +8,29 @@ /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - *

+ * * RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ -public class DeleteButton extends JButton implements Component { - private transient Mediator mediator; +public class DeleteButton extends JButton implements Component { + private Mediator mediator; - public DeleteButton() { - super("Del"); - } + public DeleteButton() { + super("Del"); + } - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } - @Override - protected void fireActionPerformed(ActionEvent actionEvent) { - mediator.deleteNote(); - } + @Override + protected void fireActionPerformed(ActionEvent actionEvent) { + mediator.deleteNote(); + } - @Override - public String getName() { - return "DelButton"; - } + @Override + public String getName() { + return "DelButton"; + } } diff --git a/src/refactoring_guru/mediator/example/components/Filter.java b/src/refactoring_guru/mediator/example/components/Filter.java index 4fddf08..c60aa0e 100644 --- a/src/refactoring_guru/mediator/example/components/Filter.java +++ b/src/refactoring_guru/mediator/example/components/Filter.java @@ -5,57 +5,61 @@ import javax.swing.*; import java.awt.event.KeyEvent; -import javax.swing.DefaultListModel; +import java.util.ArrayList; /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - *

+ * * RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ public class Filter extends JTextField implements Component { - private transient Mediator mediator; - private transient ListModel listModel; - - public Filter(Mediator mediator, ListModel listModel) { - this.mediator = mediator; - this.listModel = listModel; - } - - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } - - @Override - protected void processComponentKeyEvent(KeyEvent keyEvent) { - String start = getText(); - searchElements(start); - } - - public void setList(ListModel listModel) { - this.listModel = listModel; - } - - private void searchElements(String s) { - if (listModel == null || s.equals("")) { - mediator.setElementsList(listModel); - return; + private Mediator mediator; + private ListModel listModel; + + public Filter() {} + + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; } - DefaultListModel filteredListModel = new DefaultListModel<>(); - for (int i = 0; i < listModel.getSize(); i++) { - Note note = listModel.getElementAt(i); - if (note.getName().contains(s)) { - filteredListModel.addElement(note); - } + @Override + protected void processComponentKeyEvent(KeyEvent keyEvent) { + String start = getText(); + searchElements(start); } - mediator.setElementsList(filteredListModel); - } - @Override - public String getName() { - return "Filter"; - } + public void setList(ListModel listModel) { + this.listModel = listModel; + } + + private void searchElements(String s) { + if (listModel == null) { + return; + } + + if (s.equals("")) { + mediator.setElementsList(listModel); + return; + } + + ArrayList notes = new ArrayList<>(); + for (int i = 0; i < listModel.getSize(); i++) { + notes.add((Note) listModel.getElementAt(i)); + } + DefaultListModel listModel = new DefaultListModel<>(); + for (Note note : notes) { + if (note.getName().contains(s)) { + listModel.addElement(note); + } + } + mediator.setElementsList(listModel); + } + + @Override + public String getName() { + return "Filter"; + } } diff --git a/src/refactoring_guru/mediator/example/components/InitList.java b/src/refactoring_guru/mediator/example/components/InitList.java deleted file mode 100644 index 5159de0..0000000 --- a/src/refactoring_guru/mediator/example/components/InitList.java +++ /dev/null @@ -1,74 +0,0 @@ -package refactoring_guru.mediator.example.components; - -import refactoring_guru.mediator.example.mediator.Mediator; -import refactoring_guru.mediator.example.mediator.Note; - -import javax.swing.*; - -/** - * EN: Concrete components don't talk with each other. They have only one - * communication channel–sending requests to the mediator. - *

- * RU: Конкретные компоненты никак не связаны между собой. У них есть только - * один канал общения – через отправку уведомлений посреднику. - */ -@SuppressWarnings("unchecked") -public class InitList extends JList implements Component { - private transient Mediator mediator; - private final DefaultListModel listModel; - private static final boolean running = true; - - public InitList(DefaultListModel listModel) { - super(listModel); - this.listModel = listModel; - setModel(listModel); - this.setLayoutOrientation(JList.VERTICAL); - Thread thread = new Thread(new Hide(this)); - thread.start(); - } - - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } - - public void addElement(Note note) { - listModel.addElement(note); - int index = listModel.size() - 1; - setSelectedIndex(index); - ensureIndexIsVisible(index); - mediator.sendToFilter(listModel); - } - - public void deleteElement() { - int index = this.getSelectedIndex(); - if (index >= 0 && index < listModel.size()) { - listModel.remove(index); - mediator.sendToFilter(listModel); - } - } - - public Note getCurrentElement() { - return (Note) getSelectedValue(); - } - - @Override - public String getName() { - return "List"; - } - - private class Hide implements Runnable { - private final InitList list; - - Hide(InitList list) { - this.list = list; - } - - @Override - public void run() { - while (running) { - SwingUtilities.invokeLater(() -> mediator.hideElements(list.isSelectionEmpty())); - } - } - } -} diff --git a/src/refactoring_guru/mediator/example/components/List.java b/src/refactoring_guru/mediator/example/components/List.java new file mode 100644 index 0000000..3694ce6 --- /dev/null +++ b/src/refactoring_guru/mediator/example/components/List.java @@ -0,0 +1,82 @@ +package refactoring_guru.mediator.example.components; + +import refactoring_guru.mediator.example.mediator.Mediator; +import refactoring_guru.mediator.example.mediator.Note; + +import javax.swing.*; + +/** + * EN: Concrete components don't talk with each other. They have only one + * communication channel–sending requests to the mediator. + * + * RU: Конкретные компоненты никак не связаны между собой. У них есть только + * один канал общения – через отправку уведомлений посреднику. + */ +@SuppressWarnings("unchecked") +public class List extends JList implements Component { + private Mediator mediator; + private final DefaultListModel LIST_MODEL; + + public List(DefaultListModel listModel) { + super(listModel); + this.LIST_MODEL = listModel; + setModel(listModel); + this.setLayoutOrientation(JList.VERTICAL); + Thread thread = new Thread(new Hide(this)); + thread.start(); + } + + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + public void addElement(Note note) { + LIST_MODEL.addElement(note); + int index = LIST_MODEL.size() - 1; + setSelectedIndex(index); + ensureIndexIsVisible(index); + mediator.sendToFilter(LIST_MODEL); + } + + public void deleteElement() { + int index = this.getSelectedIndex(); + try { + LIST_MODEL.remove(index); + mediator.sendToFilter(LIST_MODEL); + } catch (ArrayIndexOutOfBoundsException ignored) {} + } + + public Note getCurrentElement() { + return (Note)getSelectedValue(); + } + + @Override + public String getName() { + return "List"; + } + + private class Hide implements Runnable { + private List list; + + Hide(List list) { + this.list = list; + } + + @Override + public void run() { + while (true) { + try { + Thread.sleep(300); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + if (list.isSelectionEmpty()) { + mediator.hideElements(true); + } else { + mediator.hideElements(false); + } + } + } + } +} diff --git a/src/refactoring_guru/mediator/example/components/SaveButton.java b/src/refactoring_guru/mediator/example/components/SaveButton.java index 4a417ac..52f897f 100644 --- a/src/refactoring_guru/mediator/example/components/SaveButton.java +++ b/src/refactoring_guru/mediator/example/components/SaveButton.java @@ -8,29 +8,29 @@ /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - *

+ * * RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ public class SaveButton extends JButton implements Component { - private transient Mediator mediator; + private Mediator mediator; - public SaveButton() { - super("Save"); - } + public SaveButton() { + super("Save"); + } - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } - @Override - protected void fireActionPerformed(ActionEvent actionEvent) { - mediator.saveChanges(); - } + @Override + protected void fireActionPerformed(ActionEvent actionEvent) { + mediator.saveChanges(); + } - @Override - public String getName() { - return "SaveButton"; - } + @Override + public String getName() { + return "SaveButton"; + } } diff --git a/src/refactoring_guru/mediator/example/components/TextBox.java b/src/refactoring_guru/mediator/example/components/TextBox.java index 2cabad3..fff5887 100644 --- a/src/refactoring_guru/mediator/example/components/TextBox.java +++ b/src/refactoring_guru/mediator/example/components/TextBox.java @@ -8,25 +8,25 @@ /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - *

+ * * RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ public class TextBox extends JTextArea implements Component { - private transient Mediator mediator; + private Mediator mediator; - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } - @Override - protected void processComponentKeyEvent(KeyEvent keyEvent) { - mediator.markNote(); - } + @Override + protected void processComponentKeyEvent(KeyEvent keyEvent) { + mediator.markNote(); + } - @Override - public String getName() { - return "TextBox"; - } + @Override + public String getName() { + return "TextBox"; + } } diff --git a/src/refactoring_guru/mediator/example/components/Title.java b/src/refactoring_guru/mediator/example/components/Title.java index e15d555..4f0e0b9 100644 --- a/src/refactoring_guru/mediator/example/components/Title.java +++ b/src/refactoring_guru/mediator/example/components/Title.java @@ -8,25 +8,25 @@ /** * EN: Concrete components don't talk with each other. They have only one * communication channel–sending requests to the mediator. - *

+ * * RU: Конкретные компоненты никак не связаны между собой. У них есть только * один канал общения – через отправку уведомлений посреднику. */ public class Title extends JTextField implements Component { - private transient Mediator mediator; + private Mediator mediator; - @Override - public void setMediator(Mediator mediator) { - this.mediator = mediator; - } + @Override + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } - @Override - protected void processComponentKeyEvent(KeyEvent keyEvent) { - mediator.markNote(); - } + @Override + protected void processComponentKeyEvent(KeyEvent keyEvent) { + mediator.markNote(); + } - @Override - public String getName() { - return "Title"; - } + @Override + public String getName() { + return "Title"; + } } diff --git a/src/refactoring_guru/mediator/example/mediator/Editor.java b/src/refactoring_guru/mediator/example/mediator/Editor.java index c506569..d60ff2a 100644 --- a/src/refactoring_guru/mediator/example/mediator/Editor.java +++ b/src/refactoring_guru/mediator/example/mediator/Editor.java @@ -2,191 +2,201 @@ import refactoring_guru.mediator.example.components.*; import refactoring_guru.mediator.example.components.Component; -import refactoring_guru.mediator.example.components.InitList; +import refactoring_guru.mediator.example.components.List; import javax.swing.*; import javax.swing.border.LineBorder; import java.awt.*; -import java.util.logging.Level; -import java.util.logging.Logger; /** * EN: Concrete mediator. All chaotic communications between concrete components * have been extracted to the mediator. Now components only talk with the * mediator, which knows who has to handle a request. - *

+ * * RU: Конкретный посредник. Все связи между конкретными компонентами переехали * в код посредника. Он получает извещения от своих компонентов и знает как на * них реагировать. */ public class Editor implements Mediator { - private Title title; - private TextBox textBox; - private AddButton add; - private DeleteButton del; - private SaveButton save; - private InitList list; - private Filter filter; - - private final JLabel titleLabel = new JLabel("Title:"); - private final JLabel textLabel = new JLabel("Text:"); - private final JLabel label = new JLabel("Add or select existing note to proceed..."); - - /** - * EN: Here the registration of components by the mediator. - *

- * RU: Здесь происходит регистрация компонентов посредником. - */ - @Override - public void registerComponent(Component component) { - component.setMediator(this); - switch (component.getName()) { - case "AddButton" -> add = (AddButton) component; - case "DelButton" -> del = (DeleteButton) component; - case "Filter" -> filter = (Filter) component; - case "List" -> list = (InitList) component; // assign the component to list - case "SaveButton" -> save = (SaveButton) component; - case "TextBox" -> textBox = (TextBox) component; - case "Title" -> title = (Title) component; - default -> Logger.getLogger(Editor.class.getName()) - .log(Level.WARNING, () -> "Unknown component: " + component.getName()); - } - - if (list != null) { - list.addListSelectionListener(listSelectionEvent -> { - Note note = (Note) list.getSelectedValue(); - if (note != null) { - getInfoFromList(note); - } else { - clear(); + private Title title; + private TextBox textBox; + private AddButton add; + private DeleteButton del; + private SaveButton save; + private List list; + private Filter filter; + + private JLabel titleLabel = new JLabel("Title:"); + private JLabel textLabel = new JLabel("Text:"); + private JLabel label = new JLabel("Add or select existing note to proceed..."); + + /** + * EN: Here the registration of components by the mediator. + * + * RU: Здесь происходит регистрация компонентов посредником. + */ + @Override + public void registerComponent(Component component) { + component.setMediator(this); + switch (component.getName()) { + case "AddButton": + add = (AddButton)component; + break; + case "DelButton": + del = (DeleteButton)component; + break; + case "Filter": + filter = (Filter)component; + break; + case "List": + list = (List)component; + this.list.addListSelectionListener(listSelectionEvent -> { + Note note = (Note)list.getSelectedValue(); + if (note != null) { + getInfoFromList(note); + } else { + clear(); + } + }); + break; + case "SaveButton": + save = (SaveButton)component; + break; + case "TextBox": + textBox = (TextBox)component; + break; + case "Title": + title = (Title)component; + break; } - }); } - } - - /** - * EN: Various methods to handle requests from particular components. - *

- * RU: Разнообразные методы общения с компонентами. - */ - @Override - public void addNewNote(Note note) { - title.setText(""); - textBox.setText(""); - list.addElement(note); - } + /** + * EN: Various methods to handle requests from particular components. + * + * RU: Разнообразные методы общения с компонентами. + */ + @Override + public void addNewNote(Note note) { + title.setText(""); + textBox.setText(""); + list.addElement(note); + } - @Override - public void deleteNote() { - list.deleteElement(); - } + @Override + public void deleteNote() { + list.deleteElement(); + } - @Override - public void getInfoFromList(Note note) { - title.setText(note.getName().replace('*', ' ')); - textBox.setText(note.getText()); - } + @Override + public void getInfoFromList(Note note) { + title.setText(note.getName().replace('*', ' ')); + textBox.setText(note.getText()); + } - @Override - public void saveChanges() { - Note note = (Note) list.getSelectedValue(); - note.setName(title.getText()); - note.setText(textBox.getText()); - list.repaint(); - } + @Override + public void saveChanges() { + try { + Note note = (Note) list.getSelectedValue(); + note.setName(title.getText()); + note.setText(textBox.getText()); + list.repaint(); + } catch (NullPointerException ignored) {} + } - @Override - public void markNote() { - Note note = list.getCurrentElement(); - String name = note.getName(); - if (!name.endsWith("*")) { - note.setName(note.getName() + "*"); + @Override + public void markNote() { + try { + Note note = list.getCurrentElement(); + String name = note.getName(); + if (!name.endsWith("*")) { + note.setName(note.getName() + "*"); + } + list.repaint(); + } catch (NullPointerException ignored) {} } - list.repaint(); - } - @Override - public void clear() { - title.setText(""); - textBox.setText(""); - } + @Override + public void clear() { + title.setText(""); + textBox.setText(""); + } - @Override - public void sendToFilter(ListModel listModel) { - filter.setList(listModel); - } + @Override + public void sendToFilter(ListModel listModel) { + filter.setList(listModel); + } - @SuppressWarnings("unchecked") - @Override - public void setElementsList(ListModel list) { - this.list.setModel(list); - this.list.repaint(); - } + @SuppressWarnings("unchecked") + @Override + public void setElementsList(ListModel list) { + this.list.setModel(list); + this.list.repaint(); + } - @Override - public void hideElements(boolean flag) { - titleLabel.setVisible(!flag); - textLabel.setVisible(!flag); - title.setVisible(!flag); - textBox.setVisible(!flag); - save.setVisible(!flag); - label.setVisible(flag); - } + @Override + public void hideElements(boolean flag) { + titleLabel.setVisible(!flag); + textLabel.setVisible(!flag); + title.setVisible(!flag); + textBox.setVisible(!flag); + save.setVisible(!flag); + label.setVisible(flag); + } - @Override - public void createGUI() { - JFrame notes = new JFrame("Notes"); - notes.setSize(960, 600); - notes.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - JPanel left = new JPanel(); - left.setBorder(new LineBorder(Color.BLACK)); - left.setSize(320, 600); - left.setLayout(new BoxLayout(left, BoxLayout.Y_AXIS)); - JPanel filterPanel = new JPanel(); - filterPanel.add(new JLabel("Filter:")); - filter.setColumns(20); - filterPanel.add(filter); - filterPanel.setPreferredSize(new Dimension(280, 40)); - JPanel listPanel = new JPanel(); - list.setFixedCellWidth(260); - listPanel.setSize(320, 470); - JScrollPane scrollPane = new JScrollPane(list); - scrollPane.setPreferredSize(new Dimension(275, 410)); - listPanel.add(scrollPane); - JPanel buttonPanel = new JPanel(); - add.setPreferredSize(new Dimension(85, 25)); - buttonPanel.add(add); - del.setPreferredSize(new Dimension(85, 25)); - buttonPanel.add(del); - buttonPanel.setLayout(new FlowLayout()); - left.add(filterPanel); - left.add(listPanel); - left.add(buttonPanel); - JPanel right = new JPanel(); - right.setLayout(null); - right.setSize(640, 600); - right.setLocation(320, 0); - right.setBorder(new LineBorder(Color.BLACK)); - titleLabel.setBounds(20, 4, 50, 20); - title.setBounds(60, 5, 555, 20); - textLabel.setBounds(20, 4, 50, 130); - textBox.setBorder(new LineBorder(Color.DARK_GRAY)); - textBox.setBounds(20, 80, 595, 410); - save.setBounds(270, 535, 80, 25); - label.setFont(new Font("Verdana", Font.PLAIN, 22)); - label.setBounds(100, 240, 500, 100); - right.add(label); - right.add(titleLabel); - right.add(title); - right.add(textLabel); - right.add(textBox); - right.add(save); - notes.setLayout(null); - notes.getContentPane().add(left); - notes.getContentPane().add(right); - notes.setResizable(false); - notes.setLocationRelativeTo(null); - notes.setVisible(true); - } + @Override + public void createGUI() { + JFrame notes = new JFrame("Notes"); + notes.setSize(960, 600); + notes.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + JPanel left = new JPanel(); + left.setBorder(new LineBorder(Color.BLACK)); + left.setSize(320, 600); + left.setLayout(new BoxLayout(left, BoxLayout.Y_AXIS)); + JPanel filterPanel = new JPanel(); + filterPanel.add(new JLabel("Filter:")); + filter.setColumns(20); + filterPanel.add(filter); + filterPanel.setPreferredSize(new Dimension(280, 40)); + JPanel listPanel = new JPanel(); + list.setFixedCellWidth(260); + listPanel.setSize(320, 470); + JScrollPane scrollPane = new JScrollPane(list); + scrollPane.setPreferredSize(new Dimension(275, 410)); + listPanel.add(scrollPane); + JPanel buttonPanel = new JPanel(); + add.setPreferredSize(new Dimension(85, 25)); + buttonPanel.add(add); + del.setPreferredSize(new Dimension(85, 25)); + buttonPanel.add(del); + buttonPanel.setLayout(new FlowLayout()); + left.add(filterPanel); + left.add(listPanel); + left.add(buttonPanel); + JPanel right = new JPanel(); + right.setLayout(null); + right.setSize(640, 600); + right.setLocation(320, 0); + right.setBorder(new LineBorder(Color.BLACK)); + titleLabel.setBounds(20, 4, 50, 20); + title.setBounds(60, 5, 555, 20); + textLabel.setBounds(20, 4, 50, 130); + textBox.setBorder(new LineBorder(Color.DARK_GRAY)); + textBox.setBounds(20, 80, 595, 410); + save.setBounds(270, 535, 80, 25); + label.setFont(new Font("Verdana", Font.PLAIN, 22)); + label.setBounds(100, 240, 500, 100); + right.add(label); + right.add(titleLabel); + right.add(title); + right.add(textLabel); + right.add(textBox); + right.add(save); + notes.setLayout(null); + notes.getContentPane().add(left); + notes.getContentPane().add(right); + notes.setResizable(false); + notes.setLocationRelativeTo(null); + notes.setVisible(true); + } } diff --git a/src/refactoring_guru/mediator/example/mediator/Mediator.java b/src/refactoring_guru/mediator/example/mediator/Mediator.java index dd3b1b6..86806f5 100644 --- a/src/refactoring_guru/mediator/example/mediator/Mediator.java +++ b/src/refactoring_guru/mediator/example/mediator/Mediator.java @@ -6,29 +6,19 @@ /** * EN: Common mediator interface. - *

+ * * RU: Общий интерфейс посредников. */ public interface Mediator { - void addNewNote(Note note); - - void deleteNote(); - - void getInfoFromList(Note note); - - void saveChanges(); - - void markNote(); - - void clear(); - - void sendToFilter(ListModel noteListModel); - - void setElementsList(ListModel elementList); - - void registerComponent(Component component); - - void hideElements(boolean flag); - - void createGUI(); + void addNewNote(Note note); + void deleteNote(); + void getInfoFromList(Note note); + void saveChanges(); + void markNote(); + void clear(); + void sendToFilter(ListModel listModel); + void setElementsList(ListModel list); + void registerComponent(Component component); + void hideElements(boolean flag); + void createGUI(); } diff --git a/src/refactoring_guru/mediator/example/mediator/Note.java b/src/refactoring_guru/mediator/example/mediator/Note.java index 6fb06e1..d727fef 100644 --- a/src/refactoring_guru/mediator/example/mediator/Note.java +++ b/src/refactoring_guru/mediator/example/mediator/Note.java @@ -2,35 +2,35 @@ /** * EN: Note class. - *

+ * * RU: Класс заметок. */ public class Note { - private String name; - private String text; + private String name; + private String text; - public Note() { - name = "New note"; - } + public Note() { + name = "New note"; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public void setText(String text) { - this.text = text; - } + public void setText(String text) { + this.text = text; + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public String getText() { - return text; - } + public String getText() { + return text; + } - @Override - public String toString() { - return name; - } + @Override + public String toString() { + return name; + } } diff --git a/src/refactoring_guru/memento/example/Demo.java b/src/refactoring_guru/memento/example/Demo.java index 59e2cbc..da19c60 100644 --- a/src/refactoring_guru/memento/example/Demo.java +++ b/src/refactoring_guru/memento/example/Demo.java @@ -9,23 +9,23 @@ import java.awt.*; public class Demo { - public static void main(String[] args) { - Editor editor = new Editor(); - editor.loadShapes( - new Circle(10, 10, 10, Color.BLUE), + public static void main(String[] args) { + Editor editor = new Editor(); + editor.loadShapes( + new Circle(10, 10, 10, Color.BLUE), - new CompoundShape( - new Circle(110, 110, 50, Color.RED), - new Dot(160, 160, Color.RED) - ), + new CompoundShape( + new Circle(110, 110, 50, Color.RED), + new Dot(160, 160, Color.RED) + ), - new CompoundShape( - new Rectangle(250, 250, 100, 100, Color.GREEN), - new Dot(240, 240, Color.GREEN), - new Dot(240, 360, Color.GREEN), - new Dot(360, 360, Color.GREEN), - new Dot(360, 240, Color.GREEN) - ) - ); - } + new CompoundShape( + new Rectangle(250, 250, 100, 100, Color.GREEN), + new Dot(240, 240, Color.GREEN), + new Dot(240, 360, Color.GREEN), + new Dot(360, 360, Color.GREEN), + new Dot(360, 240, Color.GREEN) + ) + ); + } } diff --git a/src/refactoring_guru/memento/example/commands/ColorCommand.java b/src/refactoring_guru/memento/example/commands/ColorCommand.java index e71856f..3c6d9a3 100644 --- a/src/refactoring_guru/memento/example/commands/ColorCommand.java +++ b/src/refactoring_guru/memento/example/commands/ColorCommand.java @@ -6,23 +6,23 @@ import java.awt.*; public class ColorCommand implements Command { - private final Editor editor; - private final Color color; + private Editor editor; + private Color color; - public ColorCommand(Editor editor, Color color) { - this.editor = editor; - this.color = color; - } + public ColorCommand(Editor editor, Color color) { + this.editor = editor; + this.color = color; + } - @Override - public String getName() { - return "Colorize: " + color.toString(); - } + @Override + public String getName() { + return "Colorize: " + color.toString(); + } - @Override - public void execute() { - for (Shape child : editor.getShapes().getSelected()) { - child.setColor(color); + @Override + public void execute() { + for (Shape child : editor.getShapes().getSelected()) { + child.setColor(color); + } } - } } diff --git a/src/refactoring_guru/memento/example/commands/Command.java b/src/refactoring_guru/memento/example/commands/Command.java index 45cf0c2..56e0997 100644 --- a/src/refactoring_guru/memento/example/commands/Command.java +++ b/src/refactoring_guru/memento/example/commands/Command.java @@ -1,7 +1,6 @@ package refactoring_guru.memento.example.commands; public interface Command { - String getName(); - - void execute(); + String getName(); + void execute(); } diff --git a/src/refactoring_guru/memento/example/commands/MoveCommand.java b/src/refactoring_guru/memento/example/commands/MoveCommand.java index 9daed95..f134c43 100644 --- a/src/refactoring_guru/memento/example/commands/MoveCommand.java +++ b/src/refactoring_guru/memento/example/commands/MoveCommand.java @@ -4,47 +4,45 @@ import refactoring_guru.memento.example.shapes.Shape; public class MoveCommand implements Command { - private final Editor editor; - private int startX; - private int startY; - private int endX; - private int endY; - - public MoveCommand(Editor editor) { - this.editor = editor; - } - - @Override - public String getName() { - return "Move by X:" + (endX - startX) + " Y:" + (endY - startY); - } - - public void start(int x, int y) { - startX = x; - startY = y; - for (Shape child : editor.getShapes().getSelected()) { - child.drag(); + private Editor editor; + private int startX, startY; + private int endX, endY; + + public MoveCommand(Editor editor) { + this.editor = editor; + } + + @Override + public String getName() { + return "Move by X:" + (endX - startX) + " Y:" + (endY - startY); + } + + public void start(int x, int y) { + startX = x; + startY = y; + for (Shape child : editor.getShapes().getSelected()) { + child.drag(); + } } - } - public void move(int x, int y) { - for (Shape child : editor.getShapes().getSelected()) { - child.moveTo(x - startX, y - startY); + public void move(int x, int y) { + for (Shape child : editor.getShapes().getSelected()) { + child.moveTo(x - startX, y - startY); + } } - } - public void stop(int x, int y) { - endX = x; - endY = y; - for (Shape child : editor.getShapes().getSelected()) { - child.drop(); + public void stop(int x, int y) { + endX = x; + endY = y; + for (Shape child : editor.getShapes().getSelected()) { + child.drop(); + } } - } - @Override - public void execute() { - for (Shape child : editor.getShapes().getSelected()) { - child.moveBy(endX - startX, endY - startY); + @Override + public void execute() { + for (Shape child : editor.getShapes().getSelected()) { + child.moveBy(endX - startX, endY - startY); + } } - } } diff --git a/src/refactoring_guru/memento/example/editor/Canvas.java b/src/refactoring_guru/memento/example/editor/Canvas.java new file mode 100644 index 0000000..06105ed --- /dev/null +++ b/src/refactoring_guru/memento/example/editor/Canvas.java @@ -0,0 +1,171 @@ +package refactoring_guru.memento.example.editor; + +import refactoring_guru.memento.example.commands.ColorCommand; +import refactoring_guru.memento.example.commands.MoveCommand; +import refactoring_guru.memento.example.shapes.Shape; + +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; +import java.awt.event.*; +import java.awt.image.BufferedImage; + +class Canvas extends java.awt.Canvas { + private Editor editor; + private JFrame frame; + private static final int PADDING = 10; + + Canvas(Editor editor) { + this.editor = editor; + createFrame(); + attachKeyboardListeners(); + attachMouseListeners(); + refresh(); + } + + private void createFrame() { + frame = new JFrame(); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frame.setLocationRelativeTo(null); + + JPanel contentPanel = new JPanel(); + Border padding = BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING); + contentPanel.setBorder(padding); + contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS)); + frame.setContentPane(contentPanel); + + contentPanel.add(new JLabel("Select and drag to move."), BorderLayout.PAGE_END); + contentPanel.add(new JLabel("Right click to change color."), BorderLayout.PAGE_END); + contentPanel.add(new JLabel("Undo: Ctrl+Z, Redo: Ctrl+R"), BorderLayout.PAGE_END); + contentPanel.add(this); + frame.setVisible(true); + contentPanel.setBackground(Color.LIGHT_GRAY); + } + + private void attachKeyboardListeners() { + addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0) { + switch (e.getKeyCode()) { + case KeyEvent.VK_Z: + editor.undo(); + break; + case KeyEvent.VK_R: + editor.redo(); + break; + } + } + } + }); + } + + private void attachMouseListeners() { + MouseAdapter colorizer = new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (e.getButton() != MouseEvent.BUTTON3) { + return; + } + Shape target = editor.getShapes().getChildAt(e.getX(), e.getY()); + if (target != null) { + editor.execute(new ColorCommand(editor, new Color((int) (Math.random() * 0x1000000)))); + repaint(); + } + } + }; + addMouseListener(colorizer); + + MouseAdapter selector = new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (e.getButton() != MouseEvent.BUTTON1) { + return; + } + + Shape target = editor.getShapes().getChildAt(e.getX(), e.getY()); + boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK; + + if (target == null) { + if (!ctrl) { + editor.getShapes().unSelect(); + } + } else { + if (ctrl) { + if (target.isSelected()) { + target.unSelect(); + } else { + target.select(); + } + } else { + if (!target.isSelected()) { + editor.getShapes().unSelect(); + } + target.select(); + } + } + repaint(); + } + }; + addMouseListener(selector); + + + MouseAdapter dragger = new MouseAdapter() { + MoveCommand moveCommand; + + @Override + public void mouseDragged(MouseEvent e) { + if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) != MouseEvent.BUTTON1_DOWN_MASK) { + return; + } + if (moveCommand == null) { + moveCommand = new MoveCommand(editor); + moveCommand.start(e.getX(), e.getY()); + } + moveCommand.move(e.getX(), e.getY()); + repaint(); + } + + @Override + public void mouseReleased(MouseEvent e) { + if (e.getButton() != MouseEvent.BUTTON1 || moveCommand == null) { + return; + } + moveCommand.stop(e.getX(), e.getY()); + editor.execute(moveCommand); + this.moveCommand = null; + repaint(); + } + }; + addMouseListener(dragger); + addMouseMotionListener(dragger); + } + + public int getWidth() { + return editor.getShapes().getX() + editor.getShapes().getWidth() + PADDING; + } + + public int getHeight() { + return editor.getShapes().getY() + editor.getShapes().getHeight() + PADDING; + } + + void refresh() { + this.setSize(getWidth(), getHeight()); + frame.pack(); + } + + public void update(Graphics g) { + paint(g); + } + + public void paint(Graphics graphics) { + BufferedImage buffer = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB); + Graphics2D ig2 = buffer.createGraphics(); + ig2.setBackground(Color.WHITE); + ig2.clearRect(0, 0, this.getWidth(), this.getHeight()); + + editor.getShapes().paint(buffer.getGraphics()); + + graphics.drawImage(buffer, 0, 0, null); + } +} diff --git a/src/refactoring_guru/memento/example/editor/Editor.java b/src/refactoring_guru/memento/example/editor/Editor.java index 78d7e9c..90f7dc6 100644 --- a/src/refactoring_guru/memento/example/editor/Editor.java +++ b/src/refactoring_guru/memento/example/editor/Editor.java @@ -11,58 +11,62 @@ import java.util.Base64; public class Editor extends JComponent { - private final Frame canvas; - private CompoundShape allShapes = new CompoundShape(); - private final transient History history; + private Canvas canvas; + private CompoundShape allShapes = new CompoundShape(); + private History history; - public Editor() { - canvas = new Frame(this); - history = new History(); - } + public Editor() { + canvas = new Canvas(this); + history = new History(); + } - public void loadShapes(Shape... shapes) { - allShapes.clear(); - allShapes.add(shapes); - canvas.refresh(); - } + public void loadShapes(Shape... shapes) { + allShapes.clear(); + allShapes.add(shapes); + canvas.refresh(); + } - public CompoundShape getShapes() { - return allShapes; - } + public CompoundShape getShapes() { + return allShapes; + } - public void execute(Command c) throws IOException { - history.push(c, new Memento(this)); - c.execute(); - } + public void execute(Command c) { + history.push(c, new Memento(this)); + c.execute(); + } - public void undo() { - if (history.undo()) - canvas.repaint(); - } + public void undo() { + if (history.undo()) + canvas.repaint(); + } - public void redo() { - if (history.redo()) - canvas.repaint(); - } + public void redo() { + if (history.redo()) + canvas.repaint(); + } - public String backup() throws IOException { - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); - objectOutputStream.writeObject(this.allShapes); - objectOutputStream.close(); - return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()); - } + public String backup() { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(this.allShapes); + oos.close(); + return Base64.getEncoder().encodeToString(baos.toByteArray()); + } catch (IOException e) { + return ""; + } + } - public void restore(String state) { - try { - byte[] data = Base64.getDecoder().decode(state); - ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data)); - this.allShapes = (CompoundShape) ois.readObject(); - ois.close(); - } catch (ClassNotFoundException e) { - System.out.print("ClassNotFoundException occurred."); - } catch (IOException e) { - System.out.print("IOException occurred."); + public void restore(String state) { + try { + byte[] data = Base64.getDecoder().decode(state); + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data)); + this.allShapes = (CompoundShape) ois.readObject(); + ois.close(); + } catch (ClassNotFoundException e) { + System.out.print("ClassNotFoundException occurred."); + } catch (IOException e) { + System.out.print("IOException occurred."); + } } - } } diff --git a/src/refactoring_guru/memento/example/editor/Frame.java b/src/refactoring_guru/memento/example/editor/Frame.java deleted file mode 100644 index c647ef5..0000000 --- a/src/refactoring_guru/memento/example/editor/Frame.java +++ /dev/null @@ -1,188 +0,0 @@ -package refactoring_guru.memento.example.editor; - -import refactoring_guru.memento.example.commands.ColorCommand; -import refactoring_guru.memento.example.commands.MoveCommand; -import refactoring_guru.memento.example.shapes.Shape; - -import javax.swing.*; -import javax.swing.border.Border; -import java.awt.*; -import java.awt.event.*; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.Random; -import java.util.logging.Level; -import java.util.logging.Logger; - -class Frame extends Canvas implements FrameMemento { - private final Editor editor; - private JFrame jFrame; - private static final int PADDING = 10; - private final Random random = new Random(); - - Frame(Editor editor) { - this.editor = editor; - initFrame(); - attachListeners(); - mouseListeners(); - refresh(); - } - - private void initFrame() { - jFrame = new JFrame(); - jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - jFrame.setLocationRelativeTo(null); - - JPanel contentPanel = new JPanel(); - Border padding = BorderFactory.createEmptyBorder(PADDING, PADDING, PADDING, PADDING); - contentPanel.setBorder(padding); - contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS)); - jFrame.setContentPane(contentPanel); - - contentPanel.add(new JLabel("Select and drag to move."), BorderLayout.PAGE_END); - contentPanel.add(new JLabel("Right click to change color."), BorderLayout.PAGE_END); - contentPanel.add(new JLabel("Undo: Ctrl+Z, Redo: Ctrl+R"), BorderLayout.PAGE_END); - contentPanel.add(this); - jFrame.setVisible(true); - contentPanel.setBackground(Color.LIGHT_GRAY); - } - - private void attachListeners() { - addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) { - switch (e.getKeyCode()) { - case KeyEvent.VK_Z -> editor.undo(); - case KeyEvent.VK_R -> editor.redo(); - default -> Logger.getLogger(Frame.class.getName()) - .log(Level.WARNING, () -> "Unknown component: "); - - } - } - } - }); - } - - private void mouseListeners() { - MouseAdapter mouseAdapter = new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - if (e.getButton() != MouseEvent.BUTTON3) { - return; - } - Shape target = editor.getShapes().getChildAt(e.getX(), e.getY()); - if (target != null) { - try { - editor.execute(new ColorCommand(editor, new Color((random.nextInt() * 0x1000000)))); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - repaint(); - } - } - }; - addMouseListener(mouseAdapter); - - MouseAdapter selector = new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - if (e.getButton() != MouseEvent.BUTTON1) { - throw new IllegalArgumentException("if the button is not working "); - } - - Shape target = editor.getShapes().getChildAt(e.getX(), e.getY()); - boolean ctrl = (e.getModifiersEx() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK; - - if (target == null) { - if (!ctrl) { - editor.getShapes().unSelect(); - } - } else { - if (ctrl) { - if (target.isSelected()) { - target.unSelect(); - } else { - target.select(); - } - } else { - if (!target.isSelected()) { - editor.getShapes().unSelect(); - } - target.select(); - } - } - repaint(); - } - }; - addMouseListener(selector); - - - MouseAdapter mouseAdapter1 = new MouseAdapter() { - MoveCommand moveCommand; - - @Override - public void mouseDragged(MouseEvent e) { - if ((e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != InputEvent.BUTTON1_DOWN_MASK) { - return; - } - if (moveCommand == null) { - moveCommand = new MoveCommand(editor); - moveCommand.start(e.getX(), e.getY()); - } - moveCommand.move(e.getX(), e.getY()); - repaint(); - } - - @Override - public void mouseReleased(MouseEvent e) { - if (e.getButton() != MouseEvent.BUTTON1 || moveCommand == null) { - throw new IllegalArgumentException("Cannot execute"); - } - moveCommand.stop(e.getX(), e.getY()); - try { - editor.execute(moveCommand); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - this.moveCommand = null; - repaint(); - } - }; - addMouseListener(mouseAdapter1); - addMouseMotionListener(mouseAdapter1); - } - - @Override - public int getWidth() { - return editor.getShapes().getX() + editor.getShapes().getWidth() + PADDING; - } - - @Override - public int getHeight() { - return editor.getShapes().getY() + editor.getShapes().getHeight() + PADDING; - } - - @Override - public void refresh() { - this.setSize(getWidth(), getHeight()); - jFrame.pack(); - } - - @Override - public void update(Graphics g) { - paint(g); - } - - @Override - public void paint(Graphics graphics) { - BufferedImage buffer = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB); - Graphics2D ig2 = buffer.createGraphics(); - ig2.setBackground(Color.WHITE); - ig2.clearRect(0, 0, this.getWidth(), this.getHeight()); - - editor.getShapes().paint(buffer.getGraphics()); - - graphics.drawImage(buffer, 0, 0, null); - } -} diff --git a/src/refactoring_guru/memento/example/editor/FrameMemento.java b/src/refactoring_guru/memento/example/editor/FrameMemento.java deleted file mode 100644 index 340f966..0000000 --- a/src/refactoring_guru/memento/example/editor/FrameMemento.java +++ /dev/null @@ -1,5 +0,0 @@ -package refactoring_guru.memento.example.editor; - -public interface FrameMemento { - void refresh(); -} diff --git a/src/refactoring_guru/memento/example/history/History.java b/src/refactoring_guru/memento/example/history/History.java index a0fe4b3..90d6cbd 100644 --- a/src/refactoring_guru/memento/example/history/History.java +++ b/src/refactoring_guru/memento/example/history/History.java @@ -6,69 +6,68 @@ import java.util.List; public class History { - private List pairs = new ArrayList<>(); - private int virtualSize = 0; + private List history = new ArrayList(); + private int virtualSize = 0; - public void push(Command c, Memento m) { - if (virtualSize != pairs.size() && virtualSize > 0) { - pairs = pairs.subList(0, virtualSize - 1); - } - pairs.add(new Pair(c, m)); - virtualSize = pairs.size(); - } + private class Pair { + Command command; + Memento memento; + Pair(Command c, Memento m) { + command = c; + memento = m; + } - public boolean undo() { - Pair pair = getUndo(); - if (pair == null) { - return false; - } - System.out.println("Undoing: " + pair.getCommand().getName()); - pair.getMemento().restore(); - return true; - } + private Command getCommand() { + return command; + } - public boolean redo() { - Pair pair = getRedo(); - if (pair == null) { - return false; + private Memento getMemento() { + return memento; + } } - System.out.println("Redoing: " + pair.getCommand().getName()); - pair.getMemento().restore(); - pair.getCommand().execute(); - return true; - } - private Pair getUndo() { - if (virtualSize == 0) { - return null; + public void push(Command c, Memento m) { + if (virtualSize != history.size() && virtualSize > 0) { + history = history.subList(0, virtualSize - 1); + } + history.add(new Pair(c, m)); + virtualSize = history.size(); } - virtualSize = Math.max(0, virtualSize - 1); - return pairs.get(virtualSize); - } - private Pair getRedo() { - if (virtualSize == pairs.size()) { - return null; + public boolean undo() { + Pair pair = getUndo(); + if (pair == null) { + return false; + } + System.out.println("Undoing: " + pair.getCommand().getName()); + pair.getMemento().restore(); + return true; } - virtualSize = Math.min(pairs.size(), virtualSize + 1); - return pairs.get(virtualSize - 1); - } - - private static class Pair { - Command command; - Memento memento; - Pair(Command c, Memento m) { - command = c; - memento = m; + public boolean redo() { + Pair pair = getRedo(); + if (pair == null) { + return false; + } + System.out.println("Redoing: " + pair.getCommand().getName()); + pair.getMemento().restore(); + pair.getCommand().execute(); + return true; } - private Command getCommand() { - return command; + private Pair getUndo() { + if (virtualSize == 0) { + return null; + } + virtualSize = Math.max(0, virtualSize - 1); + return history.get(virtualSize); } - private Memento getMemento() { - return memento; + private Pair getRedo() { + if (virtualSize == history.size()) { + return null; + } + virtualSize = Math.min(history.size(), virtualSize + 1); + return history.get(virtualSize - 1); } - } } diff --git a/src/refactoring_guru/memento/example/history/Memento.java b/src/refactoring_guru/memento/example/history/Memento.java index dc5e6cd..6800638 100644 --- a/src/refactoring_guru/memento/example/history/Memento.java +++ b/src/refactoring_guru/memento/example/history/Memento.java @@ -2,18 +2,16 @@ import refactoring_guru.memento.example.editor.Editor; -import java.io.IOException; - public class Memento { - private final String backup; - private final Editor editor; + private String backup; + private Editor editor; - public Memento(Editor editor) throws IOException { - this.editor = editor; - this.backup = editor.backup(); - } + public Memento(Editor editor) { + this.editor = editor; + this.backup = editor.backup(); + } - public void restore() { - editor.restore(backup); - } + public void restore() { + editor.restore(backup); + } } diff --git a/src/refactoring_guru/memento/example/shapes/BaseShape.java b/src/refactoring_guru/memento/example/shapes/BaseShape.java index fd08d1a..3433329 100644 --- a/src/refactoring_guru/memento/example/shapes/BaseShape.java +++ b/src/refactoring_guru/memento/example/shapes/BaseShape.java @@ -3,117 +3,118 @@ import java.awt.*; public abstract class BaseShape implements Shape { - int x; - int y; - private int dx = 0; - private int dy = 0; - private Color color; - private boolean selected = false; - - BaseShape(int x, int y, Color color) { - this.x = x; - this.y = y; - this.color = color; - } - - @Override - public int getX() { - return x; - } - - @Override - public int getY() { - return y; - } - - @Override - public int getWidth() { - return 0; - } - - @Override - public int getHeight() { - return 0; - } - - @Override - public void drag() { - dx = x; - dy = y; - } - - @Override - public void moveTo(int x, int y) { - this.x = dx + x; - this.y = dy + y; - } - - @Override - public void moveBy(int x, int y) { - this.x += x; - this.y += y; - } - - @Override - public void drop() { - this.x = dx; - this.y = dy; - } - - @Override - public boolean isInsideBounds(int x, int y) { - return x > getX() && x < (getX() + getWidth()) && - y > getY() && y < (getY() + getHeight()); - } - - @Override - public Color getColor() { - return color; - } - - @Override - public void setColor(Color color) { - this.color = color; - } - - @Override - public void select() { - selected = true; - } - - @Override - public void unSelect() { - selected = false; - } - - @Override - public boolean isSelected() { - return selected; - } - - void enableSelectionStyle(Graphics graphics) { - graphics.setColor(Color.LIGHT_GRAY); - - Graphics2D g2 = (Graphics2D) graphics; - float[] dash1 = {2.0f}; - g2.setStroke(new BasicStroke(1.0f, - BasicStroke.CAP_BUTT, - BasicStroke.JOIN_MITER, - 2.0f, dash1, 0.0f)); - } - - void disableSelectionStyle(Graphics graphics) { - graphics.setColor(color); - Graphics2D g2 = (Graphics2D) graphics; - g2.setStroke(new BasicStroke()); - } - - @Override - public void paint(Graphics graphics) { - if (isSelected()) { - enableSelectionStyle(graphics); - } else { - disableSelectionStyle(graphics); - } - } + int x, y; + private int dx = 0, dy = 0; + private Color color; + private boolean selected = false; + + BaseShape(int x, int y, Color color) { + this.x = x; + this.y = y; + this.color = color; + } + + @Override + public int getX() { + return x; + } + + @Override + public int getY() { + return y; + } + + @Override + public int getWidth() { + return 0; + } + + @Override + public int getHeight() { + return 0; + } + + @Override + public void drag() { + dx = x; + dy = y; + } + + @Override + public void moveTo(int x, int y) { + this.x = dx + x; + this.y = dy + y; + } + + @Override + public void moveBy(int x, int y) { + this.x += x; + this.y += y; + } + + @Override + public void drop() { + this.x = dx; + this.y = dy; + } + + @Override + public boolean isInsideBounds(int x, int y) { + return x > getX() && x < (getX() + getWidth()) && + y > getY() && y < (getY() + getHeight()); + } + + @Override + public Color getColor() { + return color; + } + + @Override + public void setColor(Color color) { + this.color = color; + } + + @Override + public void select() { + selected = true; + } + + @Override + public void unSelect() { + selected = false; + } + + @Override + public boolean isSelected() { + return selected; + } + + void enableSelectionStyle(Graphics graphics) { + graphics.setColor(Color.LIGHT_GRAY); + + Graphics2D g2 = (Graphics2D) graphics; + float[] dash1 = {2.0f}; + g2.setStroke(new BasicStroke(1.0f, + BasicStroke.CAP_BUTT, + BasicStroke.JOIN_MITER, + 2.0f, dash1, 0.0f)); + } + + void disableSelectionStyle(Graphics graphics) { + graphics.setColor(color); + Graphics2D g2 = (Graphics2D) graphics; + g2.setStroke(new BasicStroke()); + } + + @Override + public void paint(Graphics graphics) { + if (isSelected()) { + enableSelectionStyle(graphics); + } + else { + disableSelectionStyle(graphics); + } + + // ... + } } \ No newline at end of file diff --git a/src/refactoring_guru/memento/example/shapes/Circle.java b/src/refactoring_guru/memento/example/shapes/Circle.java index e15b719..6400a50 100644 --- a/src/refactoring_guru/memento/example/shapes/Circle.java +++ b/src/refactoring_guru/memento/example/shapes/Circle.java @@ -3,26 +3,26 @@ import java.awt.*; public class Circle extends BaseShape { - private final int radius; + private int radius; - public Circle(int x, int y, int radius, Color color) { - super(x, y, color); - this.radius = radius; - } + public Circle(int x, int y, int radius, Color color) { + super(x, y, color); + this.radius = radius; + } - @Override - public int getWidth() { - return radius * 2; - } + @Override + public int getWidth() { + return radius * 2; + } - @Override - public int getHeight() { - return radius * 2; - } + @Override + public int getHeight() { + return radius * 2; + } - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.drawOval(x, y, getWidth() - 1, getHeight() - 1); - } + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.drawOval(x, y, getWidth() - 1, getHeight() - 1); + } } diff --git a/src/refactoring_guru/memento/example/shapes/CompoundShape.java b/src/refactoring_guru/memento/example/shapes/CompoundShape.java index 5236a02..ba94a4b 100644 --- a/src/refactoring_guru/memento/example/shapes/CompoundShape.java +++ b/src/refactoring_guru/memento/example/shapes/CompoundShape.java @@ -6,183 +6,181 @@ import java.util.List; public class CompoundShape extends BaseShape { - private final List children = new ArrayList<>(); - - public CompoundShape(Shape... components) { - super(0, 0, Color.BLACK); - add(components); - } - - public void add(Shape component) { - children.add(component); - } - - public void add(Shape... components) { - children.addAll(Arrays.asList(components)); - } - - public void remove(Shape child) { - children.remove(child); - } - - public void remove(Shape... components) { - children.removeAll(Arrays.asList(components)); - } - - public void clear() { - children.clear(); - } - - @Override - public int getX() { - checkNotEmpty(children); - int x = children.get(0).getX(); - for (Shape child : children) { - if (child.getX() < x) { - x = child.getX(); - } - } - return x; - } - - @Override - public int getY() { - checkNotEmpty(children); - int y = children.get(0).getY(); - for (Shape child : children) { - if (child.getY() < y) { - y = child.getY(); - } - } - return y; - } - - @Override - public int getWidth() { - int maxWidth = 0; - int x = getX(); - for (Shape child : children) { - int childsRelativeX = child.getX() - x; - int childWidth = childsRelativeX + child.getWidth(); - if (childWidth > maxWidth) { - maxWidth = childWidth; - } - } - return maxWidth; - } - - @Override - public int getHeight() { - int maxHeight = 0; - int y = getY(); - for (Shape child : children) { - int childsRelativeY = child.getY() - y; - int childHeight = childsRelativeY + child.getHeight(); - if (childHeight > maxHeight) { - maxHeight = childHeight; - } - } - return maxHeight; - } - - @Override - public void drag() { - for (Shape child : children) { - child.drag(); - } - } - - @Override - public void drop() { - for (Shape child : children) { - child.drop(); - } - } - - @Override - public void moveTo(int x, int y) { - for (Shape child : children) { - child.moveTo(x, y); - } - } - - @Override - public void moveBy(int x, int y) { - for (Shape child : children) { - child.moveBy(x, y); - } - } - - @Override - public boolean isInsideBounds(int x, int y) { - for (Shape child : children) { - if (child.isInsideBounds(x, y)) { - return true; - } - } - return false; - } - - @Override - public void setColor(Color color) { - super.setColor(color); - for (Shape child : children) { - child.setColor(color); - } - } - - @Override - public void unSelect() { - super.unSelect(); - for (Shape child : children) { - child.unSelect(); - } - } - - public Shape getChildAt(int x, int y) { - for (Shape child : children) { - if (child.isInsideBounds(x, y)) { - return child; - } - } - return null; - } - - public boolean selectChildAt(int x, int y) { - Shape child = getChildAt(x, y); - if (child != null) { - child.select(); - return true; - } - return false; - } - - public List getSelected() { - List selected = new ArrayList<>(); - for (Shape child : children) { - if (child.isSelected()) { - selected.add(child); - } - } - return selected; - } - - @Override - public void paint(Graphics graphics) { - if (isSelected()) { - enableSelectionStyle(graphics); - graphics.drawRect(getX() - 1, getY() - 1, getWidth() + 1, getHeight() + 1); - disableSelectionStyle(graphics); - } - - for (Shape child : children) { - child.paint(graphics); - } - } + private List children = new ArrayList<>(); - private void checkNotEmpty(List children) { - if (children.isEmpty()) { - throw new IllegalArgumentException("The List is empty "); - } - } + public CompoundShape(Shape... components) { + super(0, 0, Color.BLACK); + add(components); + } + + public void add(Shape component) { + children.add(component); + } + + public void add(Shape... components) { + children.addAll(Arrays.asList(components)); + } + + public void remove(Shape child) { + children.remove(child); + } + + public void remove(Shape... components) { + children.removeAll(Arrays.asList(components)); + } + + public void clear() { + children.clear(); + } + + @Override + public int getX() { + if (children.size() == 0) { + return 0; + } + int x = children.get(0).getX(); + for (Shape child : children) { + if (child.getX() < x) { + x = child.getX(); + } + } + return x; + } + + @Override + public int getY() { + if (children.size() == 0) { + return 0; + } + int y = children.get(0).getY(); + for (Shape child : children) { + if (child.getY() < y) { + y = child.getY(); + } + } + return y; + } + + @Override + public int getWidth() { + int maxWidth = 0; + int x = getX(); + for (Shape child : children) { + int childsRelativeX = child.getX() - x; + int childWidth = childsRelativeX + child.getWidth(); + if (childWidth > maxWidth) { + maxWidth = childWidth; + } + } + return maxWidth; + } + + @Override + public int getHeight() { + int maxHeight = 0; + int y = getY(); + for (Shape child : children) { + int childsRelativeY = child.getY() - y; + int childHeight = childsRelativeY + child.getHeight(); + if (childHeight > maxHeight) { + maxHeight = childHeight; + } + } + return maxHeight; + } + + @Override + public void drag() { + for (Shape child : children) { + child.drag(); + } + } + + @Override + public void drop() { + for (Shape child : children) { + child.drop(); + } + } + + @Override + public void moveTo(int x, int y) { + for (Shape child : children) { + child.moveTo(x, y); + } + } + + @Override + public void moveBy(int x, int y) { + for (Shape child : children) { + child.moveBy(x, y); + } + } + + @Override + public boolean isInsideBounds(int x, int y) { + for (Shape child : children) { + if (child.isInsideBounds(x, y)) { + return true; + } + } + return false; + } + + @Override + public void setColor(Color color) { + super.setColor(color); + for (Shape child : children) { + child.setColor(color); + } + } + + @Override + public void unSelect() { + super.unSelect(); + for (Shape child : children) { + child.unSelect(); + } + } + + public Shape getChildAt(int x, int y) { + for (Shape child : children) { + if (child.isInsideBounds(x, y)) { + return child; + } + } + return null; + } + + public boolean selectChildAt(int x, int y) { + Shape child = getChildAt(x,y); + if (child != null) { + child.select(); + return true; + } + return false; + } + + public List getSelected() { + List selected = new ArrayList<>(); + for (Shape child : children) { + if (child.isSelected()) { + selected.add(child); + } + } + return selected; + } + + @Override + public void paint(Graphics graphics) { + if (isSelected()) { + enableSelectionStyle(graphics); + graphics.drawRect(getX() - 1, getY() - 1, getWidth() + 1, getHeight() + 1); + disableSelectionStyle(graphics); + } + + for (Shape child : children) { + child.paint(graphics); + } + } } diff --git a/src/refactoring_guru/memento/example/shapes/Dot.java b/src/refactoring_guru/memento/example/shapes/Dot.java index 8c8cdf9..a8562e6 100644 --- a/src/refactoring_guru/memento/example/shapes/Dot.java +++ b/src/refactoring_guru/memento/example/shapes/Dot.java @@ -3,26 +3,25 @@ import java.awt.*; public class Dot extends BaseShape { - private final int DOT_WIDTH = 3; - private final int DOT_HEIGHT = 3; + private final int DOT_SIZE = 3; - public Dot(int x, int y, Color color) { - super(x, y, color); - } + public Dot(int x, int y, Color color) { + super(x, y, color); + } - @Override - public int getWidth() { - return DOT_WIDTH; - } + @Override + public int getWidth() { + return DOT_SIZE; + } - @Override - public int getHeight() { - return DOT_HEIGHT; - } + @Override + public int getHeight() { + return DOT_SIZE; + } - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.fillRect(x - 1, y - 1, getWidth(), getHeight()); - } + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.fillRect(x - 1, y - 1, getWidth(), getHeight()); + } } diff --git a/src/refactoring_guru/memento/example/shapes/Rectangle.java b/src/refactoring_guru/memento/example/shapes/Rectangle.java index e53a2e3..76aa5e8 100644 --- a/src/refactoring_guru/memento/example/shapes/Rectangle.java +++ b/src/refactoring_guru/memento/example/shapes/Rectangle.java @@ -3,28 +3,28 @@ import java.awt.*; public class Rectangle extends BaseShape { - private final int width; - private final int height; + private int width; + private int height; - public Rectangle(int x, int y, int width, int height, Color color) { - super(x, y, color); - this.width = width; - this.height = height; - } + public Rectangle(int x, int y, int width, int height, Color color) { + super(x, y, color); + this.width = width; + this.height = height; + } - @Override - public int getWidth() { - return width; - } + @Override + public int getWidth() { + return width; + } - @Override - public int getHeight() { - return height; - } + @Override + public int getHeight() { + return height; + } - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - graphics.drawRect(x, y, getWidth() - 1, getHeight() - 1); - } + @Override + public void paint(Graphics graphics) { + super.paint(graphics); + graphics.drawRect(x, y, getWidth() - 1, getHeight() - 1); + } } diff --git a/src/refactoring_guru/memento/example/shapes/Shape.java b/src/refactoring_guru/memento/example/shapes/Shape.java index 71b4d9a..90d078d 100644 --- a/src/refactoring_guru/memento/example/shapes/Shape.java +++ b/src/refactoring_guru/memento/example/shapes/Shape.java @@ -4,34 +4,20 @@ import java.io.Serializable; public interface Shape extends Serializable { - int getX(); - - int getY(); - - int getWidth(); - - int getHeight(); - - void drag(); - - void drop(); - - void moveTo(int x, int y); - - void moveBy(int x, int y); - - boolean isInsideBounds(int x, int y); - - Color getColor(); - - void setColor(Color color); - - void select(); - - void unSelect(); - - boolean isSelected(); - - void paint(Graphics graphics); + int getX(); + int getY(); + int getWidth(); + int getHeight(); + void drag(); + void drop(); + void moveTo(int x, int y); + void moveBy(int x, int y); + boolean isInsideBounds(int x, int y); + Color getColor(); + void setColor(Color color); + void select(); + void unSelect(); + boolean isSelected(); + void paint(Graphics graphics); } diff --git a/src/refactoring_guru/observer/example/Demo.java b/src/refactoring_guru/observer/example/Demo.java index 6515a09..7d399c0 100644 --- a/src/refactoring_guru/observer/example/Demo.java +++ b/src/refactoring_guru/observer/example/Demo.java @@ -5,11 +5,16 @@ import refactoring_guru.observer.example.listeners.LogOpenListener; public class Demo { - public static void main(String[] args) throws Exception { - Editor editor = new Editor(); - editor.events.subscribe("open", new LogOpenListener("/path/to/log/file.txt")); - editor.events.subscribe("save", new EmailNotificationListener("admin@example.com")); - editor.openFile("test.txt"); - editor.saveFile(); - } + public static void main(String[] args) { + Editor editor = new Editor(); + editor.events.subscribe("open", new LogOpenListener("/path/to/log/file.txt")); + editor.events.subscribe("save", new EmailNotificationListener("admin@example.com")); + + try { + editor.openFile("test.txt"); + editor.saveFile(); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/src/refactoring_guru/observer/example/editor/Editor.java b/src/refactoring_guru/observer/example/editor/Editor.java index 20117fc..f373045 100644 --- a/src/refactoring_guru/observer/example/editor/Editor.java +++ b/src/refactoring_guru/observer/example/editor/Editor.java @@ -5,23 +5,23 @@ import java.io.File; public class Editor { - public EventManager events; - private File file; + public EventManager events; + private File file; - public Editor() { - this.events = new EventManager("open", "save"); - } + public Editor() { + this.events = new EventManager("open", "save"); + } - public void openFile(String filePath) { - this.file = new File(filePath); - events.notify("open", file); - } + public void openFile(String filePath) { + this.file = new File(filePath); + events.notify("open", file); + } - public void saveFile() throws Exception { - if (this.file != null) { - events.notify("save", file); - } else { - throw new Exception("Please open a file first."); + public void saveFile() throws Exception { + if (this.file != null) { + events.notify("save", file); + } else { + throw new Exception("Please open a file first."); + } } - } } diff --git a/src/refactoring_guru/observer/example/listeners/EmailNotificationListener.java b/src/refactoring_guru/observer/example/listeners/EmailNotificationListener.java index 6daac9f..efd3f9d 100644 --- a/src/refactoring_guru/observer/example/listeners/EmailNotificationListener.java +++ b/src/refactoring_guru/observer/example/listeners/EmailNotificationListener.java @@ -3,19 +3,14 @@ import java.io.File; public class EmailNotificationListener implements EventListener { - private final String email; + private String email; - public EmailNotificationListener(String email) { - this.email = email; - } + public EmailNotificationListener(String email) { + this.email = email; + } - @Override - public void update(String eventType, File file) { - System.out.println("Email to " - + email - + "Someone has performed " - + eventType - + " operation with the following file: " - + file.getClass().getName()); - } + @Override + public void update(String eventType, File file) { + System.out.println("Email to " + email + ": Someone has performed " + eventType + " operation with the following file: " + file.getName()); + } } diff --git a/src/refactoring_guru/observer/example/listeners/EventListener.java b/src/refactoring_guru/observer/example/listeners/EventListener.java index 4ff0d0b..a996b3a 100644 --- a/src/refactoring_guru/observer/example/listeners/EventListener.java +++ b/src/refactoring_guru/observer/example/listeners/EventListener.java @@ -3,5 +3,5 @@ import java.io.File; public interface EventListener { - void update(String eventType, File file); + void update(String eventType, File file); } diff --git a/src/refactoring_guru/observer/example/listeners/LogOpenListener.java b/src/refactoring_guru/observer/example/listeners/LogOpenListener.java index 09f4388..180470b 100644 --- a/src/refactoring_guru/observer/example/listeners/LogOpenListener.java +++ b/src/refactoring_guru/observer/example/listeners/LogOpenListener.java @@ -3,19 +3,14 @@ import java.io.File; public class LogOpenListener implements EventListener { - private final File log; + private File log; - public LogOpenListener(String fileName) { - this.log = new File(fileName); - } + public LogOpenListener(String fileName) { + this.log = new File(fileName); + } - @Override - public void update(String eventType, File file) { - System.out.println("Save to log " - + log - + "Someone has performed " - + eventType - + " operation with the following file: " - + file.getClass().getName()); - } + @Override + public void update(String eventType, File file) { + System.out.println("Save to log " + log + ": Someone has performed " + eventType + " operation with the following file: " + file.getName()); + } } diff --git a/src/refactoring_guru/observer/example/publisher/EventManager.java b/src/refactoring_guru/observer/example/publisher/EventManager.java index 5116817..2918ba1 100644 --- a/src/refactoring_guru/observer/example/publisher/EventManager.java +++ b/src/refactoring_guru/observer/example/publisher/EventManager.java @@ -9,28 +9,28 @@ import java.util.Map; public class EventManager { - Map> listeners = new HashMap<>(); + Map> listeners = new HashMap<>(); - public EventManager(String... operations) { - for (String operation : operations) { - this.listeners.put(operation, new ArrayList<>()); + public EventManager(String... operations) { + for (String operation : operations) { + this.listeners.put(operation, new ArrayList<>()); + } } - } - public void subscribe(String eventType, EventListener listener) { - List users = listeners.get(eventType); - users.add(listener); - } + public void subscribe(String eventType, EventListener listener) { + List users = listeners.get(eventType); + users.add(listener); + } - public void unsubscribe(String eventType, EventListener listener) { - List users = listeners.get(eventType); - users.remove(listener); - } + public void unsubscribe(String eventType, EventListener listener) { + List users = listeners.get(eventType); + users.remove(listener); + } - public void notify(String eventType, File file) { - List users = listeners.get(eventType); - for (EventListener listener : users) { - listener.update(eventType, file); + public void notify(String eventType, File file) { + List users = listeners.get(eventType); + for (EventListener listener : users) { + listener.update(eventType, file); + } } - } } diff --git a/src/refactoring_guru/prototype/caching/Demo.java b/src/refactoring_guru/prototype/caching/Demo.java index 557b216..5cad2ed 100644 --- a/src/refactoring_guru/prototype/caching/Demo.java +++ b/src/refactoring_guru/prototype/caching/Demo.java @@ -4,28 +4,28 @@ import refactoring_guru.prototype.example.shapes.Shape; public class Demo { - public static void main(String[] args) { - BundledShapeCache cache = new BundledShapeCache(); + public static void main(String[] args) { + BundledShapeCache cache = new BundledShapeCache(); - Shape shape1 = cache.get("Big green circle"); - Shape shape2 = cache.get("Medium blue rectangle"); - Shape shape3 = cache.get("Medium blue rectangle"); + Shape shape1 = cache.get("Big green circle"); + Shape shape2 = cache.get("Medium blue rectangle"); + Shape shape3 = cache.get("Medium blue rectangle"); - if (shape1 != shape2 && !shape1.equals(shape2)) { - System.out.println("Big green circle != Medium blue rectangle (yay!)"); - } else { - System.out.println("Big green circle == Medium blue rectangle (booo!)"); - } + if (shape1 != shape2 && !shape1.equals(shape2)) { + System.out.println("Big green circle != Medium blue rectangle (yay!)"); + } else { + System.out.println("Big green circle == Medium blue rectangle (booo!)"); + } - if (shape2 != shape3) { - System.out.println("Medium blue rectangles are two different objects (yay!)"); - if (shape2.equals(shape3)) { - System.out.println("And they are identical (yay!)"); - } else { - System.out.println("But they are not identical (booo!)"); - } - } else { - System.out.println("Rectangle objects are the same (booo!)"); + if (shape2 != shape3) { + System.out.println("Medium blue rectangles are two different objects (yay!)"); + if (shape2.equals(shape3)) { + System.out.println("And they are identical (yay!)"); + } else { + System.out.println("But they are not identical (booo!)"); + } + } else { + System.out.println("Rectangle objects are the same (booo!)"); + } } - } } \ No newline at end of file diff --git a/src/refactoring_guru/prototype/caching/cache/BundledShapeCache.java b/src/refactoring_guru/prototype/caching/cache/BundledShapeCache.java index 3367423..cd67746 100644 --- a/src/refactoring_guru/prototype/caching/cache/BundledShapeCache.java +++ b/src/refactoring_guru/prototype/caching/cache/BundledShapeCache.java @@ -8,32 +8,32 @@ import java.util.Map; public class BundledShapeCache { - private final Map cache = new HashMap<>(); - - public BundledShapeCache() { - Circle circle = new Circle(); - circle.x = 5; - circle.y = 7; - circle.radius = 45; - circle.color = "Green"; - - Rectangle rectangle = new Rectangle(); - rectangle.x = 6; - rectangle.y = 9; - rectangle.width = 8; - rectangle.height = 10; - rectangle.color = "Blue"; - - cache.put("Big green circle", circle); - cache.put("Medium blue rectangle", rectangle); - } - - public Shape put(String key, Shape shape) { - cache.put(key, shape); - return shape; - } - - public Shape get(String key) { - return cache.get(key).clone(); - } + private Map cache = new HashMap<>(); + + public BundledShapeCache() { + Circle circle = new Circle(); + circle.x = 5; + circle.y = 7; + circle.radius = 45; + circle.color = "Green"; + + Rectangle rectangle = new Rectangle(); + rectangle.x = 6; + rectangle.y = 9; + rectangle.width = 8; + rectangle.height = 10; + rectangle.color = "Blue"; + + cache.put("Big green circle", circle); + cache.put("Medium blue rectangle", rectangle); + } + + public Shape put(String key, Shape shape) { + cache.put(key, shape); + return shape; + } + + public Shape get(String key) { + return cache.get(key).clone(); + } } diff --git a/src/refactoring_guru/prototype/example/Demo.java b/src/refactoring_guru/prototype/example/Demo.java index 29c9a25..c02a2cd 100644 --- a/src/refactoring_guru/prototype/example/Demo.java +++ b/src/refactoring_guru/prototype/example/Demo.java @@ -8,45 +8,45 @@ import java.util.List; public class Demo { - public static void main(String[] args) { - List shapes = new ArrayList<>(); - List shapeArrayList = new ArrayList<>(); - - Circle circle = new Circle(); - circle.x = 10; - circle.y = 20; - circle.radius = 15; - circle.color = "red"; - shapes.add(circle); - - Circle anotherCircle = (Circle) circle.clone(); - shapes.add(anotherCircle); - - Rectangle rectangle = new Rectangle(); - rectangle.width = 10; - rectangle.height = 20; - rectangle.color = "blue"; - shapes.add(rectangle); - - cloneAndCompare(shapes, shapeArrayList); - } - - private static void cloneAndCompare(List shapes, List shapeList) { - for (Shape shape : shapes) { - shapeList.add(shape.clone()); + public static void main(String[] args) { + List shapes = new ArrayList<>(); + List shapesCopy = new ArrayList<>(); + + Circle circle = new Circle(); + circle.x = 10; + circle.y = 20; + circle.radius = 15; + circle.color = "red"; + shapes.add(circle); + + Circle anotherCircle = (Circle) circle.clone(); + shapes.add(anotherCircle); + + Rectangle rectangle = new Rectangle(); + rectangle.width = 10; + rectangle.height = 20; + rectangle.color = "blue"; + shapes.add(rectangle); + + cloneAndCompare(shapes, shapesCopy); } - for (int i = 0; i < shapes.size(); i++) { - if (shapes.get(i) != shapeList.get(i)) { - System.out.println(i + "Shapes are different objects (yay!)"); - if (shapes.get(i).equals(shapeList.get(i))) { - System.out.println(i + "And they are identical (yay!)"); - } else { - System.out.println(i + "But they are not identical (booo!)"); + private static void cloneAndCompare(List shapes, List shapesCopy) { + for (Shape shape : shapes) { + shapesCopy.add(shape.clone()); + } + + for (int i = 0; i < shapes.size(); i++) { + if (shapes.get(i) != shapesCopy.get(i)) { + System.out.println(i + ": Shapes are different objects (yay!)"); + if (shapes.get(i).equals(shapesCopy.get(i))) { + System.out.println(i + ": And they are identical (yay!)"); + } else { + System.out.println(i + ": But they are not identical (booo!)"); + } + } else { + System.out.println(i + ": Shape objects are the same (booo!)"); + } } - } else { - System.out.println(i + "Shape objects are the same (booo!)"); - } } - } } diff --git a/src/refactoring_guru/prototype/example/shapes/Circle.java b/src/refactoring_guru/prototype/example/shapes/Circle.java index 32aca7b..074e178 100644 --- a/src/refactoring_guru/prototype/example/shapes/Circle.java +++ b/src/refactoring_guru/prototype/example/shapes/Circle.java @@ -1,32 +1,27 @@ package refactoring_guru.prototype.example.shapes; public class Circle extends Shape { - public int radius; + public int radius; - public Circle() { - } - - public Circle(Circle target) { - super(target); - if (target != null) { - this.radius = target.radius; + public Circle() { } - } - @Override - public Shape clone() { - return new Circle(this); - } + public Circle(Circle target) { + super(target); + if (target != null) { + this.radius = target.radius; + } + } - @Override - public boolean equals(Object object) { - if (this == object) { - return true; + @Override + public Shape clone() { + return new Circle(this); } - if (object == null || getClass() != object.getClass()) { - return false; + + @Override + public boolean equals(Object object2) { + if (!(object2 instanceof Circle) || !super.equals(object2)) return false; + Circle shape2 = (Circle) object2; + return shape2.radius == radius; } - Shape shape = (Shape) object; - return radius == shape.x && radius == shape.y; - } } diff --git a/src/refactoring_guru/prototype/example/shapes/Rectangle.java b/src/refactoring_guru/prototype/example/shapes/Rectangle.java index 072b4fc..4adbf0e 100644 --- a/src/refactoring_guru/prototype/example/shapes/Rectangle.java +++ b/src/refactoring_guru/prototype/example/shapes/Rectangle.java @@ -1,36 +1,29 @@ package refactoring_guru.prototype.example.shapes; public class Rectangle extends Shape { - public int width; - public int height; + public int width; + public int height; - public Rectangle() { - } - - public Rectangle(Rectangle target) { - super(target); - if (target != null) { - this.width = target.width; - this.height = target.height; + public Rectangle() { } - } - @Override - public Shape clone() { - return new Rectangle(this); - } + public Rectangle(Rectangle target) { + super(target); + if (target != null) { + this.width = target.width; + this.height = target.height; + } + } - @Override - public boolean equals(Object object2) { - if (!(object2 instanceof Rectangle shape2) || !super.equals(object2)) { - return false; + @Override + public Shape clone() { + return new Rectangle(this); } - return shape2.width == width && shape2.height == height; - } - @Override - public int hashCode() { - return Integer.hashCode(width) - ^ Integer.hashCode(height); - } + @Override + public boolean equals(Object object2) { + if (!(object2 instanceof Rectangle) || !super.equals(object2)) return false; + Rectangle shape2 = (Rectangle) object2; + return shape2.width == width && shape2.height == height; + } } diff --git a/src/refactoring_guru/prototype/example/shapes/Shape.java b/src/refactoring_guru/prototype/example/shapes/Shape.java index 28215a7..6893a3f 100644 --- a/src/refactoring_guru/prototype/example/shapes/Shape.java +++ b/src/refactoring_guru/prototype/example/shapes/Shape.java @@ -3,32 +3,27 @@ import java.util.Objects; public abstract class Shape { - public int x; - public int y; - public String color; + public int x; + public int y; + public String color; - protected Shape() { - } - - protected Shape(Shape target) { - if (target != null) { - this.x = target.x; - this.y = target.y; - this.color = target.color; + public Shape() { } - } - public abstract Shape clone(); + public Shape(Shape target) { + if (target != null) { + this.x = target.x; + this.y = target.y; + this.color = target.color; + } + } - @Override - public boolean equals(Object object2) { - if (!(object2 instanceof Shape shape2)) return false; - return shape2.x == x && shape2.y == y && Objects.equals(shape2.color, color); - } + public abstract Shape clone(); - @Override - public int hashCode() { - return Integer.hashCode(x) - ^ Integer.hashCode(y); - } + @Override + public boolean equals(Object object2) { + if (!(object2 instanceof Shape)) return false; + Shape shape2 = (Shape) object2; + return shape2.x == x && shape2.y == y && Objects.equals(shape2.color, color); + } } diff --git a/src/refactoring_guru/proxy/example/Demo.java b/src/refactoring_guru/proxy/example/Demo.java index f9c47c4..4861f65 100644 --- a/src/refactoring_guru/proxy/example/Demo.java +++ b/src/refactoring_guru/proxy/example/Demo.java @@ -1,40 +1,35 @@ package refactoring_guru.proxy.example; -import refactoring_guru.proxy.example.downloader.Renderer; import refactoring_guru.proxy.example.downloader.YouTubeDownloader; import refactoring_guru.proxy.example.proxy.YouTubeCacheProxy; import refactoring_guru.proxy.example.some_cool_media_library.ThirdPartyYouTubeClass; -import java.util.logging.Logger; - public class Demo { - private static final Logger LOGGER = Logger.getLogger(Demo.class.getName()); - - public static void main(String[] args) { - final YouTubeDownloader naiveDownloader = new YouTubeDownloader(new ThirdPartyYouTubeClass(), new Renderer()); - final YouTubeDownloader smartDownloader = new YouTubeDownloader(new YouTubeCacheProxy(), new Renderer()); - - final long naive = test(naiveDownloader); - final long smart = test(smartDownloader); - - LOGGER.info("Time saved by caching proxy: " + (naive - smart) + "ms"); - } - - private static long test(YouTubeDownloader downloader) { - final long startTime = System.currentTimeMillis(); - simulateUserBehavior(downloader); - - final long estimatedTime = System.currentTimeMillis() - startTime; - LOGGER.info("Time elapsed: " + estimatedTime + "ms"); - return estimatedTime; - } - - private static void simulateUserBehavior(YouTubeDownloader downloader) { - downloader.renderPopularVideos(); - downloader.renderVideoPage("catzzzzzzzzz"); - downloader.renderPopularVideos(); - downloader.renderVideoPage("dancesvideoo"); - downloader.renderVideoPage("catzzzzzzzzz"); - downloader.renderVideoPage("someothervid"); - } + + public static void main(String[] args) { + YouTubeDownloader naiveDownloader = new YouTubeDownloader(new ThirdPartyYouTubeClass()); + YouTubeDownloader smartDownloader = new YouTubeDownloader(new YouTubeCacheProxy()); + + long naive = test(naiveDownloader); + long smart = test(smartDownloader); + System.out.print("Time saved by caching proxy: " + (naive - smart) + "ms"); + + } + + private static long test(YouTubeDownloader downloader) { + long startTime = System.currentTimeMillis(); + + // User behavior in our app: + downloader.renderPopularVideos(); + downloader.renderVideoPage("catzzzzzzzzz"); + downloader.renderPopularVideos(); + downloader.renderVideoPage("dancesvideoo"); + // Users might visit the same page quite often. + downloader.renderVideoPage("catzzzzzzzzz"); + downloader.renderVideoPage("someothervid"); + + long estimatedTime = System.currentTimeMillis() - startTime; + System.out.print("Time elapsed: " + estimatedTime + "ms\n"); + return estimatedTime; + } } \ No newline at end of file diff --git a/src/refactoring_guru/proxy/example/downloader/Renderer.java b/src/refactoring_guru/proxy/example/downloader/Renderer.java deleted file mode 100644 index 626f7ae..0000000 --- a/src/refactoring_guru/proxy/example/downloader/Renderer.java +++ /dev/null @@ -1,27 +0,0 @@ -package refactoring_guru.proxy.example.downloader; - -import refactoring_guru.proxy.example.some_cool_media_library.Video; - -import java.util.Map; - -public class Renderer { - private static final String SEPARATOR = "\n-------------------------------\n"; - - void renderVideo(Video video) { - System.out.println(SEPARATOR); - System.out.println("Video page (imagine fancy HTML)"); - System.out.println("ID: " + video.id); - System.out.println("Title: " + video.title); - System.out.println("Video: " + video.data); - System.out.println(SEPARATOR); - } - - void renderPopularVideos(Map videos) { - System.out.println(SEPARATOR); - System.out.println("Most popular videos on YouTube (imagine fancy HTML)"); - for (Video video : videos.values()) { - System.out.println("ID: " + video.id + " / Title: " + video.title); - } - System.out.println(SEPARATOR); - } -} diff --git a/src/refactoring_guru/proxy/example/downloader/YouTubeDownloader.java b/src/refactoring_guru/proxy/example/downloader/YouTubeDownloader.java index 28ef58a..1ae9d2c 100644 --- a/src/refactoring_guru/proxy/example/downloader/YouTubeDownloader.java +++ b/src/refactoring_guru/proxy/example/downloader/YouTubeDownloader.java @@ -3,32 +3,32 @@ import refactoring_guru.proxy.example.some_cool_media_library.ThirdPartyYouTubeLib; import refactoring_guru.proxy.example.some_cool_media_library.Video; -import java.util.Map; +import java.util.HashMap; public class YouTubeDownloader { - private final ThirdPartyYouTubeLib api; - private final Renderer renderer; + private ThirdPartyYouTubeLib api; - public YouTubeDownloader(ThirdPartyYouTubeLib api, Renderer renderer) { - this.api = api; - this.renderer = renderer; - } + public YouTubeDownloader(ThirdPartyYouTubeLib api) { + this.api = api; + } - public void renderVideoPage(String videoId) { - Video video = api.getVideo(videoId); - if (video != null) { - renderer.renderVideo(video); - } else { - throw new IllegalArgumentException("No more videos "); + public void renderVideoPage(String videoId) { + Video video = api.getVideo(videoId); + System.out.println("\n-------------------------------"); + System.out.println("Video page (imagine fancy HTML)"); + System.out.println("ID: " + video.id); + System.out.println("Title: " + video.title); + System.out.println("Video: " + video.data); + System.out.println("-------------------------------\n"); } - } - public void renderPopularVideos() { - Map list = api.popularVideos(); - if (list != null && !list.isEmpty()) { - renderer.renderPopularVideos(list); - } else { - throw new IllegalArgumentException("The List is empty "); + public void renderPopularVideos() { + HashMap list = api.popularVideos(); + System.out.println("\n-------------------------------"); + System.out.println("Most popular videos on YouTube (imagine fancy HTML)"); + for (Video video : list.values()) { + System.out.println("ID: " + video.id + " / Title: " + video.title); + } + System.out.println("-------------------------------\n"); } - } } diff --git a/src/refactoring_guru/proxy/example/proxy/YouTubeCacheProxy.java b/src/refactoring_guru/proxy/example/proxy/YouTubeCacheProxy.java index 676fb2b..7a2887c 100644 --- a/src/refactoring_guru/proxy/example/proxy/YouTubeCacheProxy.java +++ b/src/refactoring_guru/proxy/example/proxy/YouTubeCacheProxy.java @@ -5,32 +5,40 @@ import refactoring_guru.proxy.example.some_cool_media_library.Video; import java.util.HashMap; -import java.util.Map; public class YouTubeCacheProxy implements ThirdPartyYouTubeLib { - private final ThirdPartyYouTubeLib youtubeService; - private final Map cachePopular = new HashMap<>(); - private final Map cacheAll = new HashMap<>(); + private ThirdPartyYouTubeLib youtubeService; + private HashMap cachePopular = new HashMap(); + private HashMap cacheAll = new HashMap(); - public YouTubeCacheProxy() { - this.youtubeService = new ThirdPartyYouTubeClass(); - } + public YouTubeCacheProxy() { + this.youtubeService = new ThirdPartyYouTubeClass(); + } - @Override - public Map popularVideos() { - return cachePopular.isEmpty() ? youtubeService.popularVideos() : logAndReturn(cachePopular); - } + @Override + public HashMap popularVideos() { + if (cachePopular.isEmpty()) { + cachePopular = youtubeService.popularVideos(); + } else { + System.out.println("Retrieved list from cache."); + } + return cachePopular; + } - @Override - public Video getVideo(String videoId) { - return cacheAll.computeIfAbsent(videoId, key -> { - System.out.println("Fetching video '" + key + "' from YouTube service."); - return youtubeService.getVideo(key); - }); - } + @Override + public Video getVideo(String videoId) { + Video video = cacheAll.get(videoId); + if (video == null) { + video = youtubeService.getVideo(videoId); + cacheAll.put(videoId, video); + } else { + System.out.println("Retrieved video '" + videoId + "' from cache."); + } + return video; + } - private T logAndReturn(T result) { - System.out.println("Retrieved a list from cache."); - return result; - } + public void reset() { + cachePopular.clear(); + cacheAll.clear(); + } } diff --git a/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeClass.java b/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeClass.java index d9433d0..7c2e07e 100644 --- a/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeClass.java +++ b/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeClass.java @@ -1,42 +1,68 @@ package refactoring_guru.proxy.example.some_cool_media_library; import java.util.HashMap; -import java.util.Map; -import java.util.logging.Logger; public class ThirdPartyYouTubeClass implements ThirdPartyYouTubeLib { - private static final Logger LOGGER = Logger.getLogger(ThirdPartyYouTubeClass.class.getName()); - - @Override - public Map popularVideos() { - connectToServer("http://www.youtube.com"); - return fetchPopularVideos(); - } - - @Override - public Video getVideo(String videoId) { - connectToServer("http://www.youtube.com/" + videoId); - return fetchVideo(videoId); - } - - private void connectToServer(String server) { - LOGGER.info("Connecting to " + server + "... "); - LOGGER.info("Connected!" + "\n"); - } - - private Map fetchPopularVideos() { - LOGGER.info("Downloading popular videos... "); - Map videoMap = new HashMap<>(); - videoMap.put("catzzzzzzzzz", new Video("sadgahasgdas", "Catzzzz.avi")); - LOGGER.info("Done!" + "\n"); - return videoMap; - } - - private Video fetchVideo(String videoId) { - LOGGER.info("Downloading video... "); - Video video = new Video(videoId, "Some video title"); - LOGGER.info("Done!" + "\n"); - return video; - } + @Override + public HashMap popularVideos() { + connectToServer("http://www.youtube.com"); + return getRandomVideos(); + } + + @Override + public Video getVideo(String videoId) { + connectToServer("http://www.youtube.com/" + videoId); + return getSomeVideo(videoId); + } + + // ----------------------------------------------------------------------- + // Fake methods to simulate network activity. They as slow as a real life. + + private int random(int min, int max) { + return min + (int) (Math.random() * ((max - min) + 1)); + } + + private void experienceNetworkLatency() { + int randomLatency = random(5, 10); + for (int i = 0; i < randomLatency; i++) { + try { + Thread.sleep(100); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } + + private void connectToServer(String server) { + System.out.print("Connecting to " + server + "... "); + experienceNetworkLatency(); + System.out.print("Connected!" + "\n"); + } + + private HashMap getRandomVideos() { + System.out.print("Downloading populars... "); + + experienceNetworkLatency(); + HashMap hmap = new HashMap(); + hmap.put("catzzzzzzzzz", new Video("sadgahasgdas", "Catzzzz.avi")); + hmap.put("mkafksangasj", new Video("mkafksangasj", "Dog play with ball.mp4")); + hmap.put("dancesvideoo", new Video("asdfas3ffasd", "Dancing video.mpq")); + hmap.put("dlsdk5jfslaf", new Video("dlsdk5jfslaf", "Barcelona vs RealM.mov")); + hmap.put("3sdfgsd1j333", new Video("3sdfgsd1j333", "Programing lesson#1.avi")); + + System.out.print("Done!" + "\n"); + return hmap; + } + + private Video getSomeVideo(String videoId) { + System.out.print("Downloading video... "); + + experienceNetworkLatency(); + Video video = new Video(videoId, "Some video title"); + + System.out.print("Done!" + "\n"); + return video; + } + } diff --git a/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeLib.java b/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeLib.java index 2839975..e05ff22 100644 --- a/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeLib.java +++ b/src/refactoring_guru/proxy/example/some_cool_media_library/ThirdPartyYouTubeLib.java @@ -1,9 +1,9 @@ package refactoring_guru.proxy.example.some_cool_media_library; -import java.util.Map; +import java.util.HashMap; public interface ThirdPartyYouTubeLib { - Map popularVideos(); + HashMap popularVideos(); - Video getVideo(String videoId); + Video getVideo(String videoId); } diff --git a/src/refactoring_guru/proxy/example/some_cool_media_library/Video.java b/src/refactoring_guru/proxy/example/some_cool_media_library/Video.java index 4411287..96cf8b8 100644 --- a/src/refactoring_guru/proxy/example/some_cool_media_library/Video.java +++ b/src/refactoring_guru/proxy/example/some_cool_media_library/Video.java @@ -1,13 +1,13 @@ package refactoring_guru.proxy.example.some_cool_media_library; public class Video { - public String id; - public String title; - public String data; + public String id; + public String title; + public String data; - Video(String id, String title) { - this.id = id; - this.title = title; - this.data = "Random video."; - } + Video(String id, String title) { + this.id = id; + this.title = title; + this.data = "Random video."; + } } diff --git a/src/refactoring_guru/singleton/example/non_thread_safe/DemoMultiThread.java b/src/refactoring_guru/singleton/example/non_thread_safe/DemoMultiThread.java index 7bab4ee..848534b 100644 --- a/src/refactoring_guru/singleton/example/non_thread_safe/DemoMultiThread.java +++ b/src/refactoring_guru/singleton/example/non_thread_safe/DemoMultiThread.java @@ -1,33 +1,29 @@ package refactoring_guru.singleton.example.non_thread_safe; public class DemoMultiThread { - public static void main(String[] args) { - String textBlock = """ - \""" If you see the same value, then singleton was reused (yay!) - \"""If you see different values, then 2 singletons were created (booo!!) - \"""RESULT - """; - - System.out.println(textBlock); - Thread threadFoo = new Thread(new ThreadFoo()); - Thread threadBar = new Thread(new ThreadBar()); - threadFoo.start(); - threadBar.start(); - } + public static void main(String[] args) { + System.out.println("If you see the same value, then singleton was reused (yay!)" + "\n" + + "If you see different values, then 2 singletons were created (booo!!)" + "\n\n" + + "RESULT:" + "\n"); + Thread threadFoo = new Thread(new ThreadFoo()); + Thread threadBar = new Thread(new ThreadBar()); + threadFoo.start(); + threadBar.start(); + } - static class ThreadFoo implements Runnable { - @Override - public void run() { - Singleton singleton = Singleton.getInstance("FOO"); - System.out.println(singleton.value); + static class ThreadFoo implements Runnable { + @Override + public void run() { + Singleton singleton = Singleton.getInstance("FOO"); + System.out.println(singleton.value); + } } - } - static class ThreadBar implements Runnable { - @Override - public void run() { - Singleton singleton = Singleton.getInstance("BAR"); - System.out.println(singleton.value); + static class ThreadBar implements Runnable { + @Override + public void run() { + Singleton singleton = Singleton.getInstance("BAR"); + System.out.println(singleton.value); + } } - } } diff --git a/src/refactoring_guru/singleton/example/non_thread_safe/DemoSingleThread.java b/src/refactoring_guru/singleton/example/non_thread_safe/DemoSingleThread.java index fbc5b85..6aba849 100644 --- a/src/refactoring_guru/singleton/example/non_thread_safe/DemoSingleThread.java +++ b/src/refactoring_guru/singleton/example/non_thread_safe/DemoSingleThread.java @@ -1,17 +1,13 @@ package refactoring_guru.singleton.example.non_thread_safe; public class DemoSingleThread { - public static void main(String[] args) { - var textBlock = """ - If you see the same value, then singleton was reused (yay!) - If you see different values, then 2 singletons were created (booo!!) - RESULT - """; - - System.out.println(textBlock); - Singleton singleton = Singleton.getInstance("FOO"); - Singleton anotherSingleton = Singleton.getInstance("BAR"); - System.out.println(singleton.value); - System.out.println(anotherSingleton.value); - } + public static void main(String[] args) { + System.out.println("If you see the same value, then singleton was reused (yay!)" + "\n" + + "If you see different values, then 2 singletons were created (booo!!)" + "\n\n" + + "RESULT:" + "\n"); + Singleton singleton = Singleton.getInstance("FOO"); + Singleton anotherSingleton = Singleton.getInstance("BAR"); + System.out.println(singleton.value); + System.out.println(anotherSingleton.value); + } } diff --git a/src/refactoring_guru/singleton/example/non_thread_safe/Singleton.java b/src/refactoring_guru/singleton/example/non_thread_safe/Singleton.java index 22c00cd..d091303 100644 --- a/src/refactoring_guru/singleton/example/non_thread_safe/Singleton.java +++ b/src/refactoring_guru/singleton/example/non_thread_safe/Singleton.java @@ -1,29 +1,25 @@ package refactoring_guru.singleton.example.non_thread_safe; public final class Singleton { - private static Singleton instance; - public String value; + private static Singleton instance; + public String value; - /** - * EN: The following code emulates slow initialization. - *

- * RU: Этот код эмулирует медленную инициализацию. - * - * @param value example value - */ - private Singleton(String value) { - try { - Thread.sleep(1000); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); + private Singleton(String value) { + // EN: The following code emulates slow initialization. + // + // RU: Этот код эмулирует медленную инициализацию. + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + this.value = value; } - this.value = value; - } - public static Singleton getInstance(String value) { - if (instance == null) { - instance = new Singleton(value); + public static Singleton getInstance(String value) { + if (instance == null) { + instance = new Singleton(value); + } + return instance; } - return instance; - } } diff --git a/src/refactoring_guru/singleton/example/thread_safe/DemoMultiThread.java b/src/refactoring_guru/singleton/example/thread_safe/DemoMultiThread.java index a37e204..a0fd882 100644 --- a/src/refactoring_guru/singleton/example/thread_safe/DemoMultiThread.java +++ b/src/refactoring_guru/singleton/example/thread_safe/DemoMultiThread.java @@ -1,33 +1,29 @@ package refactoring_guru.singleton.example.thread_safe; public class DemoMultiThread { - public static void main(String[] args) { - var textBlock = """ - If you see the same value, then singleton was reused (yay!) - If you see different values, then 2 singletons were created (booo!!) - RESULT - """; - - System.out.println(textBlock); - Thread threadFoo = new Thread(new ThreadFoo()); - Thread threadBar = new Thread(new ThreadBar()); - threadFoo.start(); - threadBar.start(); - } + public static void main(String[] args) { + System.out.println("If you see the same value, then singleton was reused (yay!)" + "\n" + + "If you see different values, then 2 singletons were created (booo!!)" + "\n\n" + + "RESULT:" + "\n"); + Thread threadFoo = new Thread(new ThreadFoo()); + Thread threadBar = new Thread(new ThreadBar()); + threadFoo.start(); + threadBar.start(); + } - static class ThreadFoo implements Runnable { - @Override - public void run() { - Singleton singleton = Singleton.getInstance("FOO"); - System.out.println(singleton.value); + static class ThreadFoo implements Runnable { + @Override + public void run() { + Singleton singleton = Singleton.getInstance("FOO"); + System.out.println(singleton.value); + } } - } - static class ThreadBar implements Runnable { - @Override - public void run() { - Singleton singleton = Singleton.getInstance("BAR"); - System.out.println(singleton.value); + static class ThreadBar implements Runnable { + @Override + public void run() { + Singleton singleton = Singleton.getInstance("BAR"); + System.out.println(singleton.value); + } } - } } diff --git a/src/refactoring_guru/singleton/example/thread_safe/Singleton.java b/src/refactoring_guru/singleton/example/thread_safe/Singleton.java index 0f03d31..95b8365 100644 --- a/src/refactoring_guru/singleton/example/thread_safe/Singleton.java +++ b/src/refactoring_guru/singleton/example/thread_safe/Singleton.java @@ -1,59 +1,52 @@ package refactoring_guru.singleton.example.thread_safe; -/** - * EN: The field must be declared volatile so that double check lock would - * work correctly. - *

- * RU: Поле обязательно должно быть объявлено volatile, чтобы двойная - * проверка блокировки сработала как надо. - */ public final class Singleton { - private static Singleton instance; + // EN: The field must be declared volatile so that double check lock would + // work correctly. + // + // RU: Поле обязательно должно быть объявлено volatile, чтобы двойная + // проверка блокировки сработала как надо. + private static volatile Singleton instance; - public String value; + public String value; - private Singleton(String value) { - this.value = value; - } - - /** - * It exists to prevent race condition between multiple threads that may - * EN: The approach taken here is called double-checked locking (DCL). - * attempt to get singleton instance at the same time, creating - * separate instances as a result. - *

- * It may seem that having the `result` variable here is completely - * pointless. There is, however, a very important caveat when - * implementing double-checked locking in Java, which is solved by - * introducing this local variable. - *

- * You can read more info DCL issues in Java here: - * {@link ...} - *

- * RU: Техника, которую мы здесь применяем называется «блокировка с - * двойной проверкой» (Double-Checked Locking). Она применяется, чтобы - * предотвратить создание нескольких объектов-одиночек, если метод будет - * вызван из нескольких потоков одновременно. - *

- * Хотя переменная `result` вполне оправданно кажется здесь лишней, она - * помогает избежать подводных камней реализации DCL в Java. - *

- * Больше об этой проблеме можно почитать здесь: - * {@link ...} - * - * @param value value which can be provided - * @return the instance of the Singleton class - */ - public static Singleton getInstance(String value) { - Singleton result = instance; - if (result != null) { - return result; + private Singleton(String value) { + this.value = value; } - synchronized (Singleton.class) { - if (instance == null) { - instance = new Singleton(value); - } - return instance; + + public static Singleton getInstance(String value) { + // EN: The approach taken here is called double-checked locking (DCL). + // It exists to prevent race condition between multiple threads that may + // attempt to get singleton instance at the same time, creating + // separate instances as a result. + // + // It may seem that having the `result` variable here is completely + // pointless. There is, however, a very important caveat when + // implementing double-checked locking in Java, which is solved by + // introducing this local variable. + // + // You can read more info DCL issues in Java here: + // https://refactoring.guru/java-dcl-issue + // + // RU: Техника, которую мы здесь применяем называется «блокировка с + // двойной проверкой» (Double-Checked Locking). Она применяется, чтобы + // предотвратить создание нескольких объектов-одиночек, если метод будет + // вызван из нескольких потоков одновременно. + // + // Хотя переменная `result` вполне оправданно кажется здесь лишней, она + // помогает избежать подводных камней реализации DCL в Java. + // + // Больше об этой проблеме можно почитать здесь: + // https://refactoring.guru/ru/java-dcl-issue + Singleton result = instance; + if (result != null) { + return result; + } + synchronized(Singleton.class) { + if (instance == null) { + instance = new Singleton(value); + } + return instance; + } } - } } diff --git a/src/refactoring_guru/state/example/Demo.java b/src/refactoring_guru/state/example/Demo.java index 20cd91e..03b89dd 100644 --- a/src/refactoring_guru/state/example/Demo.java +++ b/src/refactoring_guru/state/example/Demo.java @@ -5,13 +5,13 @@ /** * EN: Demo class. Everything comes together here. - *

+ * * RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - public static void main(String[] args) { - Player player = new Player(); - UI ui = new UI(player); - ui.init(); - } + public static void main(String[] args) { + Player player = new Player(); + UI ui = new UI(player); + ui.init(); + } } diff --git a/src/refactoring_guru/state/example/states/LockedState.java b/src/refactoring_guru/state/example/states/LockedState.java index 69f4303..1dde3f1 100644 --- a/src/refactoring_guru/state/example/states/LockedState.java +++ b/src/refactoring_guru/state/example/states/LockedState.java @@ -5,40 +5,39 @@ /** * EN: Concrete states provide the special implementation for all interface * methods. - *

+ * * RU: Конкретные состояния реализуют методы абстрактного состояния по-своему. */ public class LockedState extends State { - private static final String LOCKED = "Locked..."; - public LockedState(Player player) { - super(player); - player.setPlaying(false); - } + LockedState(Player player) { + super(player); + player.setPlaying(false); + } - @Override - public String onLock() { - if (player.isPlaying()) { - player.changeState(new ReadyState(player)); - return "Stop playing"; - } else { - return LOCKED; + @Override + public String onLock() { + if (player.isPlaying()) { + player.changeState(new ReadyState(player)); + return "Stop playing"; + } else { + return "Locked..."; + } } - } - @Override - public String onPlay() { - player.changeState(new ReadyState(player)); - return "Ready"; - } + @Override + public String onPlay() { + player.changeState(new ReadyState(player)); + return "Ready"; + } - @Override - public String onNext() { - return LOCKED; - } + @Override + public String onNext() { + return "Locked..."; + } - @Override - public String onPrevious() { - return LOCKED; - } + @Override + public String onPrevious() { + return "Locked..."; + } } diff --git a/src/refactoring_guru/state/example/states/PlayingState.java b/src/refactoring_guru/state/example/states/PlayingState.java index 9a6cf94..8b42e70 100644 --- a/src/refactoring_guru/state/example/states/PlayingState.java +++ b/src/refactoring_guru/state/example/states/PlayingState.java @@ -4,30 +4,30 @@ public class PlayingState extends State { - public PlayingState(Player player) { - super(player); - } + PlayingState(Player player) { + super(player); + } - @Override - public String onLock() { - player.changeState(new LockedState(player)); - player.setCurrentTrackAfterStop(); - return "Stop playing"; - } + @Override + public String onLock() { + player.changeState(new LockedState(player)); + player.setCurrentTrackAfterStop(); + return "Stop playing"; + } - @Override - public String onPlay() { - player.changeState(new ReadyState(player)); - return "Paused..."; - } + @Override + public String onPlay() { + player.changeState(new ReadyState(player)); + return "Paused..."; + } - @Override - public String onNext() { - return player.nextTrack(); - } + @Override + public String onNext() { + return player.nextTrack(); + } - @Override - public String onPrevious() { - return player.previousTrack(); - } + @Override + public String onPrevious() { + return player.previousTrack(); + } } diff --git a/src/refactoring_guru/state/example/states/ReadyState.java b/src/refactoring_guru/state/example/states/ReadyState.java index 5287797..c27e138 100644 --- a/src/refactoring_guru/state/example/states/ReadyState.java +++ b/src/refactoring_guru/state/example/states/ReadyState.java @@ -4,36 +4,35 @@ /** * EN: They can also trigger state transitions in the context. - *

+ * * RU: Они также могут переводить контекст в другие состояния. */ public class ReadyState extends State { - private static final String LOCKED = "Locked..."; - public ReadyState(Player player) { - super(player); - } + public ReadyState(Player player) { + super(player); + } - @Override - public String onLock() { - player.changeState(new LockedState(player)); - return LOCKED; - } + @Override + public String onLock() { + player.changeState(new LockedState(player)); + return "Locked..."; + } - @Override - public String onPlay() { - String action = player.startPlayback(); - player.changeState(new PlayingState(player)); - return action; - } + @Override + public String onPlay() { + String action = player.startPlayback(); + player.changeState(new PlayingState(player)); + return action; + } - @Override - public String onNext() { - return LOCKED; - } + @Override + public String onNext() { + return "Locked..."; + } - @Override - public String onPrevious() { - return LOCKED; - } + @Override + public String onPrevious() { + return "Locked..."; + } } diff --git a/src/refactoring_guru/state/example/states/State.java b/src/refactoring_guru/state/example/states/State.java index f038f3d..8263cf9 100644 --- a/src/refactoring_guru/state/example/states/State.java +++ b/src/refactoring_guru/state/example/states/State.java @@ -4,28 +4,25 @@ /** * EN: Common interface for all states. - *

+ * * RU: Общий интерфейс всех состояний. */ public abstract class State { - Player player; + Player player; - /** - * EN: Context passes itself through the state constructor. This may help a - * state to fetch some useful context data if needed. - *

- * RU: Контекст передаёт себя в конструктор состояния, чтобы состояние могло - * обращаться к его данным и методам в будущем, если потребуется. - */ - protected State(Player player) { - this.player = player; - } + /** + * EN: Context passes itself through the state constructor. This may help a + * state to fetch some useful context data if needed. + * + * RU: Контекст передаёт себя в конструктор состояния, чтобы состояние могло + * обращаться к его данным и методам в будущем, если потребуется. + */ + State(Player player) { + this.player = player; + } - public abstract String onLock(); - - public abstract String onPlay(); - - public abstract String onNext(); - - public abstract String onPrevious(); + public abstract String onLock(); + public abstract String onPlay(); + public abstract String onNext(); + public abstract String onPrevious(); } diff --git a/src/refactoring_guru/state/example/ui/Player.java b/src/refactoring_guru/state/example/ui/Player.java index 837bbc1..c8b7cb7 100644 --- a/src/refactoring_guru/state/example/ui/Player.java +++ b/src/refactoring_guru/state/example/ui/Player.java @@ -7,57 +7,56 @@ import java.util.List; public class Player { - private static final String PLAY = "Playing "; - private State state; - private boolean playing = false; - private final List playlist = new ArrayList<>(); - private int currentTrack = 0; - - public Player() { - this.state = new ReadyState(this); - setPlaying(true); - for (int i = 1; i <= 12; i++) { - playlist.add("Track " + i); - } - } - - public void changeState(State state) { - this.state = state; - } - - public State getState() { - return state; - } - - public void setPlaying(boolean playing) { - this.playing = playing; - } - - public boolean isPlaying() { - return playing; - } - - public String startPlayback() { - return PLAY + playlist.get(currentTrack); - } - - public String nextTrack() { - currentTrack++; - if (currentTrack > playlist.size() - 1) { - currentTrack = 0; - } - return PLAY + playlist.get(currentTrack); - } - - public String previousTrack() { - currentTrack--; - if (currentTrack < 0) { - currentTrack = playlist.size() - 1; - } - return PLAY + playlist.get(currentTrack); - } - - public void setCurrentTrackAfterStop() { - this.currentTrack = 0; - } + private State state; + private boolean playing = false; + private List playlist = new ArrayList<>(); + private int currentTrack = 0; + + public Player() { + this.state = new ReadyState(this); + setPlaying(true); + for (int i = 1; i <= 12; i++) { + playlist.add("Track " + i); + } + } + + public void changeState(State state) { + this.state = state; + } + + public State getState() { + return state; + } + + public void setPlaying(boolean playing) { + this.playing = playing; + } + + public boolean isPlaying() { + return playing; + } + + public String startPlayback() { + return "Playing " + playlist.get(currentTrack); + } + + public String nextTrack() { + currentTrack++; + if (currentTrack > playlist.size() - 1) { + currentTrack = 0; + } + return "Playing " + playlist.get(currentTrack); + } + + public String previousTrack() { + currentTrack--; + if (currentTrack < 0) { + currentTrack = playlist.size() - 1; + } + return "Playing " + playlist.get(currentTrack); + } + + public void setCurrentTrackAfterStop() { + this.currentTrack = 0; + } } diff --git a/src/refactoring_guru/state/example/ui/UI.java b/src/refactoring_guru/state/example/ui/UI.java index e4ce600..9f66146 100644 --- a/src/refactoring_guru/state/example/ui/UI.java +++ b/src/refactoring_guru/state/example/ui/UI.java @@ -4,43 +4,43 @@ import java.awt.*; public class UI { - private final Player player; - private static final JTextField textField = new JTextField(); + private Player player; + private static JTextField textField = new JTextField(); - public UI(Player player) { - this.player = player; - } + public UI(Player player) { + this.player = player; + } - public void init() { - JFrame frame = new JFrame("Test player"); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - JPanel context = new JPanel(); - context.setLayout(new BoxLayout(context, BoxLayout.Y_AXIS)); - frame.getContentPane().add(context); - JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER)); - context.add(textField); - context.add(buttons); + public void init() { + JFrame frame = new JFrame("Test player"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel context = new JPanel(); + context.setLayout(new BoxLayout(context, BoxLayout.Y_AXIS)); + frame.getContentPane().add(context); + JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER)); + context.add(textField); + context.add(buttons); - // EN: Context delegates handling user's input to a state object. - // Naturally, the outcome will depend on what state is currently active, - // since all states can handle the input differently. - // - // RU: Контекст заставляет состояние реагировать на пользовательский - // ввод вместо себя. Реакция может быть разной в зависимости от того, - // какое состояние сейчас активно. - JButton play = new JButton("Play"); - play.addActionListener(e -> textField.setText(player.getState().onPlay())); - JButton stop = new JButton("Stop"); - stop.addActionListener(e -> textField.setText(player.getState().onLock())); - JButton next = new JButton("Next"); - next.addActionListener(e -> textField.setText(player.getState().onNext())); - JButton prev = new JButton("Prev"); - prev.addActionListener(e -> textField.setText(player.getState().onPrevious())); - frame.setVisible(true); - frame.setSize(300, 100); - buttons.add(play); - buttons.add(stop); - buttons.add(next); - buttons.add(prev); - } + // EN: Context delegates handling user's input to a state object. + // Naturally, the outcome will depend on what state is currently active, + // since all states can handle the input differently. + // + // RU: Контекст заставляет состояние реагировать на пользовательский + // ввод вместо себя. Реакция может быть разной в зависимости от того, + // какое состояние сейчас активно. + JButton play = new JButton("Play"); + play.addActionListener(e -> textField.setText(player.getState().onPlay())); + JButton stop = new JButton("Stop"); + stop.addActionListener(e -> textField.setText(player.getState().onLock())); + JButton next = new JButton("Next"); + next.addActionListener(e -> textField.setText(player.getState().onNext())); + JButton prev = new JButton("Prev"); + prev.addActionListener(e -> textField.setText(player.getState().onPrevious())); + frame.setVisible(true); + frame.setSize(300, 100); + buttons.add(play); + buttons.add(stop); + buttons.add(next); + buttons.add(prev); + } } diff --git a/src/refactoring_guru/strategy/example/Demo.java b/src/refactoring_guru/strategy/example/Demo.java index e556297..5182c15 100644 --- a/src/refactoring_guru/strategy/example/Demo.java +++ b/src/refactoring_guru/strategy/example/Demo.java @@ -1,82 +1,95 @@ package refactoring_guru.strategy.example; -import refactoring_guru.strategy.example.init.PaymentMethod; -import refactoring_guru.strategy.example.init.Product; import refactoring_guru.strategy.example.order.Order; +import refactoring_guru.strategy.example.strategies.PayByCreditCard; +import refactoring_guru.strategy.example.strategies.PayByPayPal; import refactoring_guru.strategy.example.strategies.PayStrategy; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; /** * EN: World first console e-commerce application. - *

- * RU: Первый в мире консольный интернет магазин. + * + * RU: Первый в мире консольный интерет магазин. */ public class Demo { - private static final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); - private static final Order order = new Order(); - private static PayStrategy strategy; + private static Map priceOnProducts = new HashMap<>(); + private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + private static Order order = new Order(); + private static PayStrategy strategy; - private static final String PRODUCT_SELECTION_TEXT = """ - Please select a product: - 1 - Mother board - 2 - CPU - 3 - HDD - 4 - Memory - """; + static { + priceOnProducts.put(1, 2200); + priceOnProducts.put(2, 1850); + priceOnProducts.put(3, 1100); + priceOnProducts.put(4, 890); + } - private static final String PAYMENT_METHOD_TEXT = """ - Please select a payment method: - 1 - PalPay - 2 - Credit Card - """; + public static void main(String[] args) throws IOException { + while (!order.isClosed()) { + int cost; - public static void main(String[] args) throws IOException { - while (!order.isClosed()) { - processUserInput(); - processPayment(); - } - } + String continueChoice; + do { + System.out.print("Please, select a product:" + "\n" + + "1 - Mother board" + "\n" + + "2 - CPU" + "\n" + + "3 - HDD" + "\n" + + "4 - Memory" + "\n"); + int choice = Integer.parseInt(reader.readLine()); + cost = priceOnProducts.get(choice); + System.out.print("Count: "); + int count = Integer.parseInt(reader.readLine()); + order.setTotalCost(cost * count); + System.out.print("Do you wish to continue selecting products? Y/N: "); + continueChoice = reader.readLine(); + } while (continueChoice.equalsIgnoreCase("Y")); - private static void processUserInput() throws IOException { - String continueChoice = ""; - do { - System.out.print(PRODUCT_SELECTION_TEXT); - try { - int choice = Integer.parseInt(bufferedReader.readLine()); - Product product = Product.fromChoice(choice); - System.out.print("Count: "); - int count = Integer.parseInt(bufferedReader.readLine()); - order.setTotalCost(product.getPrice() * count); - } catch (IllegalArgumentException e) { - System.out.println("Invalid input. Please try again."); - continue; - } - System.out.print("Do you wish to continue selecting products? Y/N: "); - continueChoice = bufferedReader.readLine(); - } while (continueChoice.equalsIgnoreCase("Y")); - } + if (strategy == null) { + System.out.println("Please, select a payment method:" + "\n" + + "1 - PalPay" + "\n" + + "2 - Credit Card"); + String paymentMethod = reader.readLine(); - private static void processPayment() throws IOException { - if (strategy == null) { - System.out.println(PAYMENT_METHOD_TEXT); - var paymentMethod = bufferedReader.readLine(); - strategy = PaymentMethod.fromChoice(Integer.parseInt(paymentMethod)).createStrategy(); - } + // EN: Client creates different strategies based on input from + // user, application configuration, etc. + // + // RU: Клиент создаёт различные стратегии на основании + // пользовательских данных, конфигурации и прочих параметров. + if (paymentMethod.equals("1")) { + strategy = new PayByPayPal(); + } else { + strategy = new PayByCreditCard(); + } + } - order.processOrder(strategy); + // EN: Order object delegates gathering payment data to strategy + // object, since only strategies know what data they need to + // process a payment. + // + // RU: Объект заказа делегирует сбор платёжных данны стратегии, + // т.к. только стратегии знают какие данные им нужны для приёма + // оплаты. + order.processOrder(strategy); - System.out.print("Pay " + order.getTotalCost() + " units or Continue shopping? P/C: "); - var proceed = bufferedReader.readLine(); - if (proceed.equalsIgnoreCase("P")) { - if (strategy.pay(order.getTotalCost())) { - System.out.println("Payment has been successful."); - } else { - System.out.println("FAIL! Please, check your data."); - } - order.setClosed(); + System.out.print("Pay " + order.getTotalCost() + " units or Continue shopping? P/C: "); + String proceed = reader.readLine(); + if (proceed.equalsIgnoreCase("P")) { + // EN: Finally, strategy handles the payment. + // + // RU: И наконец, стратегия запускает приём платежа. + if (strategy.pay(order.getTotalCost())) { + System.out.println("Payment has been successful."); + } else { + System.out.println("FAIL! Please, check your data."); + } + order.setClosed(); + } + } } - } } + diff --git a/src/refactoring_guru/strategy/example/init/PaymentMethod.java b/src/refactoring_guru/strategy/example/init/PaymentMethod.java deleted file mode 100644 index 5440424..0000000 --- a/src/refactoring_guru/strategy/example/init/PaymentMethod.java +++ /dev/null @@ -1,37 +0,0 @@ -package refactoring_guru.strategy.example.init; - -import refactoring_guru.strategy.example.strategies.PayByCreditCard; -import refactoring_guru.strategy.example.strategies.PayByPayPal; -import refactoring_guru.strategy.example.strategies.PayStrategy; - -public enum PaymentMethod { - PAYPAL(1) { - @Override - public PayStrategy createStrategy() { - return new PayByPayPal(); - } - }, - CREDIT_CARD(2) { - @Override - public PayStrategy createStrategy() { - return new PayByCreditCard(); - } - }; - - private final int choice; - - PaymentMethod(int choice) { - this.choice = choice; - } - - public abstract PayStrategy createStrategy(); - - public static PaymentMethod fromChoice(int choice) { - for (PaymentMethod method : values()) { - if (method.choice == choice) { - return method; - } - } - throw new IllegalArgumentException("Invalid choice: " + choice); - } -} diff --git a/src/refactoring_guru/strategy/example/init/Product.java b/src/refactoring_guru/strategy/example/init/Product.java deleted file mode 100644 index d27849b..0000000 --- a/src/refactoring_guru/strategy/example/init/Product.java +++ /dev/null @@ -1,29 +0,0 @@ -package refactoring_guru.strategy.example.init; - -public enum Product { - MOTHER_BOARD(1, 2200), - CPU(2, 1850), - HDD(3, 1100), - MEMORY(4, 890); - - private final int choice; - private final int price; - - Product(int choice, int price) { - this.choice = choice; - this.price = price; - } - - public int getPrice() { - return price; - } - - public static Product fromChoice(int choice) { - for (Product product : values()) { - if (product.choice == choice) { - return product; - } - } - throw new IllegalArgumentException("Invalid choice: " + choice); - } -} diff --git a/src/refactoring_guru/strategy/example/order/Order.java b/src/refactoring_guru/strategy/example/order/Order.java index 69edfe3..f8695c7 100644 --- a/src/refactoring_guru/strategy/example/order/Order.java +++ b/src/refactoring_guru/strategy/example/order/Order.java @@ -6,40 +6,37 @@ * EN: Order class. Doesn't know the concrete payment method (strategy) user has * picked. It uses common strategy interface to delegate collecting payment data * to strategy object. It can be used to save order to database. - *

+ * * RU: Класс заказа. Ничего не знает о том каким способом (стратегией) будет * расчитыватся клиент, а просто вызывает метод оплаты. Все остальное стратегия * делает сама. */ public class Order { - private int totalCost = 0; - private boolean isClosed = false; - - /** - * EN: Here we could collect and store payment data from the strategy. - *

- * RU: Здесь мы могли бы забрать и сохранить платежные данные из - * стратегии. - * - * @param strategy given option - */ - public void processOrder(PayStrategy strategy) { - strategy.collectPaymentDetails(); - } - - public void setTotalCost(int cost) { - this.totalCost += cost; - } - - public int getTotalCost() { - return totalCost; - } - - public boolean isClosed() { - return isClosed; - } - - public void setClosed() { - isClosed = true; - } -} \ No newline at end of file + private int totalCost = 0; + private boolean isClosed = false; + + public void processOrder(PayStrategy strategy) { + strategy.collectPaymentDetails(); + // EN: Here we could collect and store payment data from the strategy. + // + // RU: Здесь мы могли бы забрать и сохранить платежные данные из + // стратегии. + } + + public void setTotalCost(int cost) { + this.totalCost += cost; + } + + public int getTotalCost() { + return totalCost; + } + + public boolean isClosed() { + return isClosed; + } + + public void setClosed() { + isClosed = true; + } +} + diff --git a/src/refactoring_guru/strategy/example/strategies/CreditCard.java b/src/refactoring_guru/strategy/example/strategies/CreditCard.java index 717135d..20a09d5 100644 --- a/src/refactoring_guru/strategy/example/strategies/CreditCard.java +++ b/src/refactoring_guru/strategy/example/strategies/CreditCard.java @@ -2,22 +2,28 @@ /** * EN: Dummy credit card class. - *

+ * * RU: Очень наивная реализация кредитной карты. */ public class CreditCard { - private int amount; + private int amount; + private String number; + private String date; + private String cvv; - public CreditCard() { - this.amount = 100_000; - } + CreditCard(String number, String date, String cvv) { + this.amount = 100_000; + this.number = number; + this.date = date; + this.cvv = cvv; + } - public void setAmount(int amount) { - this.amount = amount; - } + public void setAmount(int amount) { + this.amount = amount; + } - public int getAmount() { - return amount; - } + public int getAmount() { + return amount; + } } diff --git a/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java b/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java index 187b5d4..8deea76 100644 --- a/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java +++ b/src/refactoring_guru/strategy/example/strategies/PayByCreditCard.java @@ -1,47 +1,63 @@ package refactoring_guru.strategy.example.strategies; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + /** * EN: Concrete strategy. Implements credit card payment method. - *

+ * * RU: Конкретная стратегия. Реализует оплату корзины интернет магазина * кредитной картой клиента. */ public class PayByCreditCard implements PayStrategy { - private CreditCard card; - - /** - * EN: Collect credit card data. - *

- * RU: Собираем данные карты клиента. - */ - @Override - public void collectPaymentDetails() { - System.out.print("Enter the card number: "); - System.out.print("Enter the card expiration date 'mm/yy': "); - System.out.print("Enter the CVV code: "); - - card = new CreditCard(); - } - - /** - * EN: After card validation we can charge customer's credit card. - *

- * RU: После проверки карты мы можем совершить оплату. Если клиент - * продолжает покупки, мы не запрашиваем карту заново. - */ - @Override - public boolean pay(int paymentAmount) { - if (cardIsPresent()) { - System.out.println("Paying " + paymentAmount + " using Credit Card."); - card.setAmount(card.getAmount() - paymentAmount); - return true; - } else { - return false; + private final BufferedReader READER = new BufferedReader(new InputStreamReader(System.in)); + private CreditCard card; + + /** + * EN: Collect credit card data. + * + * RU: Собираем данные карты клиента. + */ + @Override + public void collectPaymentDetails() { + try { + System.out.print("Enter the card number: "); + String number = READER.readLine(); + System.out.print("Enter the card expiration date 'mm/yy': "); + String date = READER.readLine(); + System.out.print("Enter the CVV code: "); + String cvv = READER.readLine(); + card = new CreditCard(number, date, cvv); + + // EN: Validate credit card number... + // + // RU: Валидируем номер карты... + + } catch (IOException ex) { + ex.printStackTrace(); + } } - } - private boolean cardIsPresent() { - return card != null; - } + /** + * EN: After card validation we can charge customer's credit card. + * + * RU: После проверки карты мы можем совершить оплату. Если клиент + * продолжает покупки, мы не запрашиваем карту заново. + */ + @Override + public boolean pay(int paymentAmount) { + if (cardIsPresent()) { + System.out.println("Paying " + paymentAmount + " using Credit Card."); + card.setAmount(card.getAmount() - paymentAmount); + return true; + } else { + return false; + } + } + + private boolean cardIsPresent() { + return card != null; + } } diff --git a/src/refactoring_guru/strategy/example/strategies/PayByPayPal.java b/src/refactoring_guru/strategy/example/strategies/PayByPayPal.java index 3c7c4f0..fe6b963 100644 --- a/src/refactoring_guru/strategy/example/strategies/PayByPayPal.java +++ b/src/refactoring_guru/strategy/example/strategies/PayByPayPal.java @@ -8,69 +8,69 @@ /** * EN: Concrete strategy. Implements PayPal payment method. - *

+ * * RU: Конкретная стратегия. Реализует оплату корзины интернет магазина через * платежную систему PayPal. */ public class PayByPayPal implements PayStrategy { - private static final Map DATA_BASE = new HashMap<>(); - private final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); - private String email; - private String password; - private boolean signedIn; + private static final Map DATA_BASE = new HashMap<>(); + private final BufferedReader READER = new BufferedReader(new InputStreamReader(System.in)); + private String email; + private String password; + private boolean signedIn; - static { - DATA_BASE.put("amanda1985", "amanda@ya.com"); - DATA_BASE.put("qwerty", "john@amazon.eu"); - } + static { + DATA_BASE.put("amanda1985", "amanda@ya.com"); + DATA_BASE.put("qwerty", "john@amazon.eu"); + } - /** - * EN: Collect customer's data. - *

- * RU: Собираем данные от клиента. - */ - @Override - public void collectPaymentDetails() { - try { - while (!signedIn) { - System.out.print("Enter the user's email: "); - email = bufferedReader.readLine(); - System.out.print("Enter the password: "); - password = bufferedReader.readLine(); - if (verify()) { - System.out.println("Data verification has been successful."); - } else { - System.out.println("Wrong email or password!"); + /** + * EN: Collect customer's data. + * + * RU: Собираем данные от клиента. + */ + @Override + public void collectPaymentDetails() { + try { + while (!signedIn) { + System.out.print("Enter the user's email: "); + email = READER.readLine(); + System.out.print("Enter the password: "); + password = READER.readLine(); + if (verify()) { + System.out.println("Data verification has been successful."); + } else { + System.out.println("Wrong email or password!"); + } + } + } catch (IOException ex) { + ex.printStackTrace(); } - } - } catch (IOException ex) { - ex.printStackTrace(); } - } - /** - * EN: Save customer data for future shopping attempts. - *

- * RU: Если клиент уже вошел в систему, то для следующей оплаты данные - * вводить не придется. - */ - @Override - public boolean pay(int paymentAmount) { - if (signedIn) { - System.out.println("Paying " + paymentAmount + " using PayPal."); - return true; - } else { - return false; + private boolean verify() { + setSignedIn(email.equals(DATA_BASE.get(password))); + return signedIn; } - } - private boolean verify() { - setSignedIn(email.equals(DATA_BASE.get(password))); - return signedIn; - } + /** + * EN: Save customer data for future shopping attempts. + * + * RU: Если клиент уже вошел в систему, то для следующей оплаты данные + * вводить не придется. + */ + @Override + public boolean pay(int paymentAmount) { + if (signedIn) { + System.out.println("Paying " + paymentAmount + " using PayPal."); + return true; + } else { + return false; + } + } - private void setSignedIn(boolean signedIn) { - this.signedIn = signedIn; - } + private void setSignedIn(boolean signedIn) { + this.signedIn = signedIn; + } } diff --git a/src/refactoring_guru/strategy/example/strategies/PayStrategy.java b/src/refactoring_guru/strategy/example/strategies/PayStrategy.java index 28f9806..45a20c9 100644 --- a/src/refactoring_guru/strategy/example/strategies/PayStrategy.java +++ b/src/refactoring_guru/strategy/example/strategies/PayStrategy.java @@ -2,12 +2,11 @@ /** * EN: Common interface for all strategies. - *

+ * * RU: Общий интерфейс всех стратегий. */ public interface PayStrategy { - boolean pay(int paymentAmount); - - void collectPaymentDetails(); + boolean pay(int paymentAmount); + void collectPaymentDetails(); } diff --git a/src/refactoring_guru/template_method/example/Demo.java b/src/refactoring_guru/template_method/example/Demo.java index 9429362..dd2735c 100644 --- a/src/refactoring_guru/template_method/example/Demo.java +++ b/src/refactoring_guru/template_method/example/Demo.java @@ -10,44 +10,37 @@ /** * EN: Demo class. Everything comes together here. - *

+ * * RU: Демо-класс. Здесь всё сводится воедино. */ public class Demo { - public static void main(String[] args) { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { - System.out.print("Input username: "); - String userName = reader.readLine(); - System.out.print("Input password: "); - String password = reader.readLine(); - System.out.print("Input message: "); - String message = reader.readLine(); + public static void main(String[] args) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + Network network = null; + System.out.print("Input user name: "); + String userName = reader.readLine(); + System.out.print("Input password: "); + String password = reader.readLine(); - Network network = getNetwork(reader, userName, password); - if (network != null) { - network.logIn(userName, password); - network.sendData(message.getBytes()); - network.logOut(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } + // EN: Enter the message. + // + // RU: Вводим сообщение. + System.out.print("Input message: "); + String message = reader.readLine(); + + System.out.println("\nChoose social network for posting message.\n" + + "1 - Facebook\n" + + "2 - Twitter"); + int choice = Integer.parseInt(reader.readLine()); - private static Network getNetwork(BufferedReader reader, String userName, String password) throws IOException { - System.out.println(""" - Choose social network for posting a message. - 1 - Facebook - 2 - Twitter - """); - int choice = Integer.parseInt(reader.readLine()); - return switch (choice) { - case 1 -> new Facebook(userName, password); - case 2 -> new Twitter(userName, password); - default -> { - System.out.println("Invalid choice. Please run the program again."); - yield null; - } - }; - } + // EN: Create proper network object and send the message. + // + // RU: Создаем сетевые объекты и публикуем пост. + if (choice == 1) { + network = new Facebook(userName, password); + } else if (choice == 2) { + network = new Twitter(userName, password); + } + network.post(message); + } } diff --git a/src/refactoring_guru/template_method/example/networks/Facebook.java b/src/refactoring_guru/template_method/example/networks/Facebook.java index d7baee0..740b59e 100644 --- a/src/refactoring_guru/template_method/example/networks/Facebook.java +++ b/src/refactoring_guru/template_method/example/networks/Facebook.java @@ -2,37 +2,52 @@ /** * EN: Class of social network - *

+ * * RU: Класс социальной сети. */ public class Facebook extends Network { - public Facebook(String userName, String password) { - super(userName, password); - } + public Facebook(String userName, String password) { + this.userName = userName; + this.password = password; + } - @Override - public void logIn(String userName, String password) { - simulateNetworkLatency(); - System.out.println("\n\nLogIn success on Facebook"); - } + public boolean logIn(String userName, String password) { + System.out.println("\nChecking user's parameters"); + System.out.println("Name: " + this.userName); + System.out.print("Password: "); + for (int i = 0; i < this.password.length(); i++) { + System.out.print("*"); + } + simulateNetworkLatency(); + System.out.println("\n\nLogIn success on Facebook"); + return true; + } - @Override - public void sendData(byte[] data) { - System.out.println("Message: '" + new String(data) + "' was posted on Facebook"); - } + public boolean sendData(byte[] data) { + boolean messagePosted = true; + if (messagePosted) { + System.out.println("Message: '" + new String(data) + "' was posted on Facebook"); + return true; + } else { + return false; + } + } - @Override - public void logOut() { - System.out.println("User: '" + getUserName() + "' was logged out from Facebook"); - } + public void logOut() { + System.out.println("User: '" + userName + "' was logged out from Facebook"); + } - protected void simulateNetworkLatency() { - try { - System.out.println("Simulating network latency..."); - Thread.sleep(5000); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - throw new RuntimeException(ex); + private void simulateNetworkLatency() { + try { + int i = 0; + System.out.println(); + while (i < 10) { + System.out.print("."); + Thread.sleep(500); + i++; + } + } catch (InterruptedException ex) { + ex.printStackTrace(); + } } - } } diff --git a/src/refactoring_guru/template_method/example/networks/Network.java b/src/refactoring_guru/template_method/example/networks/Network.java index e5fb145..1d85461 100644 --- a/src/refactoring_guru/template_method/example/networks/Network.java +++ b/src/refactoring_guru/template_method/example/networks/Network.java @@ -2,31 +2,38 @@ /** * EN: Base class of social network. - *

+ * * RU: Базовый класс социальной сети. */ public abstract class Network { - public final String userName; - public final String password; - - protected Network(String userName, String password) { - this.userName = userName; - this.password = password; - } - - public String getUserName() { - return userName; - } - - public String getPassword() { - return password; - } - - public abstract void logIn(String userName, String password); - - public abstract void sendData(byte[] data); - - public abstract void logOut(); - - protected abstract void simulateNetworkLatency(); + String userName; + String password; + + Network() {} + + /** + * EN: Publish the data to whatever network. + * + * RU: Публикация данных в любой сети. + */ + public boolean post(String message) { + // EN: Authenticate before posting. Every network uses a different + // authentication method. + // + // RU: Проверка данных пользователя перед постом в соцсеть. Каждая сеть + // для проверки использует разные методы. + if (logIn(this.userName, this.password)) { + // EN: Send the post data. + // + // RU: Отправка данных. + boolean result = sendData(message.getBytes()); + logOut(); + return result; + } + return false; + } + + abstract boolean logIn(String userName, String password); + abstract boolean sendData(byte[] data); + abstract void logOut(); } \ No newline at end of file diff --git a/src/refactoring_guru/template_method/example/networks/Twitter.java b/src/refactoring_guru/template_method/example/networks/Twitter.java index 340cad0..d5eae2a 100644 --- a/src/refactoring_guru/template_method/example/networks/Twitter.java +++ b/src/refactoring_guru/template_method/example/networks/Twitter.java @@ -2,39 +2,53 @@ /** * EN: Class of social network - *

+ * * RU: Класс социальной сети. */ public class Twitter extends Network { - public Twitter(String userName, String password) { - super(userName, password); - } + public Twitter(String userName, String password) { + this.userName = userName; + this.password = password; + } - @Override - public void logIn(String userName, String password) { - simulateNetworkLatency(); - System.out.println("\n\nLogIn success on Twitter"); - } + public boolean logIn(String userName, String password) { + System.out.println("\nChecking user's parameters"); + System.out.println("Name: " + this.userName); + System.out.print("Password: "); + for (int i = 0; i < this.password.length(); i++) { + System.out.print("*"); + } + simulateNetworkLatency(); + System.out.println("\n\nLogIn success on Twitter"); + return true; + } - @Override - public void sendData(byte[] data) { - System.out.println("Message: '" + new String(data) + "' it was posted on Twitter"); - } + public boolean sendData(byte[] data) { + boolean messagePosted = true; + if (messagePosted) { + System.out.println("Message: '" + new String(data) + "' was posted on Twitter"); + return true; + } else { + return false; + } + } - @Override - public void logOut() { - System.out.println("User: '" + getUserName() + "' was logged out from Twitter"); - } + public void logOut() { + System.out.println("User: '" + userName + "' was logged out from Twitter"); + } - @Override - protected void simulateNetworkLatency() { - try { - System.out.println("Simulating network latency..."); - Thread.sleep(5000); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - throw new RuntimeException(ex); + private void simulateNetworkLatency() { + try { + int i = 0; + System.out.println(); + while (i < 10) { + System.out.print("."); + Thread.sleep(500); + i++; + } + } catch (InterruptedException ex) { + ex.printStackTrace(); + } } - } } diff --git a/src/refactoring_guru/visitor/example/Demo.java b/src/refactoring_guru/visitor/example/Demo.java index 71c659c..7effa76 100644 --- a/src/refactoring_guru/visitor/example/Demo.java +++ b/src/refactoring_guru/visitor/example/Demo.java @@ -4,25 +4,25 @@ import refactoring_guru.visitor.example.visitor.XMLExportVisitor; public class Demo { - public static void main(String[] args) { - Dot dot = new Dot(1, 10, 55); - Circle circle = new Circle(2, 23, 15, 10); - Rectangle rectangle = new Rectangle(3, 10, 17, 20, 30); + public static void main(String[] args) { + Dot dot = new Dot(1, 10, 55); + Circle circle = new Circle(2, 23, 15, 10); + Rectangle rectangle = new Rectangle(3, 10, 17, 20, 30); - CompoundShape compoundShape = new CompoundShape(4); - compoundShape.add(dot); - compoundShape.add(circle); - compoundShape.add(rectangle); + CompoundShape compoundShape = new CompoundShape(4); + compoundShape.add(dot); + compoundShape.add(circle); + compoundShape.add(rectangle); - CompoundShape c = new CompoundShape(5); - c.add(dot); - compoundShape.add(c); + CompoundShape c = new CompoundShape(5); + c.add(dot); + compoundShape.add(c); - export(circle, compoundShape); - } + export(circle, compoundShape); + } - private static void export(Shape... shapes) { - XMLExportVisitor exportVisitor = new XMLExportVisitor(); - System.out.println(exportVisitor.export(shapes)); - } + private static void export(Shape... shapes) { + XMLExportVisitor exportVisitor = new XMLExportVisitor(); + System.out.println(exportVisitor.export(shapes)); + } } diff --git a/src/refactoring_guru/visitor/example/shapes/Circle.java b/src/refactoring_guru/visitor/example/shapes/Circle.java index 28ca385..908a388 100644 --- a/src/refactoring_guru/visitor/example/shapes/Circle.java +++ b/src/refactoring_guru/visitor/example/shapes/Circle.java @@ -3,19 +3,19 @@ import refactoring_guru.visitor.example.visitor.Visitor; public class Circle extends Dot { - private final int radius; + private int radius; - public Circle(int id, int x, int y, int radius) { - super(id, x, y); - this.radius = radius; - } + public Circle(int id, int x, int y, int radius) { + super(id, x, y); + this.radius = radius; + } - @Override - public String accept(Visitor visitor) { - return visitor.visitCircle(this); - } + @Override + public String accept(Visitor visitor) { + return visitor.visitCircle(this); + } - public int getRadius() { - return radius; - } + public int getRadius() { + return radius; + } } diff --git a/src/refactoring_guru/visitor/example/shapes/CompoundShape.java b/src/refactoring_guru/visitor/example/shapes/CompoundShape.java index 097f42f..bd8b32b 100644 --- a/src/refactoring_guru/visitor/example/shapes/CompoundShape.java +++ b/src/refactoring_guru/visitor/example/shapes/CompoundShape.java @@ -6,33 +6,33 @@ import java.util.List; public class CompoundShape implements Shape { - public int id; - public List children = new ArrayList<>(); - - public CompoundShape(int id) { - this.id = id; - } - - @Override - public void move(int x, int y) { - // move shape - } - - @Override - public void draw() { - // draw shape - } - - public int getId() { - return id; - } - - @Override - public String accept(Visitor visitor) { - return visitor.visitCompoundGraphic(this); - } - - public void add(Shape shape) { - children.add(shape); - } + public int id; + public List children = new ArrayList<>(); + + public CompoundShape(int id) { + this.id = id; + } + + @Override + public void move(int x, int y) { + // move shape + } + + @Override + public void draw() { + // draw shape + } + + public int getId() { + return id; + } + + @Override + public String accept(Visitor visitor) { + return visitor.visitCompoundGraphic(this); + } + + public void add(Shape shape) { + children.add(shape); + } } diff --git a/src/refactoring_guru/visitor/example/shapes/Dot.java b/src/refactoring_guru/visitor/example/shapes/Dot.java index a4bffc7..5e37a85 100644 --- a/src/refactoring_guru/visitor/example/shapes/Dot.java +++ b/src/refactoring_guru/visitor/example/shapes/Dot.java @@ -3,43 +3,43 @@ import refactoring_guru.visitor.example.visitor.Visitor; public class Dot implements Shape { - private int id; - private int x; - private int y; - - public Dot() { - } - - public Dot(int id, int x, int y) { - this.id = id; - this.x = x; - this.y = y; - } - - @Override - public void move(int x, int y) { - // move shape - } - - @Override - public void draw() { - // draw shape - } - - @Override - public String accept(Visitor visitor) { - return visitor.visitDot(this); - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } - - public int getId() { - return id; - } + private int id; + private int x; + private int y; + + public Dot() { + } + + public Dot(int id, int x, int y) { + this.id = id; + this.x = x; + this.y = y; + } + + @Override + public void move(int x, int y) { + // move shape + } + + @Override + public void draw() { + // draw shape + } + + @Override + public String accept(Visitor visitor) { + return visitor.visitDot(this); + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getId() { + return id; + } } diff --git a/src/refactoring_guru/visitor/example/shapes/Rectangle.java b/src/refactoring_guru/visitor/example/shapes/Rectangle.java index ce987d6..d439065 100644 --- a/src/refactoring_guru/visitor/example/shapes/Rectangle.java +++ b/src/refactoring_guru/visitor/example/shapes/Rectangle.java @@ -2,20 +2,53 @@ import refactoring_guru.visitor.example.visitor.Visitor; -public record Rectangle(int id, int x, int y, int width, int height) implements Shape { - - @Override - public String accept(Visitor visitor) { - return visitor.visitRectangle(this); - } - - @Override - public void move(int x, int y) { - // move shape - } - - @Override - public void draw() { - // draw shape - } +public class Rectangle implements Shape { + private int id; + private int x; + private int y; + private int width; + private int height; + + public Rectangle(int id, int x, int y, int width, int height) { + this.id = id; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + @Override + public String accept(Visitor visitor) { + return visitor.visitRectangle(this); + } + + @Override + public void move(int x, int y) { + // move shape + } + + @Override + public void draw() { + // draw shape + } + + public int getId() { + return id; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } } diff --git a/src/refactoring_guru/visitor/example/shapes/Shape.java b/src/refactoring_guru/visitor/example/shapes/Shape.java index 4c4a633..e190136 100644 --- a/src/refactoring_guru/visitor/example/shapes/Shape.java +++ b/src/refactoring_guru/visitor/example/shapes/Shape.java @@ -3,9 +3,7 @@ import refactoring_guru.visitor.example.visitor.Visitor; public interface Shape { - void move(int x, int y); - - void draw(); - - String accept(Visitor visitor); + void move(int x, int y); + void draw(); + String accept(Visitor visitor); } diff --git a/src/refactoring_guru/visitor/example/visitor/Visitor.java b/src/refactoring_guru/visitor/example/visitor/Visitor.java index e0d8683..60d0ecf 100644 --- a/src/refactoring_guru/visitor/example/visitor/Visitor.java +++ b/src/refactoring_guru/visitor/example/visitor/Visitor.java @@ -6,11 +6,11 @@ import refactoring_guru.visitor.example.shapes.Rectangle; public interface Visitor { - String visitDot(Dot dot); + String visitDot(Dot dot); - String visitCircle(Circle circle); + String visitCircle(Circle circle); - String visitRectangle(Rectangle rectangle); + String visitRectangle(Rectangle rectangle); - String visitCompoundGraphic(CompoundShape cg); + String visitCompoundGraphic(CompoundShape cg); } diff --git a/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java b/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java index 531b133..a1e41e8 100644 --- a/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java +++ b/src/refactoring_guru/visitor/example/visitor/XMLExportVisitor.java @@ -4,57 +4,58 @@ public class XMLExportVisitor implements Visitor { - public String export(Shape... args) { - StringBuilder sb = new StringBuilder(); - sb.append("" + "\n"); - for (Shape shape : args) { - sb.append(shape.accept(this)).append("\n"); + public String export(Shape... args) { + StringBuilder sb = new StringBuilder(); + sb.append("" + "\n"); + for (Shape shape : args) { + sb.append(shape.accept(this)).append("\n"); + } + return sb.toString(); } - return sb.toString(); - } - - public String visitDot(Dot d) { - return "" + "\n" + - " " + d.getId() + "" + "\n" + - " " + d.getX() + "" + "\n" + - " " + d.getY() + "" + "\n" + - ""; - } - - public String visitCircle(Circle c) { - return "" + "\n" + - " " + c.getId() + "" + "\n" + - " " + c.getX() + "" + "\n" + - " " + c.getY() + "" + "\n" + - " " + c.getRadius() + "" + "\n" + - ""; - } - - public String visitRectangle(Rectangle r) { - return "" + "\n" + - " " + r.id() + "" + "\n" + - " " + r.x() + "" + "\n" + - " " + r.y() + "" + "\n" + - " " + r.width() + "" + "\n" + - " " + r.height() + "" + "\n" + - ""; - } - - public String visitCompoundGraphic(CompoundShape cg) { - return "" + "\n" + - " " + cg.getId() + "" + "\n" + - _visitCompoundGraphic(cg) + - ""; - } - - private String _visitCompoundGraphic(CompoundShape cg) { - StringBuilder sb = new StringBuilder(); - for (Shape shape : cg.children) { - String obj = shape.accept(this); - // Proper indentation for sub-objects. - obj = " " + obj.replace("\n", "\n ") + "\n"; - sb.append(obj); + + public String visitDot(Dot d) { + return "" + "\n" + + " " + d.getId() + "" + "\n" + + " " + d.getX() + "" + "\n" + + " " + d.getY() + "" + "\n" + + ""; + } + + public String visitCircle(Circle c) { + return "" + "\n" + + " " + c.getId() + "" + "\n" + + " " + c.getX() + "" + "\n" + + " " + c.getY() + "" + "\n" + + " " + c.getRadius() + "" + "\n" + + ""; + } + + public String visitRectangle(Rectangle r) { + return "" + "\n" + + " " + r.getId() + "" + "\n" + + " " + r.getX() + "" + "\n" + + " " + r.getY() + "" + "\n" + + " " + r.getWidth() + "" + "\n" + + " " + r.getHeight() + "" + "\n" + + ""; } - return sb.toString(); - } + + public String visitCompoundGraphic(CompoundShape cg) { + return "" + "\n" + + " " + cg.getId() + "" + "\n" + + _visitCompoundGraphic(cg) + + ""; + } + + private String _visitCompoundGraphic(CompoundShape cg) { + StringBuilder sb = new StringBuilder(); + for (Shape shape : cg.children) { + String obj = shape.accept(this); + // Proper indentation for sub-objects. + obj = " " + obj.replace("\n", "\n ") + "\n"; + sb.append(obj); + } + return sb.toString(); + } + } From 069f952b96c1842fd40f8ce6808f399a02e8d557 Mon Sep 17 00:00:00 2001 From: Alexander Shvets Date: Wed, 29 May 2024 17:32:00 +0200 Subject: [PATCH 43/45] Updates in content. --- .../decorator/example/decorators/DataSourceDecorator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java b/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java index f126d93..c0ce837 100644 --- a/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java +++ b/src/refactoring_guru/decorator/example/decorators/DataSourceDecorator.java @@ -1,6 +1,6 @@ package refactoring_guru.decorator.example.decorators; -public class DataSourceDecorator implements DataSource { +public abstract class DataSourceDecorator implements DataSource { private DataSource wrappee; DataSourceDecorator(DataSource source) { From c775bcc140f3d0d28b06590af90a0ebceff76368 Mon Sep 17 00:00:00 2001 From: Zakaria Shahen <35308232+zakaria-shahen@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:55:07 +0200 Subject: [PATCH 44/45] applying miss @Override for paint() method --- src/refactoring_guru/composite/example/shapes/Circle.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/refactoring_guru/composite/example/shapes/Circle.java b/src/refactoring_guru/composite/example/shapes/Circle.java index 98fd6db..91dc168 100644 --- a/src/refactoring_guru/composite/example/shapes/Circle.java +++ b/src/refactoring_guru/composite/example/shapes/Circle.java @@ -19,7 +19,8 @@ public int getWidth() { public int getHeight() { return radius * 2; } - + + @Override public void paint(Graphics graphics) { super.paint(graphics); graphics.drawOval(x, y, getWidth() - 1, getHeight() - 1); From 3737cd49c450031158c27f2eb431f9ec57487d19 Mon Sep 17 00:00:00 2001 From: Izzat Karimov <108251704+izzatkarimov@users.noreply.github.com> Date: Sun, 9 Mar 2025 21:32:15 +0100 Subject: [PATCH 45/45] Improve README Clarity and Formatting Hey, I made a few changes to make the README clearer and more concise in certain parts --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 25603de..05045aa 100644 --- a/README.md +++ b/README.md @@ -22,13 +22,13 @@ After importing the project, you will be able to run examples by right-clicking ## Roadmap -- [ ] Add detailed comments all classes. +- [ ] Add detailed comments to all classes. - [ ] Add structure-only examples. ## Contributor's Guide -We appreciate any help, whether it's a simple fix of a typo or a whole new example. Just [make a fork](https://help.github.com/articles/fork-a-repo/), do your change and submit a [pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/). +We appreciate any help, whether it's a simple fix of a typo or a whole new example. Just [make a fork](https://help.github.com/articles/fork-a-repo/), make your changes, and submit a [pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/). Here's a style guide which might help you to keep your changes consistent with our code: @@ -79,7 +79,7 @@ Here's a style guide which might help you to keep your changes consistent with o */ ``` - Don't be scared and ignore the non-English part of such comments. If you want to change something in a comment like this, then do it. Even if you do it wrong, we'll tell you how to fix it during the Pull Request. + Don't be scared and ignore the non-English part of such comments. If you want to change a comment like this, then feel free to do so. Even if you do it wrong, we'll tell you how to fix it during the Pull Request. ## License