diff --git a/chapter1/jongwoon/strategy/src/adventureGame/GameSimulator.java b/chapter1/jongwoon/strategy/src/adventureGame/GameSimulator.java
new file mode 100644
index 0000000..8bd3e10
--- /dev/null
+++ b/chapter1/jongwoon/strategy/src/adventureGame/GameSimulator.java
@@ -0,0 +1,18 @@
+package adventureGame;
+
+import adventureGame.domain.character.Character;
+import adventureGame.domain.character.King;
+import adventureGame.domain.character.Queen;
+import adventureGame.domain.weapon.BowAndArrowBehavior;
+
+public class GameSimulator {
+ public static void main(String[] args) {
+ Character king = new King();
+ Character queen = new Queen();
+ king.fight(queen);
+
+ king.changeWeapon(new BowAndArrowBehavior());
+ king.fight(queen);
+ queen.fight(king);
+ }
+}
diff --git a/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Character.java b/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Character.java
new file mode 100644
index 0000000..36202f1
--- /dev/null
+++ b/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Character.java
@@ -0,0 +1,23 @@
+package adventureGame.domain.character;
+
+import adventureGame.domain.weapon.WeaponBehavior;
+
+public abstract class Character {
+ String name;
+ WeaponBehavior weapon;
+
+ public void fight(Character character) {
+ System.out.println(name + "이 무기를 사용하여 공격하였습니다.");
+ weapon.useWeapon();
+ character.attacked();
+ }
+
+ public void changeWeapon(WeaponBehavior weapon) {
+ System.out.println(name + "이 무기를 교체하였습니다.");
+ this.weapon = weapon;
+ }
+
+ private void attacked() {
+ System.out.println(name + "이 피해를 입었습니다.");
+ }
+}
diff --git a/chapter1/jongwoon/strategy/src/adventureGame/domain/character/King.java b/chapter1/jongwoon/strategy/src/adventureGame/domain/character/King.java
new file mode 100644
index 0000000..597ceb3
--- /dev/null
+++ b/chapter1/jongwoon/strategy/src/adventureGame/domain/character/King.java
@@ -0,0 +1,11 @@
+package adventureGame.domain.character;
+
+import adventureGame.domain.weapon.SwordBehavior;
+
+public class King extends Character {
+
+ public King() {
+ name = "king";
+ weapon = new SwordBehavior();
+ }
+}
diff --git a/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Knight.java b/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Knight.java
new file mode 100644
index 0000000..96f6a9d
--- /dev/null
+++ b/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Knight.java
@@ -0,0 +1,10 @@
+package adventureGame.domain.character;
+
+import adventureGame.domain.weapon.BowAndArrowBehavior;
+
+public class Knight extends Character {
+ public Knight() {
+ name = "knight";
+ weapon = new BowAndArrowBehavior();
+ }
+}
diff --git a/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Queen.java b/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Queen.java
new file mode 100644
index 0000000..7da0e4a
--- /dev/null
+++ b/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Queen.java
@@ -0,0 +1,11 @@
+package adventureGame.domain.character;
+
+import adventureGame.domain.weapon.KnifeBehavior;
+
+public class Queen extends Character {
+
+ public Queen() {
+ name = "queen";
+ weapon = new KnifeBehavior();
+ }
+}
diff --git a/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Troll.java b/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Troll.java
new file mode 100644
index 0000000..4f7f8d0
--- /dev/null
+++ b/chapter1/jongwoon/strategy/src/adventureGame/domain/character/Troll.java
@@ -0,0 +1,11 @@
+package adventureGame.domain.character;
+
+import adventureGame.domain.weapon.AxeBehavior;
+
+public class Troll extends Character {
+
+ public Troll() {
+ name = "troll";
+ weapon = new AxeBehavior();
+ }
+}
diff --git a/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/AxeBehavior.java b/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/AxeBehavior.java
new file mode 100644
index 0000000..92d90b3
--- /dev/null
+++ b/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/AxeBehavior.java
@@ -0,0 +1,8 @@
+package adventureGame.domain.weapon;
+
+public class AxeBehavior implements WeaponBehavior {
+ @Override
+ public void useWeapon() {
+ System.out.println("도끼로 내려찍기!");
+ }
+}
diff --git a/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/BowAndArrowBehavior.java b/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/BowAndArrowBehavior.java
new file mode 100644
index 0000000..966659c
--- /dev/null
+++ b/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/BowAndArrowBehavior.java
@@ -0,0 +1,8 @@
+package adventureGame.domain.weapon;
+
+public class BowAndArrowBehavior implements WeaponBehavior {
+ @Override
+ public void useWeapon() {
+ System.out.println("활 쏘기!");
+ }
+}
diff --git a/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/KnifeBehavior.java b/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/KnifeBehavior.java
new file mode 100644
index 0000000..67acd2e
--- /dev/null
+++ b/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/KnifeBehavior.java
@@ -0,0 +1,8 @@
+package adventureGame.domain.weapon;
+
+public class KnifeBehavior implements WeaponBehavior {
+ @Override
+ public void useWeapon() {
+ System.out.println("칼로 찌르기!");
+ }
+}
diff --git a/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/SwordBehavior.java b/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/SwordBehavior.java
new file mode 100644
index 0000000..5614207
--- /dev/null
+++ b/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/SwordBehavior.java
@@ -0,0 +1,8 @@
+package adventureGame.domain.weapon;
+
+public class SwordBehavior implements WeaponBehavior {
+ @Override
+ public void useWeapon() {
+ System.out.println("칼로 베기!");
+ }
+}
diff --git a/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/WeaponBehavior.java b/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/WeaponBehavior.java
new file mode 100644
index 0000000..dd839ef
--- /dev/null
+++ b/chapter1/jongwoon/strategy/src/adventureGame/domain/weapon/WeaponBehavior.java
@@ -0,0 +1,5 @@
+package adventureGame.domain.weapon;
+
+public interface WeaponBehavior {
+ void useWeapon();
+}
diff --git a/chapter1/jongwoon/strategy/strategy.iml b/chapter1/jongwoon/strategy/strategy.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/chapter1/jongwoon/strategy/strategy.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter2/chapter2.iml b/chapter2/chapter2.iml
new file mode 100644
index 0000000..cec3b1a
--- /dev/null
+++ b/chapter2/chapter2.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter2/jongwoon/src/main/java/Main.java b/chapter2/jongwoon/src/main/java/Main.java
new file mode 100644
index 0000000..137758a
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/Main.java
@@ -0,0 +1,16 @@
+import observer.Observer;
+import observer.ObserverConcrete;
+import subject.Subject;
+import subject.SubjectConcrete;
+
+public class Main {
+ public static void main(String[] args) {
+ Subject subject = new SubjectConcrete();
+ Observer observer1 = new ObserverConcrete("관찰자 1");
+ Observer observer2 = new ObserverConcrete("관찰자 2");
+ subject.addObserver(observer1);
+ subject.addObserver(observer2);
+
+ subject.notifyObservers();
+ }
+}
\ No newline at end of file
diff --git a/chapter2/jongwoon/src/main/java/observer/Observer.java b/chapter2/jongwoon/src/main/java/observer/Observer.java
new file mode 100644
index 0000000..cb19107
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/observer/Observer.java
@@ -0,0 +1,5 @@
+package observer;
+
+public interface Observer {
+ void update();
+}
diff --git a/chapter2/jongwoon/src/main/java/observer/ObserverConcrete.java b/chapter2/jongwoon/src/main/java/observer/ObserverConcrete.java
new file mode 100644
index 0000000..4d075eb
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/observer/ObserverConcrete.java
@@ -0,0 +1,15 @@
+package observer;
+
+public class ObserverConcrete implements Observer {
+
+ String name;
+
+ public ObserverConcrete(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void update() {
+ System.out.println(name + "에게 발송 되었습니다.");
+ }
+}
diff --git a/chapter2/jongwoon/src/main/java/stock/StockApp.java b/chapter2/jongwoon/src/main/java/stock/StockApp.java
new file mode 100644
index 0000000..79b5858
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/stock/StockApp.java
@@ -0,0 +1,25 @@
+package stock;
+
+import stock.observer.Customer;
+import stock.observer.StockCustomer;
+import stock.stocks.repository.StocksRepository;
+import stock.subject.Brokerage;
+import stock.subject.SamsungBrokerage;
+
+public class StockApp {
+ public static void main(String[] args) {
+ Brokerage brokerage = new SamsungBrokerage();
+ StockCustomer customer1 = new Customer("김봉팔");
+ StockCustomer customer2 = new Customer("김사지");
+ customer1.addStocks(StocksRepository.STOCKS_MAP.get("Kakao"));
+ customer1.addStocks(StocksRepository.STOCKS_MAP.get("Samsung"));
+
+ customer2.addStocks(StocksRepository.STOCKS_MAP.get("Kakao"));
+ customer2.addStocks(StocksRepository.STOCKS_MAP.get("Samsung"));
+ customer2.addStocks(StocksRepository.STOCKS_MAP.get("Tesla"));
+
+ brokerage.addCustomer(customer1);
+ brokerage.addCustomer(customer2);
+ brokerage.notifyToCustomer();
+ }
+}
diff --git a/chapter2/jongwoon/src/main/java/stock/observer/Customer.java b/chapter2/jongwoon/src/main/java/stock/observer/Customer.java
new file mode 100644
index 0000000..57b8ba3
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/stock/observer/Customer.java
@@ -0,0 +1,18 @@
+package stock.observer;
+
+import stock.stocks.Stocks;
+
+public class Customer extends StockCustomer {
+
+ public Customer(String customerName) {
+ super(customerName);
+ }
+
+ @Override
+ public void update() {
+ System.out.println(customerName + "의 포트폴리오");
+ for (Stocks stock : stockList) {
+ System.out.println(stock);
+ }
+ }
+}
diff --git a/chapter2/jongwoon/src/main/java/stock/observer/StockCustomer.java b/chapter2/jongwoon/src/main/java/stock/observer/StockCustomer.java
new file mode 100644
index 0000000..2c9d41b
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/stock/observer/StockCustomer.java
@@ -0,0 +1,21 @@
+package stock.observer;
+
+import stock.stocks.Stocks;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class StockCustomer {
+ String customerName;
+ List stockList = new ArrayList<>();
+
+ public StockCustomer(String customerName) {
+ this.customerName = customerName;
+ }
+
+ public abstract void update();
+
+ public void addStocks(Stocks stocks) {
+ stockList.add(stocks);
+ }
+}
diff --git a/chapter2/jongwoon/src/main/java/stock/stocks/Kakao.java b/chapter2/jongwoon/src/main/java/stock/stocks/Kakao.java
new file mode 100644
index 0000000..c7e0c37
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/stock/stocks/Kakao.java
@@ -0,0 +1,10 @@
+package stock.stocks;
+
+import java.math.BigDecimal;
+
+public class Kakao extends Stocks {
+ public Kakao(BigDecimal stockPrice) {
+ super(stockPrice);
+ stockName = "카카오 주식";
+ }
+}
diff --git a/chapter2/jongwoon/src/main/java/stock/stocks/Samsung.java b/chapter2/jongwoon/src/main/java/stock/stocks/Samsung.java
new file mode 100644
index 0000000..dddb3f7
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/stock/stocks/Samsung.java
@@ -0,0 +1,10 @@
+package stock.stocks;
+
+import java.math.BigDecimal;
+
+public class Samsung extends Stocks {
+ public Samsung(BigDecimal stockPrice) {
+ super(stockPrice);
+ stockName = "삼성 주식";
+ }
+}
diff --git a/chapter2/jongwoon/src/main/java/stock/stocks/Stocks.java b/chapter2/jongwoon/src/main/java/stock/stocks/Stocks.java
new file mode 100644
index 0000000..ab2631a
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/stock/stocks/Stocks.java
@@ -0,0 +1,36 @@
+package stock.stocks;
+
+import java.math.BigDecimal;
+import java.util.Random;
+
+public abstract class Stocks {
+ protected String stockName;
+ protected BigDecimal stockPrice;
+
+ public Stocks(BigDecimal stockPrice) {
+ this.stockPrice = stockPrice;
+ }
+
+ public void changeStockPrice() {
+ int randomMenu = new Random().nextInt(2) + 1;
+ int dollar = new Random().nextInt(2);
+ switch (randomMenu) {
+ case 1:
+ BigDecimal addMoney = BigDecimal.valueOf(new Random().nextDouble() + dollar);
+ stockPrice = stockPrice.add(addMoney);
+ break;
+ case 2:
+ BigDecimal subtractMoney = BigDecimal.valueOf(new Random().nextDouble() + dollar);
+ stockPrice = stockPrice.subtract(subtractMoney);
+ break;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Stocks{" +
+ "stockName='" + stockName + '\'' +
+ ", stockPrice=" + Math.round(stockPrice.doubleValue() * 100) / 100.0 +
+ '}';
+ }
+}
diff --git a/chapter2/jongwoon/src/main/java/stock/stocks/Tesla.java b/chapter2/jongwoon/src/main/java/stock/stocks/Tesla.java
new file mode 100644
index 0000000..efd6559
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/stock/stocks/Tesla.java
@@ -0,0 +1,10 @@
+package stock.stocks;
+
+import java.math.BigDecimal;
+
+public class Tesla extends Stocks {
+ public Tesla(BigDecimal stockPrice) {
+ super(stockPrice);
+ stockName = "테슬라 주식";
+ }
+}
diff --git a/chapter2/jongwoon/src/main/java/stock/stocks/repository/StocksRepository.java b/chapter2/jongwoon/src/main/java/stock/stocks/repository/StocksRepository.java
new file mode 100644
index 0000000..06fe0af
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/stock/stocks/repository/StocksRepository.java
@@ -0,0 +1,24 @@
+package stock.stocks.repository;
+
+import stock.stocks.Kakao;
+import stock.stocks.Samsung;
+import stock.stocks.Stocks;
+import stock.stocks.Tesla;
+
+import java.math.BigDecimal;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class StocksRepository {
+ public static final Map STOCKS_MAP = new LinkedHashMap<>();
+
+ static {
+ STOCKS_MAP.put("Kakao", new Kakao(new BigDecimal("43.8")));
+ STOCKS_MAP.put("Samsung", new Samsung(new BigDecimal("55.91")));
+ STOCKS_MAP.put("Tesla", new Tesla(new BigDecimal("244.4")));
+
+ STOCKS_MAP.forEach((a, b) -> {
+ System.out.println(a + "의 첫 주가 : " + b);
+ });
+ }
+}
diff --git a/chapter2/jongwoon/src/main/java/stock/subject/Brokerage.java b/chapter2/jongwoon/src/main/java/stock/subject/Brokerage.java
new file mode 100644
index 0000000..2a17e15
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/stock/subject/Brokerage.java
@@ -0,0 +1,11 @@
+package stock.subject;
+
+import stock.observer.StockCustomer;
+
+public interface Brokerage {
+ void addCustomer(StockCustomer customer);
+
+ void removeCustomer(StockCustomer customer);
+
+ void notifyToCustomer();
+}
diff --git a/chapter2/jongwoon/src/main/java/stock/subject/SamsungBrokerage.java b/chapter2/jongwoon/src/main/java/stock/subject/SamsungBrokerage.java
new file mode 100644
index 0000000..18b5609
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/stock/subject/SamsungBrokerage.java
@@ -0,0 +1,42 @@
+package stock.subject;
+
+import stock.observer.StockCustomer;
+import stock.stocks.Stocks;
+import stock.stocks.repository.StocksRepository;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SamsungBrokerage implements Brokerage {
+
+ List stocksList;
+ List customers;
+
+ public SamsungBrokerage() {
+ stocksList = new ArrayList<>();
+ customers = new ArrayList<>();
+ StocksRepository.STOCKS_MAP.forEach((a, b) -> {
+ stocksList.add(b);
+ });
+ }
+
+ @Override
+ public void addCustomer(StockCustomer customer) {
+ customers.add(customer);
+ }
+
+ @Override
+ public void removeCustomer(StockCustomer customer) {
+ customers.remove(customer);
+ }
+
+ @Override
+ public void notifyToCustomer() {
+ for (Stocks stock : stocksList) {
+ stock.changeStockPrice();
+ }
+ for (StockCustomer customer : customers) {
+ customer.update();
+ }
+ }
+}
diff --git a/chapter2/jongwoon/src/main/java/subject/Subject.java b/chapter2/jongwoon/src/main/java/subject/Subject.java
new file mode 100644
index 0000000..57b467a
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/subject/Subject.java
@@ -0,0 +1,10 @@
+package subject;
+
+import observer.Observer;
+
+public interface Subject {
+
+ void addObserver(Observer observer);
+ void removeObserver(Observer observer);
+ void notifyObservers();
+}
diff --git a/chapter2/jongwoon/src/main/java/subject/SubjectConcrete.java b/chapter2/jongwoon/src/main/java/subject/SubjectConcrete.java
new file mode 100644
index 0000000..6222293
--- /dev/null
+++ b/chapter2/jongwoon/src/main/java/subject/SubjectConcrete.java
@@ -0,0 +1,33 @@
+package subject;
+
+import observer.Observer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SubjectConcrete implements Subject {
+
+ List observerList;
+ String msg;
+
+ public SubjectConcrete() {
+ observerList = new ArrayList<>();
+ }
+
+ @Override
+ public void addObserver(Observer observer) {
+ observerList.add(observer);
+ }
+
+ @Override
+ public void removeObserver(Observer observer) {
+ observerList.remove(observer);
+ }
+
+ @Override
+ public void notifyObservers() {
+ for(Observer observer : observerList) {
+ observer.update();
+ }
+ }
+}
diff --git a/chapter3/chapter3.iml b/chapter3/chapter3.iml
new file mode 100644
index 0000000..5abffe5
--- /dev/null
+++ b/chapter3/chapter3.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter3/jongwoon/jongwoon.iml b/chapter3/jongwoon/jongwoon.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/chapter3/jongwoon/jongwoon.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter3/jongwoon/src/Main.java b/chapter3/jongwoon/src/Main.java
new file mode 100644
index 0000000..2999a1d
--- /dev/null
+++ b/chapter3/jongwoon/src/Main.java
@@ -0,0 +1,13 @@
+import decorator.Weapon.*;
+
+public class Main {
+ public static void main(String[] args) {
+ Weapon weapon = new Buttstock(new BaseWeapon());
+ weapon.aimAndFire();
+
+ System.out.println("=============");
+
+ Weapon weapon2 = new Buttstock(new Scoped(new Grenade(new BaseWeapon())));
+ weapon2.aimAndFire();
+ }
+}
\ No newline at end of file
diff --git a/chapter3/jongwoon/src/decorator/Weapon/BaseWeapon.java b/chapter3/jongwoon/src/decorator/Weapon/BaseWeapon.java
new file mode 100644
index 0000000..f6ae82d
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/Weapon/BaseWeapon.java
@@ -0,0 +1,8 @@
+package decorator.Weapon;
+
+public class BaseWeapon implements Weapon {
+ @Override
+ public void aimAndFire() {
+ System.out.println("총알 발사!!");
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/Weapon/Buttstock.java b/chapter3/jongwoon/src/decorator/Weapon/Buttstock.java
new file mode 100644
index 0000000..0e4fc7c
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/Weapon/Buttstock.java
@@ -0,0 +1,18 @@
+package decorator.Weapon;
+
+public class Buttstock extends WeaponAccessory {
+
+ public Buttstock(Weapon weapon) {
+ super(weapon);
+ }
+
+ @Override
+ public void aimAndFire() {
+ holding();
+ super.aimAndFire();
+ }
+
+ public void holding() {
+ System.out.println("견착 중");
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/Weapon/Grenade.java b/chapter3/jongwoon/src/decorator/Weapon/Grenade.java
new file mode 100644
index 0000000..5efcfd8
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/Weapon/Grenade.java
@@ -0,0 +1,18 @@
+package decorator.Weapon;
+
+public class Grenade extends WeaponAccessory {
+
+ public Grenade(Weapon weapon) {
+ super(weapon);
+ }
+
+ @Override
+ public void aimAndFire() {
+ super.aimAndFire();
+ grenade();
+ }
+
+ void grenade() {
+ System.out.println("유탄 발사!!");
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/Weapon/Scoped.java b/chapter3/jongwoon/src/decorator/Weapon/Scoped.java
new file mode 100644
index 0000000..8de06a8
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/Weapon/Scoped.java
@@ -0,0 +1,18 @@
+package decorator.Weapon;
+
+public class Scoped extends WeaponAccessory {
+
+ public Scoped(Weapon weapon) {
+ super(weapon);
+ }
+
+ @Override
+ public void aimAndFire() {
+ scope();
+ super.aimAndFire();
+ }
+
+ void scope() {
+ System.out.println("조준 중");
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/Weapon/Weapon.java b/chapter3/jongwoon/src/decorator/Weapon/Weapon.java
new file mode 100644
index 0000000..f901015
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/Weapon/Weapon.java
@@ -0,0 +1,5 @@
+package decorator.Weapon;
+
+public interface Weapon {
+ void aimAndFire();
+}
diff --git a/chapter3/jongwoon/src/decorator/Weapon/WeaponAccessory.java b/chapter3/jongwoon/src/decorator/Weapon/WeaponAccessory.java
new file mode 100644
index 0000000..4b81326
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/Weapon/WeaponAccessory.java
@@ -0,0 +1,14 @@
+package decorator.Weapon;
+
+public abstract class WeaponAccessory implements Weapon{
+ private Weapon weapon;
+
+ public WeaponAccessory(Weapon weapon) {
+ this.weapon = weapon;
+ }
+
+ @Override
+ public void aimAndFire() {
+ weapon.aimAndFire();
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/Weapon/WeaponGame.java b/chapter3/jongwoon/src/decorator/Weapon/WeaponGame.java
new file mode 100644
index 0000000..13bbfd3
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/Weapon/WeaponGame.java
@@ -0,0 +1,13 @@
+package decorator.Weapon;
+
+public class WeaponGame {
+ public static void main(String[] args) {
+ Weapon weapon = new Buttstock(new BaseWeapon());
+ weapon.aimAndFire();
+
+ System.out.println("=============");
+
+ Weapon weapon2 = new Buttstock(new Scoped(new Grenade(new BaseWeapon())));
+ weapon2.aimAndFire();
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/coffee/Beverage.java b/chapter3/jongwoon/src/decorator/coffee/Beverage.java
new file mode 100644
index 0000000..c11816a
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/coffee/Beverage.java
@@ -0,0 +1,18 @@
+package decorator.coffee;
+
+public abstract class Beverage {
+ protected String name = "";
+ protected Size size;
+
+ public enum Size {TALL, GRANDE, VENTI};
+
+ public String getName() {
+ return name;
+ }
+
+ public Size getSize() {
+ return size;
+ }
+
+ public abstract double cost();
+}
diff --git a/chapter3/jongwoon/src/decorator/coffee/CoffeeStore.java b/chapter3/jongwoon/src/decorator/coffee/CoffeeStore.java
new file mode 100644
index 0000000..6a947b1
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/coffee/CoffeeStore.java
@@ -0,0 +1,9 @@
+package decorator.coffee;
+
+public class CoffeeStore {
+ public static void main(String[] args) {
+ Beverage beverage = new Soybean(new Whip(new Mocha(new DarkRoast(Beverage.Size.VENTI))));
+
+ System.out.println(beverage.getName() + " " + beverage.cost());
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/coffee/CondimentDecorator.java b/chapter3/jongwoon/src/decorator/coffee/CondimentDecorator.java
new file mode 100644
index 0000000..9dca29d
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/coffee/CondimentDecorator.java
@@ -0,0 +1,14 @@
+package decorator.coffee;
+
+public abstract class CondimentDecorator extends Beverage {
+ Beverage beverage;
+
+ public CondimentDecorator(Beverage beverage) {
+ this.beverage = beverage;
+ }
+ public abstract String getName();
+
+ public Size getSize() {
+ return beverage.getSize();
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/coffee/DarkRoast.java b/chapter3/jongwoon/src/decorator/coffee/DarkRoast.java
new file mode 100644
index 0000000..868ae74
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/coffee/DarkRoast.java
@@ -0,0 +1,18 @@
+package decorator.coffee;
+
+public class DarkRoast extends Beverage {
+
+ public DarkRoast() {
+ this(Size.TALL);
+ }
+
+ public DarkRoast(Size size) {
+ this.size = size;
+ name = "다크 로스트 커피";
+ }
+
+ @Override
+ public double cost() {
+ return .99;
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/coffee/Decaf.java b/chapter3/jongwoon/src/decorator/coffee/Decaf.java
new file mode 100644
index 0000000..c1fd7cc
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/coffee/Decaf.java
@@ -0,0 +1,18 @@
+package decorator.coffee;
+
+public class Decaf extends Beverage {
+
+ public Decaf() {
+ this(Size.TALL);
+ }
+
+ public Decaf(Size size) {
+ this.size = size;
+ name = "디카페인 커피";
+ }
+
+ @Override
+ public double cost() {
+ return 1.05;
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/coffee/Espresso.java b/chapter3/jongwoon/src/decorator/coffee/Espresso.java
new file mode 100644
index 0000000..cbe4653
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/coffee/Espresso.java
@@ -0,0 +1,18 @@
+package decorator.coffee;
+
+public class Espresso extends Beverage {
+
+ public Espresso() {
+ this(Size.TALL);
+ }
+
+ public Espresso(Size size) {
+ this.size = size;
+ name = "에스프레소 커피";
+ }
+
+ @Override
+ public double cost() {
+ return 1.99;
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/coffee/HouseBlend.java b/chapter3/jongwoon/src/decorator/coffee/HouseBlend.java
new file mode 100644
index 0000000..2c46d91
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/coffee/HouseBlend.java
@@ -0,0 +1,17 @@
+package decorator.coffee;
+
+public class HouseBlend extends Beverage {
+
+ public HouseBlend() {
+ this(Size.TALL);
+ }
+
+ public HouseBlend(Size size) {
+ this.size = size;
+ name = "하우스 블렌드 커피";
+ }
+
+ public double cost() {
+ return .89;
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/coffee/Mocha.java b/chapter3/jongwoon/src/decorator/coffee/Mocha.java
new file mode 100644
index 0000000..c7aa6e5
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/coffee/Mocha.java
@@ -0,0 +1,30 @@
+package decorator.coffee;
+
+public class Mocha extends CondimentDecorator {
+
+ public Mocha(Beverage beverage) {
+ super(beverage);
+ }
+
+ @Override
+ public String getName() {
+ return beverage.getName() + ", 모카";
+ }
+
+ @Override
+ public double cost() {
+ double cost = beverage.cost();
+
+ switch(beverage.getSize()) {
+ case TALL:
+ cost += 0.10;
+ break;
+ case GRANDE:
+ cost += 0.15;
+ break;
+ case VENTI:
+ cost += 0.20;
+ }
+ return cost;
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/coffee/Soybean.java b/chapter3/jongwoon/src/decorator/coffee/Soybean.java
new file mode 100644
index 0000000..045b16d
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/coffee/Soybean.java
@@ -0,0 +1,30 @@
+package decorator.coffee;
+
+public class Soybean extends CondimentDecorator {
+
+ public Soybean(Beverage beverage) {
+ super(beverage);
+ }
+
+ @Override
+ public String getName() {
+ return beverage.getName() + ", 두유";
+ }
+
+ @Override
+ public double cost() {
+ double cost = beverage.cost();
+
+ switch(beverage.getSize()) {
+ case TALL:
+ cost += 0.05;
+ break;
+ case GRANDE:
+ cost += 0.1;
+ break;
+ case VENTI:
+ cost += 0.15;
+ }
+ return cost;
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/coffee/Whip.java b/chapter3/jongwoon/src/decorator/coffee/Whip.java
new file mode 100644
index 0000000..057360a
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/coffee/Whip.java
@@ -0,0 +1,30 @@
+package decorator.coffee;
+
+public class Whip extends CondimentDecorator {
+
+ public Whip(Beverage beverage) {
+ super(beverage);
+ }
+
+ @Override
+ public String getName() {
+ return beverage.getName() + ", 휘핑크림";
+ }
+
+ @Override
+ public double cost() {
+ double cost = beverage.cost();
+
+ switch(beverage.getSize()) {
+ case TALL:
+ cost += 0.02;
+ break;
+ case GRANDE:
+ cost += 0.04;
+ break;
+ case VENTI:
+ cost += 0.1;
+ }
+ return cost;
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/miniproject/App.java b/chapter3/jongwoon/src/decorator/miniproject/App.java
new file mode 100644
index 0000000..1ec1d5b
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/miniproject/App.java
@@ -0,0 +1,14 @@
+package decorator.miniproject;
+
+public class App {
+ public static void main(String[] args) {
+ User user = new User("문종운", "010-6800-0708", "인천광역시 미추홀구");
+ UserWrapper baseUser = new BaseUserWrapper();
+ UserWrapper userDecorator = new UserValidationDecorator(new UserCryptographyDecorator(baseUser));
+ userDecorator.write(user);
+
+ System.out.println("encrypt 된 데이터 : " + baseUser.read());
+ System.out.println("==============");
+ System.out.println("decrypt 된 데이터 : " + userDecorator.read());
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/miniproject/BaseUserWrapper.java b/chapter3/jongwoon/src/decorator/miniproject/BaseUserWrapper.java
new file mode 100644
index 0000000..47c99d6
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/miniproject/BaseUserWrapper.java
@@ -0,0 +1,16 @@
+package decorator.miniproject;
+
+public class BaseUserWrapper implements UserWrapper{
+ private User user;
+
+ @Override
+ public void write(User user) {
+ System.out.println(user);
+ this.user = user;
+ }
+
+ @Override
+ public User read() {
+ return user;
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/miniproject/User.java b/chapter3/jongwoon/src/decorator/miniproject/User.java
new file mode 100644
index 0000000..29f09fb
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/miniproject/User.java
@@ -0,0 +1,35 @@
+package decorator.miniproject;
+
+
+public class User {
+ private String name;
+ private String phoneNumber;
+ private String address;
+
+ public User(String name, String phoneNumber, String address) {
+ this.name = name;
+ this.phoneNumber = phoneNumber;
+ this.address = address;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPhoneNumber() {
+ return phoneNumber;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ @Override
+ public String toString() {
+ return "User{" +
+ "name='" + name + '\'' +
+ ", phoneNumber='" + phoneNumber + '\'' +
+ ", address='" + address + '\'' +
+ '}';
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/miniproject/UserCryptographyDecorator.java b/chapter3/jongwoon/src/decorator/miniproject/UserCryptographyDecorator.java
new file mode 100644
index 0000000..67ca57c
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/miniproject/UserCryptographyDecorator.java
@@ -0,0 +1,52 @@
+package decorator.miniproject;
+
+public class UserCryptographyDecorator extends UserDecorator {
+
+
+ private final int MOVE_VALUE = 20;
+ public UserCryptographyDecorator(UserWrapper userWrapper) {
+ super(userWrapper);
+ }
+
+ @Override
+ public void write(User user) {
+ super.write(encryptUser(user));
+ }
+
+ private User encryptUser(User user) {
+ String encryptedName = encrypt(user.getName());
+ String encryptedPhoneNumber = encrypt(user.getPhoneNumber());
+ String encryptedAddress = encrypt(user.getAddress());
+ return new User(encryptedName, encryptedPhoneNumber, encryptedAddress);
+ }
+
+ private String encrypt(String value) {
+ StringBuilder sb = new StringBuilder();
+ for(char ch : value.toCharArray()) {
+ sb.append((char)(ch + MOVE_VALUE));
+ }
+ return sb.toString();
+ }
+
+
+ @Override
+ public User read() {
+ User user = super.read();
+ return decryptUser(user);
+ }
+
+ private User decryptUser(User user) {
+ String decryptedName = decrypt(user.getName());
+ String decryptedPhoneNumber = decrypt(user.getPhoneNumber());
+ String decryptedAddress = decrypt(user.getAddress());
+ return new User(decryptedName, decryptedPhoneNumber, decryptedAddress);
+ }
+
+ private String decrypt(String value) {
+ StringBuilder sb = new StringBuilder();
+ for(char ch : value.toCharArray()) {
+ sb.append((char)(ch - MOVE_VALUE));
+ }
+ return sb.toString();
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/miniproject/UserDecorator.java b/chapter3/jongwoon/src/decorator/miniproject/UserDecorator.java
new file mode 100644
index 0000000..574a306
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/miniproject/UserDecorator.java
@@ -0,0 +1,20 @@
+package decorator.miniproject;
+
+public abstract class UserDecorator implements UserWrapper{
+
+ protected UserWrapper wrappedUser;
+
+ public UserDecorator(UserWrapper userWrapper) {
+ this.wrappedUser = userWrapper;
+ }
+
+ @Override
+ public void write(User user) {
+ wrappedUser.write(user);
+ }
+
+ @Override
+ public User read() {
+ return wrappedUser.read();
+ }
+}
diff --git a/chapter3/jongwoon/src/decorator/miniproject/UserValidationDecorator.java b/chapter3/jongwoon/src/decorator/miniproject/UserValidationDecorator.java
new file mode 100644
index 0000000..0ca47ef
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/miniproject/UserValidationDecorator.java
@@ -0,0 +1,35 @@
+package decorator.miniproject;
+
+import java.util.regex.Pattern;
+
+public class UserValidationDecorator extends UserDecorator {
+
+ private static final String KOREAN_REGEX = "^[가-힣]+$";
+ private static final Pattern KOREAN_REGEX_COMPILE = Pattern.compile(KOREAN_REGEX);
+ private static final String PHONE_NUMBER_REGEX = "^\\d{3}-\\d{4}-\\d{4}$";
+ private static final Pattern PHONE_NUMBER_REGEX_COMPILE = Pattern.compile(PHONE_NUMBER_REGEX);
+
+ public UserValidationDecorator(UserWrapper userWrapper) {
+ super(userWrapper);
+ }
+
+ @Override
+ public void write(User user) {
+ if (validate(user)) {
+ wrappedUser.write(user);
+ }
+ }
+
+ private boolean validate(User user) {
+ return isValidKoreanName(user.getName()) && isValidPhoneNumber(user.getPhoneNumber());
+ }
+
+ private boolean isValidKoreanName(String name) {
+ return KOREAN_REGEX_COMPILE.matcher(name).matches();
+ }
+
+ private boolean isValidPhoneNumber(String phoneNumber) {
+ return PHONE_NUMBER_REGEX_COMPILE.matcher(phoneNumber).matches();
+ }
+
+}
diff --git a/chapter3/jongwoon/src/decorator/miniproject/UserWrapper.java b/chapter3/jongwoon/src/decorator/miniproject/UserWrapper.java
new file mode 100644
index 0000000..fc9885c
--- /dev/null
+++ b/chapter3/jongwoon/src/decorator/miniproject/UserWrapper.java
@@ -0,0 +1,7 @@
+package decorator.miniproject;
+
+public interface UserWrapper {
+
+ void write(User user);
+ User read();
+}
diff --git a/chapter4,5/abstractFactory/abstractFactory.iml b/chapter4,5/abstractFactory/abstractFactory.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/chapter4,5/abstractFactory/abstractFactory.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter4,5/abstractFactory/src/Application.java b/chapter4,5/abstractFactory/src/Application.java
new file mode 100644
index 0000000..5685c66
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/Application.java
@@ -0,0 +1,20 @@
+import button.Button;
+import checkBox.CheckBox;
+import factory.GUIFactory;
+
+public class Application {
+ private GUIFactory factory;
+ private Button button;
+ private CheckBox checkBox;
+
+ public Application(GUIFactory factory) {
+ this.factory = factory;
+ this.button = factory.createButton();
+ this.checkBox = factory.createCheckBox();
+ }
+
+ public void createUI() {
+ button.paint();
+ checkBox.paint();
+ }
+}
diff --git a/chapter4,5/abstractFactory/src/ApplicationExecutor.java b/chapter4,5/abstractFactory/src/ApplicationExecutor.java
new file mode 100644
index 0000000..3b162a0
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/ApplicationExecutor.java
@@ -0,0 +1,26 @@
+import factory.GUIFactory;
+import factory.MacFactory;
+import factory.WinFactory;
+
+public class ApplicationExecutor {
+ public static void main(String[] args) {
+ Output.printOs();
+ Operation operation = Operation.findOperation(Input.inputOsName())
+ .orElseThrow(() -> new RuntimeException("안돼요~"));
+
+ GUIFactory factory = null;
+
+ switch (operation) {
+ case MAC:
+ factory = MacFactory.getInstance();
+ break;
+
+ case WINDOW:
+ factory = WinFactory.getInstance();
+ break;
+ }
+
+ Application application = new Application(factory);
+ application.createUI();
+ }
+}
diff --git a/chapter4,5/abstractFactory/src/Input.java b/chapter4,5/abstractFactory/src/Input.java
new file mode 100644
index 0000000..9070925
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/Input.java
@@ -0,0 +1,9 @@
+import java.util.Scanner;
+
+public class Input {
+ private final static Scanner SCANNER = new Scanner(System.in);
+
+ public static String inputOsName() {
+ return SCANNER.nextLine();
+ }
+}
diff --git a/chapter4,5/abstractFactory/src/Operation.java b/chapter4,5/abstractFactory/src/Operation.java
new file mode 100644
index 0000000..8f6029f
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/Operation.java
@@ -0,0 +1,26 @@
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public enum Operation {
+ WINDOW("window"), MAC("mac");
+
+ private final String os;
+ private final static Map OPERATION_MAP = Collections.unmodifiableMap(Arrays.stream(values())
+ .collect(Collectors.toMap(Operation::getOs, Function.identity())));
+
+ Operation(String os) {
+ this.os = os;
+ }
+
+ public String getOs() {
+ return this.os;
+ }
+
+ public static Optional findOperation(String os) {
+ return Optional.ofNullable(OPERATION_MAP.get(os));
+ }
+}
diff --git a/chapter4,5/abstractFactory/src/Output.java b/chapter4,5/abstractFactory/src/Output.java
new file mode 100644
index 0000000..5d08964
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/Output.java
@@ -0,0 +1,10 @@
+public class Output {
+
+ public static void printOs() {
+ System.out.println("===수행 가능한 OS===");
+ for (Operation operation : Operation.values()) {
+ System.out.println(operation.getOs());
+ }
+ System.out.print("입력 : ");
+ }
+}
diff --git a/chapter4,5/abstractFactory/src/button/Button.java b/chapter4,5/abstractFactory/src/button/Button.java
new file mode 100644
index 0000000..79ca518
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/button/Button.java
@@ -0,0 +1,5 @@
+package button;
+
+public interface Button {
+ void paint();
+}
diff --git a/chapter4,5/abstractFactory/src/button/MacButton.java b/chapter4,5/abstractFactory/src/button/MacButton.java
new file mode 100644
index 0000000..b13360a
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/button/MacButton.java
@@ -0,0 +1,8 @@
+package button;
+
+public class MacButton implements Button {
+ @Override
+ public void paint() {
+ System.out.println("맥 버튼 렌더링");
+ }
+}
diff --git a/chapter4,5/abstractFactory/src/button/WinButton.java b/chapter4,5/abstractFactory/src/button/WinButton.java
new file mode 100644
index 0000000..b050d57
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/button/WinButton.java
@@ -0,0 +1,8 @@
+package button;
+
+public class WinButton implements Button {
+ @Override
+ public void paint() {
+ System.out.println("윈도우 버튼 렌더링");
+ }
+}
diff --git a/chapter4,5/abstractFactory/src/checkBox/CheckBox.java b/chapter4,5/abstractFactory/src/checkBox/CheckBox.java
new file mode 100644
index 0000000..97c5677
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/checkBox/CheckBox.java
@@ -0,0 +1,5 @@
+package checkBox;
+
+public interface CheckBox {
+ void paint();
+}
diff --git a/chapter4,5/abstractFactory/src/checkBox/MacCheckBox.java b/chapter4,5/abstractFactory/src/checkBox/MacCheckBox.java
new file mode 100644
index 0000000..f3e0b37
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/checkBox/MacCheckBox.java
@@ -0,0 +1,8 @@
+package checkBox;
+
+public class MacCheckBox implements CheckBox {
+ @Override
+ public void paint() {
+ System.out.println("맥 체크박스 렌더링");
+ }
+}
diff --git a/chapter4,5/abstractFactory/src/checkBox/WinCheckBox.java b/chapter4,5/abstractFactory/src/checkBox/WinCheckBox.java
new file mode 100644
index 0000000..035b92e
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/checkBox/WinCheckBox.java
@@ -0,0 +1,8 @@
+package checkBox;
+
+public class WinCheckBox implements CheckBox {
+ @Override
+ public void paint() {
+ System.out.println("윈도우 체크박스 렌더링");
+ }
+}
diff --git a/chapter4,5/abstractFactory/src/factory/GUIFactory.java b/chapter4,5/abstractFactory/src/factory/GUIFactory.java
new file mode 100644
index 0000000..79f04d8
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/factory/GUIFactory.java
@@ -0,0 +1,10 @@
+package factory;
+
+import button.Button;
+import checkBox.CheckBox;
+
+public interface GUIFactory {
+ Button createButton();
+
+ CheckBox createCheckBox();
+}
diff --git a/chapter4,5/abstractFactory/src/factory/MacFactory.java b/chapter4,5/abstractFactory/src/factory/MacFactory.java
new file mode 100644
index 0000000..24a38fd
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/factory/MacFactory.java
@@ -0,0 +1,30 @@
+package factory;
+
+import button.Button;
+import button.MacButton;
+import checkBox.CheckBox;
+import checkBox.MacCheckBox;
+
+public class MacFactory implements GUIFactory {
+
+ private MacFactory() {
+ }
+
+ private static class MacFactoryLazyHolder {
+ public static final MacFactory INSTANCE = new MacFactory();
+ }
+
+ public static MacFactory getInstance() {
+ return MacFactoryLazyHolder.INSTANCE;
+ }
+
+ @Override
+ public Button createButton() {
+ return new MacButton();
+ }
+
+ @Override
+ public CheckBox createCheckBox() {
+ return new MacCheckBox();
+ }
+}
diff --git a/chapter4,5/abstractFactory/src/factory/WinFactory.java b/chapter4,5/abstractFactory/src/factory/WinFactory.java
new file mode 100644
index 0000000..f3f0274
--- /dev/null
+++ b/chapter4,5/abstractFactory/src/factory/WinFactory.java
@@ -0,0 +1,29 @@
+package factory;
+
+import button.Button;
+import button.WinButton;
+import checkBox.CheckBox;
+import checkBox.WinCheckBox;
+
+public class WinFactory implements GUIFactory {
+ private WinFactory() {
+ }
+
+ private static class WinFactoryLazyHolder {
+ private static final WinFactory INSTANCE = new WinFactory();
+ }
+
+ public static WinFactory getInstance() {
+ return WinFactoryLazyHolder.INSTANCE;
+ }
+
+ @Override
+ public Button createButton() {
+ return new WinButton();
+ }
+
+ @Override
+ public CheckBox createCheckBox() {
+ return new WinCheckBox();
+ }
+}
diff --git a/chapter6/command/.gitignore b/chapter6/command/.gitignore
new file mode 100644
index 0000000..b63da45
--- /dev/null
+++ b/chapter6/command/.gitignore
@@ -0,0 +1,42 @@
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/chapter6/command/.idea/.gitignore b/chapter6/command/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/chapter6/command/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/chapter6/command/build.gradle b/chapter6/command/build.gradle
new file mode 100644
index 0000000..f7beddb
--- /dev/null
+++ b/chapter6/command/build.gradle
@@ -0,0 +1,19 @@
+plugins {
+ id 'java'
+}
+
+group = 'org.example'
+version = '1.0-SNAPSHOT'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation platform('org.junit:junit-bom:5.9.1')
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+}
+
+test {
+ useJUnitPlatform()
+}
\ No newline at end of file
diff --git a/chapter6/command/gradle/wrapper/gradle-wrapper.jar b/chapter6/command/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..249e583
Binary files /dev/null and b/chapter6/command/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/chapter6/command/gradle/wrapper/gradle-wrapper.properties b/chapter6/command/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..480c1e4
--- /dev/null
+++ b/chapter6/command/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Jun 29 21:10:36 KST 2023
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/chapter6/command/gradlew b/chapter6/command/gradlew
new file mode 100755
index 0000000..1b6c787
--- /dev/null
+++ b/chapter6/command/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/chapter6/command/gradlew.bat b/chapter6/command/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/chapter6/command/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/chapter6/command/settings.gradle b/chapter6/command/settings.gradle
new file mode 100644
index 0000000..d731fe9
--- /dev/null
+++ b/chapter6/command/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'command'
+
diff --git a/chapter6/command/src/main/java/Application.java b/chapter6/command/src/main/java/Application.java
new file mode 100644
index 0000000..e7aa28f
--- /dev/null
+++ b/chapter6/command/src/main/java/Application.java
@@ -0,0 +1,55 @@
+import java.util.ArrayList;
+import java.util.List;
+
+public class Application {
+ String clipboard;
+ List editors = new ArrayList<>();
+ Editor activeEditor;
+ CommandHistory history;
+
+ public Application() {
+ this.history = new CommandHistory();
+ }
+
+ public void addEditor(Editor editor) {
+ System.out.println(editor + "가 추가되었습니다.");
+ editors.add(editor);
+ }
+
+ public void changeEditor(Editor editor) {
+ if (editors.contains(editor)) {
+ activeEditor = editor;
+ System.out.println("application이 관리하는 editor가 " + editor + "로 변경되었습니다.");
+ }
+ editors.add(editor);
+ System.out.println(editor + "를 추가하고 변경하였습니다.");
+ activeEditor = editor;
+ }
+
+ public Editor getActiveEditor() {
+ return activeEditor;
+ }
+
+ public void executeCommand(Command command, CursorPosition cursorPosition) {
+ if (command.execute(cursorPosition)) {
+ history.push(command);
+ }
+ }
+
+ public Command undo() {
+ if (history.isEmptyHistory()) {
+ return null;
+ }
+ return history.pop();
+ }
+
+ @Override
+ public String toString() {
+ return "Application{" +
+ "clipboard='" + clipboard + '\'' +
+ ", editors=" + editors +
+ ", activeEditor=" + activeEditor +
+ ", history=" + history +
+ '}';
+ }
+}
diff --git a/chapter6/command/src/main/java/Command.java b/chapter6/command/src/main/java/Command.java
new file mode 100644
index 0000000..6229c02
--- /dev/null
+++ b/chapter6/command/src/main/java/Command.java
@@ -0,0 +1,29 @@
+public abstract class Command {
+ public Application application;
+ public Editor editor;
+ private String backup;
+
+ public Command(Application application, Editor editor) {
+ this.application = application;
+ this.editor = editor;
+ }
+
+ public void saveBackup() {
+ this.backup = editor.text;
+ }
+
+ public void undo() {
+ editor.text = backup;
+ }
+
+ @Override
+ public String toString() {
+ return "Command{" +
+ "application=" + application +
+ ", editor=" + editor +
+ ", backup='" + backup + '\'' +
+ '}';
+ }
+
+ abstract boolean execute(CursorPosition cursorPosition);
+}
diff --git a/chapter6/command/src/main/java/CommandHistory.java b/chapter6/command/src/main/java/CommandHistory.java
new file mode 100644
index 0000000..29925c6
--- /dev/null
+++ b/chapter6/command/src/main/java/CommandHistory.java
@@ -0,0 +1,22 @@
+import java.util.Stack;
+
+public class CommandHistory {
+
+ Stack history = new Stack<>();
+
+ public void push(Command command) {
+ System.out.println(command + "를 스택에 넣었습니다.");
+ history.push(command);
+ }
+
+ public Command pop() {
+ Command command = history.pop();
+ System.out.println(command + "가 취소 되었습니다.");
+ return command;
+ }
+
+ public boolean isEmptyHistory() {
+ return history.isEmpty();
+ }
+
+}
diff --git a/chapter6/command/src/main/java/CopyCommand.java b/chapter6/command/src/main/java/CopyCommand.java
new file mode 100644
index 0000000..68c30a5
--- /dev/null
+++ b/chapter6/command/src/main/java/CopyCommand.java
@@ -0,0 +1,12 @@
+public class CopyCommand extends Command {
+ public CopyCommand(Application application, Editor editor) {
+ super(application, editor);
+ }
+
+ @Override
+ boolean execute(CursorPosition cursorPosition) {
+ application.clipboard = editor.getSelection(cursorPosition.getStart(), cursorPosition.getEnd());
+ System.out.println("현재 clipBoard 의 상태 : " + application.clipboard);
+ return false;
+ }
+}
diff --git a/chapter6/command/src/main/java/CursorPosition.java b/chapter6/command/src/main/java/CursorPosition.java
new file mode 100644
index 0000000..4a865d3
--- /dev/null
+++ b/chapter6/command/src/main/java/CursorPosition.java
@@ -0,0 +1,17 @@
+public class CursorPosition {
+ private int start;
+ private int end;
+
+ public CursorPosition(int start, int end) {
+ this.start = start;
+ this.end = end;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ public int getEnd() {
+ return end;
+ }
+}
diff --git a/chapter6/command/src/main/java/CutCommand.java b/chapter6/command/src/main/java/CutCommand.java
new file mode 100644
index 0000000..0bc850c
--- /dev/null
+++ b/chapter6/command/src/main/java/CutCommand.java
@@ -0,0 +1,14 @@
+public class CutCommand extends Command {
+ public CutCommand(Application application, Editor editor) {
+ super(application, editor);
+ }
+
+ @Override
+ boolean execute(CursorPosition cursorPosition) {
+ saveBackup();
+ application.clipboard = editor.getSelection(cursorPosition.getStart(), cursorPosition.getEnd());
+ editor.deleteSelection(cursorPosition.getStart(), cursorPosition.getEnd());
+ System.out.println("현재 clipBoard 의 상태 : " + application.clipboard);
+ return true;
+ }
+}
diff --git a/chapter6/command/src/main/java/Editor.java b/chapter6/command/src/main/java/Editor.java
new file mode 100644
index 0000000..53dd708
--- /dev/null
+++ b/chapter6/command/src/main/java/Editor.java
@@ -0,0 +1,27 @@
+public class Editor {
+
+ public String text;
+
+ public Editor(String text) {
+ this.text = text;
+ }
+
+ public String getSelection(int start, int end) {
+ return text.substring(start, end);
+ }
+
+ public void deleteSelection(int start, int end) {
+ this.text = text.substring(0, start) + text.substring(end);
+ }
+
+ public void replaceSelection(int start, int end, String text) {
+ this.text = this.text.substring(0, start) + text + this.text.substring(end);
+ }
+
+ @Override
+ public String toString() {
+ return "Editor{" +
+ "text='" + text + '\'' +
+ '}';
+ }
+}
diff --git a/chapter6/command/src/main/java/EditorApp.java b/chapter6/command/src/main/java/EditorApp.java
new file mode 100644
index 0000000..123cfd1
--- /dev/null
+++ b/chapter6/command/src/main/java/EditorApp.java
@@ -0,0 +1,14 @@
+public class EditorApp {
+ public static void main(String[] args) {
+ Application application = new Application();
+ Editor editorA = new Editor("aaaabbbbccccccccc");
+ Editor editorB = new Editor("aaaaaabbbbbbsssdddsfasd");
+ application.addEditor(editorA);
+ application.addEditor(editorB);
+ application.changeEditor(editorA);
+ application.executeCommand(new CopyCommand(application, application.getActiveEditor()), new CursorPosition(0, 5));
+ application.executeCommand(new CutCommand(application, application.getActiveEditor()), new CursorPosition(1, 3));
+ application.executeCommand(new PasteCommand(application, application.getActiveEditor()), new CursorPosition(0, 5));
+ application.executeCommand(new UndoCommand(application, application.getActiveEditor()), new CursorPosition(0, 0));
+ }
+}
diff --git a/chapter6/command/src/main/java/PasteCommand.java b/chapter6/command/src/main/java/PasteCommand.java
new file mode 100644
index 0000000..f7de3e1
--- /dev/null
+++ b/chapter6/command/src/main/java/PasteCommand.java
@@ -0,0 +1,12 @@
+public class PasteCommand extends Command {
+ public PasteCommand(Application application, Editor editor) {
+ super(application, editor);
+ }
+
+ @Override
+ boolean execute(CursorPosition cursorPosition) {
+ editor.replaceSelection(cursorPosition.getStart(), cursorPosition.getEnd(), application.clipboard);
+ System.out.println("현재 clipBoard 의 상태 : " + application.clipboard);
+ return true;
+ }
+}
diff --git a/chapter6/command/src/main/java/UndoCommand.java b/chapter6/command/src/main/java/UndoCommand.java
new file mode 100644
index 0000000..ff705ca
--- /dev/null
+++ b/chapter6/command/src/main/java/UndoCommand.java
@@ -0,0 +1,12 @@
+public class UndoCommand extends Command {
+ public UndoCommand(Application application, Editor editor) {
+ super(application, editor);
+ }
+
+ @Override
+ boolean execute(CursorPosition cursorPosition) {
+ application.undo();
+ System.out.println("현재 clipBoard 의 상태 : " + application.clipboard);
+ return false;
+ }
+}
diff --git a/chapter7/Facade/.gitignore b/chapter7/Facade/.gitignore
new file mode 100644
index 0000000..b63da45
--- /dev/null
+++ b/chapter7/Facade/.gitignore
@@ -0,0 +1,42 @@
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/chapter7/Facade/.idea/.gitignore b/chapter7/Facade/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/chapter7/Facade/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/chapter7/Facade/.idea/uiDesigner.xml b/chapter7/Facade/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/chapter7/Facade/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter7/Facade/build.gradle b/chapter7/Facade/build.gradle
new file mode 100644
index 0000000..f7beddb
--- /dev/null
+++ b/chapter7/Facade/build.gradle
@@ -0,0 +1,19 @@
+plugins {
+ id 'java'
+}
+
+group = 'org.example'
+version = '1.0-SNAPSHOT'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation platform('org.junit:junit-bom:5.9.1')
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+}
+
+test {
+ useJUnitPlatform()
+}
\ No newline at end of file
diff --git a/chapter7/Facade/gradle/wrapper/gradle-wrapper.jar b/chapter7/Facade/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..249e583
Binary files /dev/null and b/chapter7/Facade/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/chapter7/Facade/gradle/wrapper/gradle-wrapper.properties b/chapter7/Facade/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..e931881
--- /dev/null
+++ b/chapter7/Facade/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 30 01:33:34 KST 2023
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/chapter7/Facade/gradlew b/chapter7/Facade/gradlew
new file mode 100755
index 0000000..1b6c787
--- /dev/null
+++ b/chapter7/Facade/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/chapter7/Facade/gradlew.bat b/chapter7/Facade/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/chapter7/Facade/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/chapter7/Facade/settings.gradle b/chapter7/Facade/settings.gradle
new file mode 100644
index 0000000..84db708
--- /dev/null
+++ b/chapter7/Facade/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'Facade'
+
diff --git a/chapter7/Facade/src/main/java/Application.java b/chapter7/Facade/src/main/java/Application.java
new file mode 100644
index 0000000..750cb87
--- /dev/null
+++ b/chapter7/Facade/src/main/java/Application.java
@@ -0,0 +1,12 @@
+import domain.AudioFile;
+import facade.VideoConversionFacade;
+
+import java.text.MessageFormat;
+
+public class Application {
+ public static void main(String[] args) {
+ VideoConversionFacade videoConversionFacade = new VideoConversionFacade();
+ AudioFile file = videoConversionFacade.convertToAudio("movie.ogg", "mpeg4");
+ System.out.println(MessageFormat.format("FileName : {0}, CodecType : {1}", file.getFileName(), file.getCodecType()));
+ }
+}
diff --git a/chapter7/Facade/src/main/java/domain/AudioFile.java b/chapter7/Facade/src/main/java/domain/AudioFile.java
new file mode 100644
index 0000000..bfac023
--- /dev/null
+++ b/chapter7/Facade/src/main/java/domain/AudioFile.java
@@ -0,0 +1,30 @@
+package domain;
+
+
+public class AudioFile {
+
+ private String fileName;
+ private CodecType codecType;
+
+ public AudioFile(String fileName, CodecType codecType) {
+ this.fileName = fileName;
+ this.codecType = CodecType.getCodecType(getExtract(fileName));
+ }
+
+ private String getExtract(String fileName) {
+ int index = fileName.indexOf(".");
+ return fileName.substring(index + 1);
+ }
+
+ public static AudioFile fix(VideoFile convertFile) {
+ return new AudioFile(convertFile.fileName, convertFile.codecType);
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public CodecType getCodecType() {
+ return codecType;
+ }
+}
diff --git a/chapter7/Facade/src/main/java/domain/BitrateReader.java b/chapter7/Facade/src/main/java/domain/BitrateReader.java
new file mode 100644
index 0000000..ba4c0d0
--- /dev/null
+++ b/chapter7/Facade/src/main/java/domain/BitrateReader.java
@@ -0,0 +1,10 @@
+package domain;
+
+public class BitrateReader {
+
+ public static VideoFile convert(VideoFile file, CodecType codecType) {
+ int index = file.getFileName().indexOf(".");
+ String fileName = file.getFileName().substring(0, index + 1) + codecType.getCodecName();
+ return new VideoFile(fileName);
+ }
+}
diff --git a/chapter7/Facade/src/main/java/domain/CodecType.java b/chapter7/Facade/src/main/java/domain/CodecType.java
new file mode 100644
index 0000000..aebc865
--- /dev/null
+++ b/chapter7/Facade/src/main/java/domain/CodecType.java
@@ -0,0 +1,28 @@
+package domain;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public enum CodecType {
+ OGG_COMPRESSION("ogg"), MPEG4_COMPRESSION("mpeg4");
+
+ private final String codecName;
+ private static final Map CODECTYPE_MAP = Collections.unmodifiableMap(Arrays.stream(CodecType.values())
+ .collect(Collectors.toMap(CodecType::getCodecName, Function.identity())));
+
+
+ CodecType(String codecName) {
+ this.codecName = codecName;
+ }
+
+ public static CodecType getCodecType(String codecName) {
+ return CODECTYPE_MAP.get(codecName);
+ }
+
+ public String getCodecName() {
+ return codecName;
+ }
+}
diff --git a/chapter7/Facade/src/main/java/domain/VideoFile.java b/chapter7/Facade/src/main/java/domain/VideoFile.java
new file mode 100644
index 0000000..155d43f
--- /dev/null
+++ b/chapter7/Facade/src/main/java/domain/VideoFile.java
@@ -0,0 +1,24 @@
+package domain;
+
+public class VideoFile {
+ String fileName;
+ CodecType codecType;
+
+ public VideoFile(String fileName) {
+ this.fileName = fileName;
+ this.codecType = CodecType.getCodecType(getExtract(fileName));
+ }
+
+ private String getExtract(String fileName) {
+ int index = fileName.indexOf(".");
+ return fileName.substring(index + 1);
+ }
+
+ public CodecType getCodecType() {
+ return codecType;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+}
diff --git a/chapter7/Facade/src/main/java/facade/VideoConversionFacade.java b/chapter7/Facade/src/main/java/facade/VideoConversionFacade.java
new file mode 100644
index 0000000..dfd227f
--- /dev/null
+++ b/chapter7/Facade/src/main/java/facade/VideoConversionFacade.java
@@ -0,0 +1,17 @@
+package facade;
+
+import domain.AudioFile;
+import domain.BitrateReader;
+import domain.CodecType;
+import domain.VideoFile;
+import util.CodecFactory;
+
+public class VideoConversionFacade {
+
+ public AudioFile convertToAudio(String fileName, String format) {
+ VideoFile videoFile = new VideoFile(fileName);
+ CodecType convertCodecType = CodecType.getCodecType(format);
+ VideoFile convertFile = BitrateReader.convert(videoFile, convertCodecType);
+ return AudioFile.fix(convertFile);
+ }
+}
diff --git a/chapter7/Facade/src/main/java/util/CodecFactory.java b/chapter7/Facade/src/main/java/util/CodecFactory.java
new file mode 100644
index 0000000..522564a
--- /dev/null
+++ b/chapter7/Facade/src/main/java/util/CodecFactory.java
@@ -0,0 +1,11 @@
+package util;
+
+import domain.CodecType;
+import domain.VideoFile;
+
+public class CodecFactory {
+
+ public static CodecType extractFrom(VideoFile file) {
+ return file.getCodecType();
+ }
+}
diff --git a/chapter7/adapter/.gitignore b/chapter7/adapter/.gitignore
new file mode 100644
index 0000000..b63da45
--- /dev/null
+++ b/chapter7/adapter/.gitignore
@@ -0,0 +1,42 @@
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/chapter7/adapter/.idea/.gitignore b/chapter7/adapter/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/chapter7/adapter/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/chapter7/adapter/build.gradle b/chapter7/adapter/build.gradle
new file mode 100644
index 0000000..f7beddb
--- /dev/null
+++ b/chapter7/adapter/build.gradle
@@ -0,0 +1,19 @@
+plugins {
+ id 'java'
+}
+
+group = 'org.example'
+version = '1.0-SNAPSHOT'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation platform('org.junit:junit-bom:5.9.1')
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+}
+
+test {
+ useJUnitPlatform()
+}
\ No newline at end of file
diff --git a/chapter7/adapter/gradle/wrapper/gradle-wrapper.jar b/chapter7/adapter/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..249e583
Binary files /dev/null and b/chapter7/adapter/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/chapter7/adapter/gradle/wrapper/gradle-wrapper.properties b/chapter7/adapter/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..3d236fd
--- /dev/null
+++ b/chapter7/adapter/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 30 00:21:04 KST 2023
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/chapter7/adapter/gradlew b/chapter7/adapter/gradlew
new file mode 100755
index 0000000..1b6c787
--- /dev/null
+++ b/chapter7/adapter/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/chapter7/adapter/gradlew.bat b/chapter7/adapter/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/chapter7/adapter/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/chapter7/adapter/settings.gradle b/chapter7/adapter/settings.gradle
new file mode 100644
index 0000000..8df43d4
--- /dev/null
+++ b/chapter7/adapter/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'adapter'
+
diff --git a/chapter7/adapter/src/main/java/AdapterApp.java b/chapter7/adapter/src/main/java/AdapterApp.java
new file mode 100644
index 0000000..261ee68
--- /dev/null
+++ b/chapter7/adapter/src/main/java/AdapterApp.java
@@ -0,0 +1,16 @@
+import domain.RoundHole;
+import domain.RoundPeg;
+import domain.RoundPegAdapter;
+import domain.SquarePeg;
+
+public class AdapterApp {
+ public static void main(String[] args) {
+ RoundHole roundHole = new RoundHole(5);
+ RoundPeg roundPeg = new RoundPeg(5.5);
+ System.out.println(roundHole.fits(roundPeg));
+
+ SquarePeg squarePeg = new SquarePeg(8);
+ RoundPegAdapter roundPegAdapter = new RoundPegAdapter(squarePeg);
+ System.out.println(roundHole.fits(roundPegAdapter));
+ }
+}
diff --git a/chapter7/adapter/src/main/java/domain/RoundHole.java b/chapter7/adapter/src/main/java/domain/RoundHole.java
new file mode 100644
index 0000000..2f195c3
--- /dev/null
+++ b/chapter7/adapter/src/main/java/domain/RoundHole.java
@@ -0,0 +1,17 @@
+package domain;
+
+public class RoundHole {
+ int radius;
+
+ public RoundHole(int radius) {
+ this.radius = radius;
+ }
+
+ public int getRadius() {
+ return this.radius;
+ }
+
+ public boolean fits(RoundPeg roundPeg) {
+ return this.radius >= roundPeg.getRadius();
+ }
+}
diff --git a/chapter7/adapter/src/main/java/domain/RoundPeg.java b/chapter7/adapter/src/main/java/domain/RoundPeg.java
new file mode 100644
index 0000000..7794f03
--- /dev/null
+++ b/chapter7/adapter/src/main/java/domain/RoundPeg.java
@@ -0,0 +1,15 @@
+package domain;
+
+public class RoundPeg {
+ private double radius;
+
+ public RoundPeg() {}
+
+ public RoundPeg(double radius) {
+ this.radius = radius;
+ }
+
+ public double getRadius() {
+ return radius;
+ }
+}
diff --git a/chapter7/adapter/src/main/java/domain/RoundPegAdapter.java b/chapter7/adapter/src/main/java/domain/RoundPegAdapter.java
new file mode 100644
index 0000000..7272b67
--- /dev/null
+++ b/chapter7/adapter/src/main/java/domain/RoundPegAdapter.java
@@ -0,0 +1,14 @@
+package domain;
+
+public class RoundPegAdapter extends RoundPeg{
+
+ private SquarePeg squarePeg;
+
+ public RoundPegAdapter(SquarePeg squarePeg) {
+ this.squarePeg = squarePeg;
+ }
+
+ public double getRadius() {
+ return squarePeg.getWidth() / 2.0;
+ }
+}
diff --git a/chapter7/adapter/src/main/java/domain/SquarePeg.java b/chapter7/adapter/src/main/java/domain/SquarePeg.java
new file mode 100644
index 0000000..76dfe86
--- /dev/null
+++ b/chapter7/adapter/src/main/java/domain/SquarePeg.java
@@ -0,0 +1,13 @@
+package domain;
+
+public class SquarePeg {
+ private int width;
+
+ public SquarePeg(int width) {
+ this.width = width;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+}
diff --git a/chapter8/Iterator/.idea/.gitignore b/chapter8/Iterator/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/chapter8/Iterator/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/chapter8/Iterator/.idea/misc.xml b/chapter8/Iterator/.idea/misc.xml
new file mode 100644
index 0000000..6ccf6d9
--- /dev/null
+++ b/chapter8/Iterator/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter8/Iterator/.idea/modules.xml b/chapter8/Iterator/.idea/modules.xml
new file mode 100644
index 0000000..67c9851
--- /dev/null
+++ b/chapter8/Iterator/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter8/Iterator/.idea/uiDesigner.xml b/chapter8/Iterator/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/chapter8/Iterator/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter8/Iterator/.idea/vcs.xml b/chapter8/Iterator/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/chapter8/Iterator/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter8/Iterator/Iterator.iml b/chapter8/Iterator/Iterator.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/chapter8/Iterator/Iterator.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter8/Iterator/src/com/iterator/Main.java b/chapter8/Iterator/src/com/iterator/Main.java
new file mode 100644
index 0000000..f9e5852
--- /dev/null
+++ b/chapter8/Iterator/src/com/iterator/Main.java
@@ -0,0 +1,34 @@
+package com.iterator;
+
+import com.iterator.domain.Facebook;
+import com.iterator.domain.LinkedIn;
+import com.iterator.domain.SocialNetwork;
+import com.iterator.domain.SocialNetworkType;
+import com.iterator.service.SocialSpammer;
+
+import java.util.Scanner;
+
+public class Main {
+ private final static Scanner SCANNER = new Scanner(System.in);
+
+ public static void main(String[] args) {
+
+ System.out.println("==please input SocialTypeNumber==");
+
+ for (SocialNetworkType type : SocialNetworkType.values()) {
+ System.out.println(type.getTypeNumber() + ". : " + type.name());
+ }
+
+ int typeNumber = SCANNER.nextInt();
+ SocialNetworkType socialNetworkType = SocialNetworkType.findByNumber(typeNumber);
+
+ SocialNetwork socialNetwork = switch(socialNetworkType) {
+ case FACEBOOK -> new Facebook(TestData.initData());
+ case LINKEDIN -> new LinkedIn(TestData.initData());
+ };
+
+ SocialSpammer spammer = new SocialSpammer(socialNetwork);
+ spammer.sendSpamToFriends("bombo96@naver.com", "너모 어렵습니다");
+ spammer.sendSpamToCoworkers("bombo96@naver.com", "스펜서님은 언제 쉬시나요?");
+ }
+}
diff --git a/chapter8/Iterator/src/com/iterator/TestData.java b/chapter8/Iterator/src/com/iterator/TestData.java
new file mode 100644
index 0000000..106eed8
--- /dev/null
+++ b/chapter8/Iterator/src/com/iterator/TestData.java
@@ -0,0 +1,20 @@
+package com.iterator;
+
+import com.iterator.domain.Profile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class TestData {
+
+ public static List initData() {
+ List data = new ArrayList<>();
+ data.add(new Profile("bombo96@naver.com", "문종운", "friends:seyeon@naver.com", "friends:wonu123@naver.com", "friends:kbg1155@naver.com", "friends:sw1234@naver.com", "coworkers:spencer@naver.com"));
+ data.add(new Profile("kbg1155@naver.com", "강병곤", "friends:seyeon@naver.com", "friends:wonu123@naver.com", "friends:bombo96@naver.com", "friends:sw1234@naver.com", "coworkers:spencer@naver.com"));
+ data.add(new Profile("sw1234@naver.com", "한승원", "friends:seyeon@naver.com", "friends:wonu123@naver.com", "friends:kbg1155@naver.com", "friends:bombo96@naver.com", "coworkers:spencer@naver.com"));
+ data.add(new Profile("seyeon@naver.com", "박세연", "friends:bombo96@naver.com", "friends:wonu123@naver.com", "friends:kbg1155@naver.com", "friends:sw1234@naver.com", "coworkers:spencer@naver.com"));
+ data.add(new Profile("wonu123@naver.com", "유원우", "friends:seyeon@naver.com", "friends:bombo96@naver.com", "friends:kbg1155@naver.com", "friends:sw1234@naver.com", "coworkers:spencer@naver.com"));
+ data.add(new Profile("spencer@naver.com", "스펜서", "friends:seyeon@naver.com", "friends:wonu123@naver.com", "friends:kbg1155@naver.com", "friends:sw1234@naver.com", "coworkers:bombo96@naver.com"));
+ return data;
+ }
+}
diff --git a/chapter8/Iterator/src/com/iterator/domain/Facebook.java b/chapter8/Iterator/src/com/iterator/domain/Facebook.java
new file mode 100644
index 0000000..9d18e37
--- /dev/null
+++ b/chapter8/Iterator/src/com/iterator/domain/Facebook.java
@@ -0,0 +1,55 @@
+package com.iterator.domain;
+
+import com.iterator.domain.iterator.FacebookIterator;
+import com.iterator.domain.iterator.ProfileIterator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Facebook implements SocialNetwork {
+ private List profiles;
+
+ public Facebook(List cache) {
+ if (cache != null) {
+ this.profiles = cache;
+ return;
+ }
+ this.profiles = new ArrayList<>();
+ }
+
+ public Profile requestProfileFriendsFromFacebook(String profileEmail) {
+ System.out.println("Facebook : Loading Profile '" + profileEmail + "' over the network...");
+
+ return findProfile(profileEmail);
+ }
+
+ public List requestProfileFriendsFromFacebook(String profileEmail, String contactType) {
+ System.out.println("Facebook : Loading '" + contactType + "' list of '" + profileEmail + "' over the network...");
+
+ Profile profile = findProfile(profileEmail);
+
+ if (profile != null) {
+ return profile.getContacts(contactType);
+ }
+
+ return null;
+ }
+
+ private Profile findProfile(String profileEmail) {
+
+ return this.profiles.stream()
+ .filter((profile) -> profile.getEmail().equals(profileEmail))
+ .findFirst()
+ .orElse(null);
+ }
+
+ @Override
+ public ProfileIterator createFriendsIterator(String profileEmail) {
+ return new FacebookIterator(this, "friends", profileEmail);
+ }
+
+ @Override
+ public ProfileIterator createCoWorkersIterator(String profileEmail) {
+ return new FacebookIterator(this, "coworkers", profileEmail);
+ }
+}
diff --git a/chapter8/Iterator/src/com/iterator/domain/LinkedIn.java b/chapter8/Iterator/src/com/iterator/domain/LinkedIn.java
new file mode 100644
index 0000000..942886d
--- /dev/null
+++ b/chapter8/Iterator/src/com/iterator/domain/LinkedIn.java
@@ -0,0 +1,61 @@
+package com.iterator.domain;
+
+import com.iterator.domain.iterator.LinkedInIterator;
+import com.iterator.domain.iterator.ProfileIterator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LinkedIn implements SocialNetwork{
+ private List profiles;
+
+ public LinkedIn(List cache) {
+ if (cache != null) {
+ this.profiles = cache;
+ }
+ this.profiles = new ArrayList<>();
+ }
+
+ public Profile requestContactInfoFromLinkedInAPI(String profileEmail) {
+ System.out.println("LinkedIn: Loading profile '" + profileEmail + "' over the network...");
+
+ return findContact(profileEmail);
+ }
+
+ public List requestRelatedContactsFromLinkedInAPI(String profileEmail, String contactType) {
+ System.out.println("LinkedIn: Loading '" + contactType + "' list of '" + profileEmail + "' over the network...");
+
+ Profile profile = findContact(profileEmail);
+ if (profile != null) {
+ return profile.getContacts(contactType);
+ }
+ return null;
+ }
+
+ private Profile findContact(String profileEmail) {
+ for (Profile profile : profiles) {
+ if (profile.getEmail().equals(profileEmail)) {
+ return profile;
+ }
+ }
+ return null;
+ }
+
+ 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 createCoWorkersIterator(String profileEmail) {
+ return new LinkedInIterator(this, "coworkers", profileEmail);
+ }
+}
diff --git a/chapter8/Iterator/src/com/iterator/domain/Profile.java b/chapter8/Iterator/src/com/iterator/domain/Profile.java
new file mode 100644
index 0000000..06eebdd
--- /dev/null
+++ b/chapter8/Iterator/src/com/iterator/domain/Profile.java
@@ -0,0 +1,52 @@
+package com.iterator.domain;
+
+import java.util.ArrayList;
+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<>();
+
+ public Profile(String email, String name, String... contacts) {
+
+ this.name = name;
+ this.email = email;
+
+ for (String contact : contacts) {
+ String[] part = contact.split(":");
+ String contactType = "friend";
+ String contactEmail = "";
+
+ if(part.length == 1) {
+ contactEmail = part[0];
+ } else {
+ contactType = part[0];
+ contactEmail = part[1];
+ }
+
+ if(!this.contacts.containsKey(contactType)) {
+ this.contacts.put(contactType, new ArrayList<>());
+ }
+ this.contacts.get(contactType).add(contactEmail);
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public List getContacts(String contactType) {
+ if (!this.contacts.containsKey(contactType)) {
+ this.contacts.put(contactType, new ArrayList<>());
+ }
+
+ return this.contacts.get(contactType);
+ }
+}
diff --git a/chapter8/Iterator/src/com/iterator/domain/SocialNetwork.java b/chapter8/Iterator/src/com/iterator/domain/SocialNetwork.java
new file mode 100644
index 0000000..3f82ac3
--- /dev/null
+++ b/chapter8/Iterator/src/com/iterator/domain/SocialNetwork.java
@@ -0,0 +1,8 @@
+package com.iterator.domain;
+
+import com.iterator.domain.iterator.ProfileIterator;
+
+public interface SocialNetwork {
+ ProfileIterator createFriendsIterator(String profileEmail);
+ ProfileIterator createCoWorkersIterator(String profileEmail);
+}
diff --git a/chapter8/Iterator/src/com/iterator/domain/SocialNetworkType.java b/chapter8/Iterator/src/com/iterator/domain/SocialNetworkType.java
new file mode 100644
index 0000000..86d332b
--- /dev/null
+++ b/chapter8/Iterator/src/com/iterator/domain/SocialNetworkType.java
@@ -0,0 +1,27 @@
+package com.iterator.domain;
+
+import java.util.Arrays;
+
+public enum SocialNetworkType {
+ FACEBOOK(1),
+ LINKEDIN(2);
+
+ private final int typeNumber;
+
+ SocialNetworkType(int typeNumber) {
+ this.typeNumber = typeNumber;
+ }
+
+ public static SocialNetworkType findByNumber(int number) {
+ SocialNetworkType socialNetworkType = Arrays.stream(values())
+ .filter((type) -> type.typeNumber == number)
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException("존재하지 않은 소셜 타입 번호 입력"));
+
+ return socialNetworkType;
+ }
+
+ public int getTypeNumber() {
+ return this.typeNumber;
+ }
+}
diff --git a/chapter8/Iterator/src/com/iterator/domain/iterator/FacebookIterator.java b/chapter8/Iterator/src/com/iterator/domain/iterator/FacebookIterator.java
new file mode 100644
index 0000000..3c9f506
--- /dev/null
+++ b/chapter8/Iterator/src/com/iterator/domain/iterator/FacebookIterator.java
@@ -0,0 +1,59 @@
+package com.iterator.domain.iterator;
+
+import com.iterator.domain.Facebook;
+import com.iterator.domain.Profile;
+
+import java.util.ArrayList;
+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 void lazyLoading() {
+ if (emails.size() == 0) {
+ List profiles = facebook.requestProfileFriendsFromFacebook(this.email, this.type);
+ for(String profile : profiles) {
+ this.emails.add(profile);
+ this.profiles.add(null);
+ }
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ lazyLoading();
+ return currentPosition < emails.size();
+ }
+
+ @Override
+ public Profile getNext() {
+ if(!hasNext()) {
+ return null;
+ }
+
+ String email = emails.get(currentPosition);
+ Profile profile = profiles.get(currentPosition);
+ if (profile == null) {
+ profile = facebook.requestProfileFriendsFromFacebook(email);
+ profiles.set(currentPosition, profile);
+ }
+ currentPosition++;
+ return profile;
+ }
+
+ @Override
+ public void reset() {
+ currentPosition = 0;
+ }
+}
diff --git a/chapter8/Iterator/src/com/iterator/domain/iterator/LinkedInIterator.java b/chapter8/Iterator/src/com/iterator/domain/iterator/LinkedInIterator.java
new file mode 100644
index 0000000..963d805
--- /dev/null
+++ b/chapter8/Iterator/src/com/iterator/domain/iterator/LinkedInIterator.java
@@ -0,0 +1,59 @@
+package com.iterator.domain.iterator;
+
+import com.iterator.domain.LinkedIn;
+import com.iterator.domain.Profile;
+
+import java.util.ArrayList;
+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 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);
+ }
+ }
+ }
+
+ @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/chapter8/Iterator/src/com/iterator/domain/iterator/ProfileIterator.java b/chapter8/Iterator/src/com/iterator/domain/iterator/ProfileIterator.java
new file mode 100644
index 0000000..f39f752
--- /dev/null
+++ b/chapter8/Iterator/src/com/iterator/domain/iterator/ProfileIterator.java
@@ -0,0 +1,10 @@
+package com.iterator.domain.iterator;
+
+import com.iterator.domain.Profile;
+
+public interface ProfileIterator {
+
+ boolean hasNext();
+ Profile getNext();
+ void reset();
+}
diff --git a/chapter8/Iterator/src/com/iterator/service/SocialSpammer.java b/chapter8/Iterator/src/com/iterator/service/SocialSpammer.java
new file mode 100644
index 0000000..7b53002
--- /dev/null
+++ b/chapter8/Iterator/src/com/iterator/service/SocialSpammer.java
@@ -0,0 +1,36 @@
+package com.iterator.service;
+
+import com.iterator.domain.Profile;
+import com.iterator.domain.SocialNetwork;
+import com.iterator.domain.iterator.ProfileIterator;
+
+public class SocialSpammer {
+ public SocialNetwork socialNetwork;
+ public ProfileIterator iterator;
+
+ public SocialSpammer(SocialNetwork socialNetwork) {
+ this.socialNetwork = socialNetwork;
+ }
+
+ public void sendSpamToFriends(String profileEmail, String message) {
+ System.out.println("Iterating over friends...");
+ iterator = socialNetwork.createFriendsIterator(profileEmail);
+ while (iterator.hasNext()) {
+ Profile profile = iterator.getNext();
+ sendMessage(profile.getEmail(), message);
+ }
+ }
+
+ public void sendSpamToCoworkers(String profileEmail, String message) {
+ System.out.println("Iterating over coworkers...");
+ iterator = socialNetwork.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 + "'");
+ }
+}
diff --git a/chapter8/templateMethod/.gitignore b/chapter8/templateMethod/.gitignore
new file mode 100644
index 0000000..f68d109
--- /dev/null
+++ b/chapter8/templateMethod/.gitignore
@@ -0,0 +1,29 @@
+### IntelliJ IDEA ###
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/chapter8/templateMethod/.idea/.gitignore b/chapter8/templateMethod/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/chapter8/templateMethod/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/chapter8/templateMethod/.idea/misc.xml b/chapter8/templateMethod/.idea/misc.xml
new file mode 100644
index 0000000..211753f
--- /dev/null
+++ b/chapter8/templateMethod/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter8/templateMethod/.idea/modules.xml b/chapter8/templateMethod/.idea/modules.xml
new file mode 100644
index 0000000..80aa6be
--- /dev/null
+++ b/chapter8/templateMethod/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter8/templateMethod/.idea/vcs.xml b/chapter8/templateMethod/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/chapter8/templateMethod/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter8/templateMethod/src/com/templateMethod/Game.java b/chapter8/templateMethod/src/com/templateMethod/Game.java
new file mode 100644
index 0000000..ce8a0f2
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/Game.java
@@ -0,0 +1,8 @@
+package com.templateMethod;
+
+public class Game {
+ public static void main(String[] args) {
+ GameAI orcAI = new OrcsAI();
+ orcAI.turn();
+ }
+}
diff --git a/chapter8/templateMethod/src/com/templateMethod/GameAI.java b/chapter8/templateMethod/src/com/templateMethod/GameAI.java
new file mode 100644
index 0000000..4f48376
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/GameAI.java
@@ -0,0 +1,56 @@
+package com.templateMethod;
+
+import com.templateMethod.domain.BuildStructure;
+import com.templateMethod.domain.GameMap;
+import com.templateMethod.domain.Player;
+import com.templateMethod.domain.Position;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+public abstract class GameAI {
+
+ protected List playerList = new ArrayList<>();
+ protected GameMap map = new GameMap(5);
+ protected Position position;
+ protected List buildStructures = new ArrayList<>();
+
+ protected void turn() {
+ collectResources();
+ buildStructures();
+ buildUnits();
+ attack();
+ }
+
+ protected void collectResources() {
+ for (BuildStructure structure : buildStructures) {
+ structure.collect();
+ }
+ }
+
+ protected abstract void buildStructures();
+
+ protected abstract void buildUnits();
+
+ protected void attack() {
+ Player enemy = closestEnemy();
+
+ if (enemy == null) {
+ sendScouts(map.getCenter());
+ return;
+ }
+
+ sendWarriors(enemy.getPosition());
+ }
+
+ private Player closestEnemy() {
+ return playerList.stream()
+ .min(Comparator.comparingInt(p -> p.getPosition().calculateDistance(this.position)))
+ .orElse(null);
+ }
+
+ protected abstract void sendScouts(Position position);
+
+ protected abstract void sendWarriors(Position position);
+}
diff --git a/chapter8/templateMethod/src/com/templateMethod/OrcsAI.java b/chapter8/templateMethod/src/com/templateMethod/OrcsAI.java
new file mode 100644
index 0000000..1a7e2ba
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/OrcsAI.java
@@ -0,0 +1,51 @@
+package com.templateMethod;
+
+import com.templateMethod.domain.Player;
+import com.templateMethod.domain.Position;
+import com.templateMethod.domain.unit.Scout;
+import com.templateMethod.domain.unit.Unit;
+import com.templateMethod.domain.unit.Warrior;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class OrcsAI extends GameAI {
+ List scouts = new ArrayList<>();
+ List warriors = new ArrayList<>();
+
+ @Override
+ protected void buildStructures() {
+
+ }
+
+ @Override
+ protected void buildUnits() {
+ if (noScouts()) {
+ scouts.add(new Scout());
+ } else {
+ warriors.add(new Warrior());
+ }
+ }
+
+ @Override
+ protected void sendScouts(Position position) {
+ if (!scouts.isEmpty()) {
+ for(Unit scout : scouts) {
+ scout.move(position);
+ }
+ }
+ }
+
+ @Override
+ protected void sendWarriors(Position position) {
+ if (!warriors.isEmpty()) {
+ for (Unit warrior : warriors) {
+ warrior.move(position);
+ }
+ }
+ }
+
+ private boolean noScouts() {
+ return scouts.isEmpty();
+ }
+}
diff --git a/chapter8/templateMethod/src/com/templateMethod/domain/BuildStructure.java b/chapter8/templateMethod/src/com/templateMethod/domain/BuildStructure.java
new file mode 100644
index 0000000..5e9087c
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/domain/BuildStructure.java
@@ -0,0 +1,6 @@
+package com.templateMethod.domain;
+
+public interface BuildStructure {
+
+ void collect();
+}
diff --git a/chapter8/templateMethod/src/com/templateMethod/domain/GameMap.java b/chapter8/templateMethod/src/com/templateMethod/domain/GameMap.java
new file mode 100644
index 0000000..23cb5c4
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/domain/GameMap.java
@@ -0,0 +1,15 @@
+package com.templateMethod.domain;
+
+public class GameMap {
+ private int[][] map;
+ private Position center;
+
+ public GameMap(int size) {
+ this.map = new int[size][size];
+ this.center = new Position(size / 2, size / 2);
+ }
+
+ public Position getCenter() {
+ return center;
+ }
+}
diff --git a/chapter8/templateMethod/src/com/templateMethod/domain/GasResource.java b/chapter8/templateMethod/src/com/templateMethod/domain/GasResource.java
new file mode 100644
index 0000000..579fa68
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/domain/GasResource.java
@@ -0,0 +1,24 @@
+package com.templateMethod.domain;
+
+public class GasResource implements BuildStructure {
+
+ private static final int PER_RESOURCE = 5;
+ private int resource;
+
+ public GasResource(int resource) {
+ this.resource = resource;
+ }
+
+ @Override
+ public void collect() {
+ if(this.resource == 0) {
+ System.out.println("자원이 고가되었습니다.");
+ return;
+ }
+ this.resource -= PER_RESOURCE;
+
+ if(this.resource <= 0) {
+ this.resource = 0;
+ }
+ }
+}
diff --git a/chapter8/templateMethod/src/com/templateMethod/domain/MineralResource.java b/chapter8/templateMethod/src/com/templateMethod/domain/MineralResource.java
new file mode 100644
index 0000000..f7e84c2
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/domain/MineralResource.java
@@ -0,0 +1,24 @@
+package com.templateMethod.domain;
+
+public class MineralResource implements BuildStructure {
+
+ private static final int PER_RESOURCE = 7;
+ private int resource;
+
+ public MineralResource(int resource) {
+ this.resource = resource;
+ }
+
+ @Override
+ public void collect() {
+ if(this.resource == 0) {
+ System.out.println("자원이 고가되었습니다.");
+ return;
+ }
+ this.resource -= PER_RESOURCE;
+
+ if(this.resource <= 0) {
+ this.resource = 0;
+ }
+ }
+}
diff --git a/chapter8/templateMethod/src/com/templateMethod/domain/Player.java b/chapter8/templateMethod/src/com/templateMethod/domain/Player.java
new file mode 100644
index 0000000..a2b5a0f
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/domain/Player.java
@@ -0,0 +1,13 @@
+package com.templateMethod.domain;
+
+public class Player {
+ private Position position;
+
+ public int calcDistance(Player enemy) {
+ return position.calculateDistance(enemy.position);
+ }
+
+ public Position getPosition() {
+ return position;
+ }
+}
diff --git a/chapter8/templateMethod/src/com/templateMethod/domain/Position.java b/chapter8/templateMethod/src/com/templateMethod/domain/Position.java
new file mode 100644
index 0000000..18d43a9
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/domain/Position.java
@@ -0,0 +1,23 @@
+package com.templateMethod.domain;
+
+public class Position {
+ int x;
+ int y;
+
+ public Position(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public int calculateDistance(Position p) {
+ return (int)Math.sqrt(Math.pow(this.x - p.x, 2) + Math.pow(this.y - p.y, 2));
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+}
diff --git a/chapter8/templateMethod/src/com/templateMethod/domain/unit/Scout.java b/chapter8/templateMethod/src/com/templateMethod/domain/unit/Scout.java
new file mode 100644
index 0000000..eea06f9
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/domain/unit/Scout.java
@@ -0,0 +1,11 @@
+package com.templateMethod.domain.unit;
+
+import com.templateMethod.domain.Position;
+
+public class Scout extends Unit {
+
+ @Override
+ public void move(Position position) {
+ System.out.println(position.getX() + " , " + position.getY() + "로 정찰병이 이동합니다");
+ }
+}
diff --git a/chapter8/templateMethod/src/com/templateMethod/domain/unit/Unit.java b/chapter8/templateMethod/src/com/templateMethod/domain/unit/Unit.java
new file mode 100644
index 0000000..aacef3c
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/domain/unit/Unit.java
@@ -0,0 +1,9 @@
+package com.templateMethod.domain.unit;
+
+import com.templateMethod.domain.Position;
+
+public abstract class Unit {
+ protected Position position;
+
+ public abstract void move(Position position);
+}
diff --git a/chapter8/templateMethod/src/com/templateMethod/domain/unit/Warrior.java b/chapter8/templateMethod/src/com/templateMethod/domain/unit/Warrior.java
new file mode 100644
index 0000000..cf4aa51
--- /dev/null
+++ b/chapter8/templateMethod/src/com/templateMethod/domain/unit/Warrior.java
@@ -0,0 +1,11 @@
+package com.templateMethod.domain.unit;
+
+import com.templateMethod.domain.Position;
+
+public class Warrior extends Unit {
+
+ @Override
+ public void move(Position position) {
+ System.out.println(position.getX() + " , " + position.getY() + "로 전사가 이동합니다");
+ }
+}
diff --git a/chapter8/templateMethod/templateMethod.iml b/chapter8/templateMethod/templateMethod.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/chapter8/templateMethod/templateMethod.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter9/composite/.gitignore b/chapter9/composite/.gitignore
new file mode 100644
index 0000000..f68d109
--- /dev/null
+++ b/chapter9/composite/.gitignore
@@ -0,0 +1,29 @@
+### IntelliJ IDEA ###
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/chapter9/composite/.idea/.gitignore b/chapter9/composite/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/chapter9/composite/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/chapter9/composite/.idea/misc.xml b/chapter9/composite/.idea/misc.xml
new file mode 100644
index 0000000..211753f
--- /dev/null
+++ b/chapter9/composite/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter9/composite/.idea/modules.xml b/chapter9/composite/.idea/modules.xml
new file mode 100644
index 0000000..9b4c39e
--- /dev/null
+++ b/chapter9/composite/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter9/composite/.idea/vcs.xml b/chapter9/composite/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/chapter9/composite/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter9/composite/composite.iml b/chapter9/composite/composite.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/chapter9/composite/composite.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chapter9/composite/src/com/composite/Main.java b/chapter9/composite/src/com/composite/Main.java
new file mode 100644
index 0000000..af15c23
--- /dev/null
+++ b/chapter9/composite/src/com/composite/Main.java
@@ -0,0 +1,23 @@
+package com.composite;
+
+import com.composite.composite.CompoundGraphic;
+import com.composite.composite.GraphicTools;
+import com.composite.domain.Circle;
+import com.composite.domain.Dot;
+
+public class Main {
+ public static void main(String[] args) {
+ CompoundGraphic compoundGraphicA = new CompoundGraphic();
+ compoundGraphicA.add(new Dot(1, 4));
+ compoundGraphicA.add(new Dot(3, 7));
+ compoundGraphicA.add(new Circle(1, 4, 7));
+
+ CompoundGraphic compoundGraphicB = new CompoundGraphic();
+ compoundGraphicB.add(new Dot(3, 5));
+ compoundGraphicB.add(new Dot(2, 6));
+ compoundGraphicB.add(new Circle(3, 10, 12));
+
+ GraphicTools tools = new GraphicTools(compoundGraphicA.getChilds(), compoundGraphicB.getChilds());
+ tools.draw();
+ }
+}
diff --git a/chapter9/composite/src/com/composite/composite/CompoundGraphic.java b/chapter9/composite/src/com/composite/composite/CompoundGraphic.java
new file mode 100644
index 0000000..3153dfe
--- /dev/null
+++ b/chapter9/composite/src/com/composite/composite/CompoundGraphic.java
@@ -0,0 +1,36 @@
+package com.composite.composite;
+
+import com.composite.domain.Graphic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CompoundGraphic implements Graphic {
+ List childs = new ArrayList<>();
+
+ public void add(Graphic child) {
+ childs.add(child);
+ }
+
+ public void remove(Graphic child) {
+ childs.remove(child);
+ }
+
+ @Override
+ public void move(int x, int y) {
+ for(Graphic child : childs) {
+ child.move(x, y);
+ }
+ }
+
+ @Override
+ public void draw() {
+ for(Graphic child : childs) {
+ child.draw();
+ }
+ }
+
+ public List getChilds() {
+ return childs;
+ }
+}
diff --git a/chapter9/composite/src/com/composite/composite/GraphicTools.java b/chapter9/composite/src/com/composite/composite/GraphicTools.java
new file mode 100644
index 0000000..c00fd7f
--- /dev/null
+++ b/chapter9/composite/src/com/composite/composite/GraphicTools.java
@@ -0,0 +1,23 @@
+package com.composite.composite;
+
+import com.composite.domain.Graphic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GraphicTools {
+
+ List compoundGraphic = new ArrayList<>();
+
+ public GraphicTools(List... compoundGraphic) {
+ for (List graphics : compoundGraphic) {
+ this.compoundGraphic.addAll(graphics);
+ }
+ }
+
+ public void draw() {
+ for (Graphic graphic : compoundGraphic) {
+ graphic.draw();
+ }
+ }
+}
diff --git a/chapter9/composite/src/com/composite/domain/Circle.java b/chapter9/composite/src/com/composite/domain/Circle.java
new file mode 100644
index 0000000..6dc6297
--- /dev/null
+++ b/chapter9/composite/src/com/composite/domain/Circle.java
@@ -0,0 +1,16 @@
+package com.composite.domain;
+
+public class Circle extends Dot {
+
+ private int radius;
+
+ public Circle(int x, int y, int radius) {
+ super(x, y);
+ this.radius = radius;
+ }
+
+ @Override
+ public void draw() {
+ System.out.println("중점 [ " + x + ", " + y + "]과 반지름 " + radius + " 를 가진 원 그리기");
+ }
+}
diff --git a/chapter9/composite/src/com/composite/domain/Dot.java b/chapter9/composite/src/com/composite/domain/Dot.java
new file mode 100644
index 0000000..763db1f
--- /dev/null
+++ b/chapter9/composite/src/com/composite/domain/Dot.java
@@ -0,0 +1,25 @@
+package com.composite.domain;
+
+public class Dot implements Graphic {
+
+ protected int x;
+ protected int y;
+
+ public Dot(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ @Override
+ public void move(int x, int y) {
+ System.out.println("점 좌표를 : " + "[ " + x + ", " + y + "] 만큼 이동시킵니다.");
+ this.x += x;
+ this.y += y;
+ }
+
+ @Override
+ public void draw() {
+ System.out.println("== 점 그리기 ==");
+ System.out.println(x + " , " + y);
+ }
+}
diff --git a/chapter9/composite/src/com/composite/domain/Graphic.java b/chapter9/composite/src/com/composite/domain/Graphic.java
new file mode 100644
index 0000000..f7aab79
--- /dev/null
+++ b/chapter9/composite/src/com/composite/domain/Graphic.java
@@ -0,0 +1,7 @@
+package com.composite.domain;
+
+public interface Graphic {
+
+ void move(int x, int y);
+ void draw();
+}
diff --git a/prototype/prototype/prototype/.gitignore b/prototype/prototype/prototype/.gitignore
new file mode 100644
index 0000000..b63da45
--- /dev/null
+++ b/prototype/prototype/prototype/.gitignore
@@ -0,0 +1,42 @@
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/prototype/prototype/prototype/.idea/.gitignore b/prototype/prototype/prototype/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/prototype/prototype/prototype/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/prototype/prototype/prototype/.idea/gradle.xml b/prototype/prototype/prototype/.idea/gradle.xml
new file mode 100644
index 0000000..14746e7
--- /dev/null
+++ b/prototype/prototype/prototype/.idea/gradle.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/prototype/prototype/prototype/.idea/misc.xml b/prototype/prototype/prototype/.idea/misc.xml
new file mode 100644
index 0000000..6a8d183
--- /dev/null
+++ b/prototype/prototype/prototype/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/prototype/prototype/prototype/.idea/vcs.xml b/prototype/prototype/prototype/.idea/vcs.xml
new file mode 100644
index 0000000..c2365ab
--- /dev/null
+++ b/prototype/prototype/prototype/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/prototype/prototype/prototype/build.gradle b/prototype/prototype/prototype/build.gradle
new file mode 100644
index 0000000..d706506
--- /dev/null
+++ b/prototype/prototype/prototype/build.gradle
@@ -0,0 +1,19 @@
+plugins {
+ id 'java'
+}
+
+group = 'com.designpattern'
+version = '1.0-SNAPSHOT'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testImplementation platform('org.junit:junit-bom:5.9.1')
+ testImplementation 'org.junit.jupiter:junit-jupiter'
+}
+
+test {
+ useJUnitPlatform()
+}
\ No newline at end of file
diff --git a/prototype/prototype/prototype/gradle/wrapper/gradle-wrapper.jar b/prototype/prototype/prototype/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..249e583
Binary files /dev/null and b/prototype/prototype/prototype/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/prototype/prototype/prototype/gradle/wrapper/gradle-wrapper.properties b/prototype/prototype/prototype/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..8656f9b
--- /dev/null
+++ b/prototype/prototype/prototype/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sun Jul 30 00:29:02 KST 2023
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/prototype/prototype/prototype/gradlew b/prototype/prototype/prototype/gradlew
new file mode 100755
index 0000000..1b6c787
--- /dev/null
+++ b/prototype/prototype/prototype/gradlew
@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/prototype/prototype/prototype/gradlew.bat b/prototype/prototype/prototype/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/prototype/prototype/prototype/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/prototype/prototype/prototype/settings.gradle b/prototype/prototype/prototype/settings.gradle
new file mode 100644
index 0000000..3aba1d9
--- /dev/null
+++ b/prototype/prototype/prototype/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'prototype'
+
diff --git a/prototype/prototype/prototype/src/main/java/com/prototype/Circle.java b/prototype/prototype/prototype/src/main/java/com/prototype/Circle.java
new file mode 100644
index 0000000..17f4250
--- /dev/null
+++ b/prototype/prototype/prototype/src/main/java/com/prototype/Circle.java
@@ -0,0 +1,33 @@
+package com.prototype;
+
+import java.util.Objects;
+
+public class Circle extends Shape {
+ private int radius;
+
+ public Circle(int x, int y, String color, int radius) {
+ super(x, y, color);
+ this.radius = radius;
+ }
+
+ public Circle(Circle target) {
+ super(target);
+ if (target != null) {
+ this.radius = target.radius;
+ }
+ }
+
+ @Override
+ public Shape clone() {
+ return new Circle(this);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+ Circle circle = (Circle) o;
+ return radius == circle.radius;
+ }
+}
diff --git a/prototype/prototype/prototype/src/main/java/com/prototype/Main.java b/prototype/prototype/prototype/src/main/java/com/prototype/Main.java
new file mode 100644
index 0000000..7f9d9d8
--- /dev/null
+++ b/prototype/prototype/prototype/src/main/java/com/prototype/Main.java
@@ -0,0 +1,42 @@
+package com.prototype;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Main {
+ public static void main(String[] args) {
+ List shapes = new ArrayList<>();
+ List shapesCopy = new ArrayList<>();
+
+ Circle circle = new Circle(10, 20, "red", 15);
+ shapes.add(circle);
+
+ Circle copyCircle = (Circle) circle.clone();
+ shapesCopy.add(copyCircle);
+
+ Rectangle rectangle = new Rectangle(0, 0, "blue", 10, 20);
+ shapes.add(rectangle);
+
+ Rectangle copyRectangle = (Rectangle) rectangle.clone();
+ copyRectangle.changeWidth(30);
+ shapesCopy.add(copyRectangle);
+
+ compare(shapes, shapesCopy);
+ }
+
+ private static void compare(List shapes, List shapesCopy) {
+
+ 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!)");
+ }
+ }
+ }
+}
diff --git a/prototype/prototype/prototype/src/main/java/com/prototype/Rectangle.java b/prototype/prototype/prototype/src/main/java/com/prototype/Rectangle.java
new file mode 100644
index 0000000..b0d3760
--- /dev/null
+++ b/prototype/prototype/prototype/src/main/java/com/prototype/Rectangle.java
@@ -0,0 +1,39 @@
+package com.prototype;
+
+
+public class Rectangle extends Shape {
+ private int width;
+ private int height;
+
+ public Rectangle(int x, int y, String color, int width, int height) {
+ super(x, y, color);
+ this.width = width;
+ this.height = 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 boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+ Rectangle rectangle = (Rectangle) o;
+ return width == rectangle.width && height == rectangle.height;
+ }
+
+ public void changeWidth(int width) {
+ this.width = width;
+ }
+}
diff --git a/prototype/prototype/prototype/src/main/java/com/prototype/Shape.java b/prototype/prototype/prototype/src/main/java/com/prototype/Shape.java
new file mode 100644
index 0000000..e1d17b7
--- /dev/null
+++ b/prototype/prototype/prototype/src/main/java/com/prototype/Shape.java
@@ -0,0 +1,33 @@
+package com.prototype;
+
+import java.util.Objects;
+
+public abstract class Shape {
+ private int x;
+ private int y;
+ private String color;
+
+ public Shape(int x, int y, String color) {
+ this.x = x;
+ this.y = y;
+ this.color = color;
+ }
+
+ public Shape(Shape target) {
+ if (target != null) {
+ this.x = target.x;
+ this.y = target.y;
+ this.color = target.color;
+ }
+ }
+
+ public abstract Shape clone();
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Shape shape = (Shape) o;
+ return x == shape.x && y == shape.y && Objects.equals(color, shape.color);
+ }
+}