diff --git a/AbstractFactory-And-Singleton/src/App.java b/AbstractFactory-And-Singleton/src/App.java new file mode 100644 index 0000000..a13f163 --- /dev/null +++ b/AbstractFactory-And-Singleton/src/App.java @@ -0,0 +1,19 @@ +import button.Button; +import checkbox.Checkbox; +import factory.GUIFactory; + +public class App { + + private Button button; + private Checkbox checkbox; + + public App(GUIFactory factory) { + this.button = factory.createButton(); + this.checkbox = factory.createCheckbox(); + } + + public void paint() { + button.paint(); + checkbox.paint(); + } +} diff --git a/AbstractFactory-And-Singleton/src/Main.java b/AbstractFactory-And-Singleton/src/Main.java new file mode 100644 index 0000000..cce890a --- /dev/null +++ b/AbstractFactory-And-Singleton/src/Main.java @@ -0,0 +1,44 @@ +import factory.GUIFactory; +import factory.MacOSFactory; +import factory.WindowsFactory; +import java.util.Scanner; + +public class Main { + + private static GUIFactory macOSFactory = new MacOSFactory(); + private static GUIFactory windowsFactory = new WindowsFactory(); + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + String osKorean = scanner.nextLine(); + GUIFactory guiFactory = getOS(osKorean); + if (!validOS(guiFactory)) { + return; + } + + App app = new App(guiFactory); + app.paint(); + + scanner.close(); + } + + private static boolean validOS(GUIFactory guiFactory) { + if (guiFactory == null) { + System.out.println("그런 OS는 존재하지 않습니다."); + return false; + } + return true; + } + + private static GUIFactory getOS(String osKorean) { + switch (osKorean) { + case "맥": + return macOSFactory; + case "윈도우": + return windowsFactory; + default: + return null; + } + } +} \ No newline at end of file diff --git a/AbstractFactory-And-Singleton/src/button/Button.java b/AbstractFactory-And-Singleton/src/button/Button.java new file mode 100644 index 0000000..79ca518 --- /dev/null +++ b/AbstractFactory-And-Singleton/src/button/Button.java @@ -0,0 +1,5 @@ +package button; + +public interface Button { + void paint(); +} diff --git a/AbstractFactory-And-Singleton/src/button/MacOSButton.java b/AbstractFactory-And-Singleton/src/button/MacOSButton.java new file mode 100644 index 0000000..fd76b8c --- /dev/null +++ b/AbstractFactory-And-Singleton/src/button/MacOSButton.java @@ -0,0 +1,9 @@ +package button; + +public class MacOSButton implements Button { + + @Override + public void paint() { + System.out.println("[맥 마우스] 생성됨"); + } +} diff --git a/AbstractFactory-And-Singleton/src/button/WindowButton.java b/AbstractFactory-And-Singleton/src/button/WindowButton.java new file mode 100644 index 0000000..36a3481 --- /dev/null +++ b/AbstractFactory-And-Singleton/src/button/WindowButton.java @@ -0,0 +1,9 @@ +package button; + +public class WindowButton implements Button { + + @Override + public void paint() { + System.out.println("[윈도우 버튼] 생성됨"); + } +} diff --git a/AbstractFactory-And-Singleton/src/checkbox/Checkbox.java b/AbstractFactory-And-Singleton/src/checkbox/Checkbox.java new file mode 100644 index 0000000..2cfd85e --- /dev/null +++ b/AbstractFactory-And-Singleton/src/checkbox/Checkbox.java @@ -0,0 +1,6 @@ +package checkbox; + +public interface Checkbox { + + void paint(); +} diff --git a/AbstractFactory-And-Singleton/src/checkbox/MacOSCheckbox.java b/AbstractFactory-And-Singleton/src/checkbox/MacOSCheckbox.java new file mode 100644 index 0000000..8387814 --- /dev/null +++ b/AbstractFactory-And-Singleton/src/checkbox/MacOSCheckbox.java @@ -0,0 +1,9 @@ +package checkbox; + +public class MacOSCheckbox implements Checkbox { + + @Override + public void paint() { + System.out.println("[맥 체크박스] 생성됨"); + } +} diff --git a/AbstractFactory-And-Singleton/src/checkbox/WindowCheckbox.java b/AbstractFactory-And-Singleton/src/checkbox/WindowCheckbox.java new file mode 100644 index 0000000..622e916 --- /dev/null +++ b/AbstractFactory-And-Singleton/src/checkbox/WindowCheckbox.java @@ -0,0 +1,9 @@ +package checkbox; + +public class WindowCheckbox implements Checkbox { + + @Override + public void paint() { + System.out.println("[윈도우 체크박스] 생성됨"); + } +} diff --git a/AbstractFactory-And-Singleton/src/factory/GUIFactory.java b/AbstractFactory-And-Singleton/src/factory/GUIFactory.java new file mode 100644 index 0000000..e7aaa39 --- /dev/null +++ b/AbstractFactory-And-Singleton/src/factory/GUIFactory.java @@ -0,0 +1,11 @@ +package factory; + +import checkbox.Checkbox; +import button.Button; + +public interface GUIFactory { + + Button createButton(); + + Checkbox createCheckbox(); +} diff --git a/AbstractFactory-And-Singleton/src/factory/MacOSFactory.java b/AbstractFactory-And-Singleton/src/factory/MacOSFactory.java new file mode 100644 index 0000000..2cea052 --- /dev/null +++ b/AbstractFactory-And-Singleton/src/factory/MacOSFactory.java @@ -0,0 +1,19 @@ +package factory; + +import button.MacOSButton; +import checkbox.Checkbox; +import button.Button; +import checkbox.MacOSCheckbox; + +public class MacOSFactory implements GUIFactory { + + @Override + public Button createButton() { + return new MacOSButton(); + } + + @Override + public Checkbox createCheckbox() { + return new MacOSCheckbox(); + } +} diff --git a/AbstractFactory-And-Singleton/src/factory/WindowsFactory.java b/AbstractFactory-And-Singleton/src/factory/WindowsFactory.java new file mode 100644 index 0000000..fbda283 --- /dev/null +++ b/AbstractFactory-And-Singleton/src/factory/WindowsFactory.java @@ -0,0 +1,19 @@ +package factory; + +import button.WindowButton; +import checkbox.Checkbox; +import button.Button; +import checkbox.WindowCheckbox; + +public class WindowsFactory implements GUIFactory { + + @Override + public Button createButton() { + return new WindowButton(); + } + + @Override + public Checkbox createCheckbox() { + return new WindowCheckbox(); + } +} diff --git a/Adapterpattern/src/Main.java b/Adapterpattern/src/Main.java new file mode 100644 index 0000000..0415d7d --- /dev/null +++ b/Adapterpattern/src/Main.java @@ -0,0 +1,24 @@ +public class Main { + + public static void main(String[] args) { + RoundHole roundHole = new RoundHole(5); + RoundPeg roundPeg = new RoundPeg(5); + if (roundHole.fits(roundPeg)) { + System.out.println("roundPeg가 들어갈 수 있습니다."); + } + + SquarePeg smallSqPeg = new SquarePeg(2); + SquarePeg largeSqPeg = new SquarePeg(20); + + SquarePegAdapter smallPeg = new SquarePegAdapter(smallSqPeg); + SquarePegAdapter largePeg = new SquarePegAdapter(largeSqPeg); +// roundHole.fits(smallSqPeg); +// roundHole.fits(largeSqPeg); + if (roundHole.fits(smallPeg)) { + System.out.println("smallPeg가 들어갈 수 있습니다."); + } + if (roundHole.fits(largePeg)) { + System.out.println("largePeg가 들어갈 수 있습니다."); + } + } +} \ No newline at end of file diff --git a/Adapterpattern/src/RoundHole.java b/Adapterpattern/src/RoundHole.java new file mode 100644 index 0000000..e4db28c --- /dev/null +++ b/Adapterpattern/src/RoundHole.java @@ -0,0 +1,15 @@ +public class RoundHole { + private double radius; + + public RoundHole(double radius) { + this.radius = radius; + } + + public double getRadius() { + return radius; + } + + public boolean fits(RoundPeg peg) { + return radius >= peg.getRadius(); + } +} diff --git a/Adapterpattern/src/RoundPeg.java b/Adapterpattern/src/RoundPeg.java new file mode 100644 index 0000000..3b2887e --- /dev/null +++ b/Adapterpattern/src/RoundPeg.java @@ -0,0 +1,15 @@ +public class RoundPeg { + + private double radius; + + public RoundPeg() { + } + + public RoundPeg(double radius) { + this.radius = radius; + } + + public double getRadius() { + return radius; + } +} diff --git a/Adapterpattern/src/SquarePeg.java b/Adapterpattern/src/SquarePeg.java new file mode 100644 index 0000000..74ec348 --- /dev/null +++ b/Adapterpattern/src/SquarePeg.java @@ -0,0 +1,15 @@ +public class SquarePeg { + private double width; + + public SquarePeg(double width) { + this.width = width; + } + + public double getWidth() { + return width; + } + + public double getSquare() { + return Math.pow(width, 2); + } +} diff --git a/Adapterpattern/src/SquarePegAdapter.java b/Adapterpattern/src/SquarePegAdapter.java new file mode 100644 index 0000000..dda672d --- /dev/null +++ b/Adapterpattern/src/SquarePegAdapter.java @@ -0,0 +1,14 @@ +public class SquarePegAdapter extends RoundPeg { + + private SquarePeg peg; + + public SquarePegAdapter(SquarePeg peg) { + this.peg = peg; + } + + @Override + public double getRadius() { + return Math.sqrt( + Math.pow(peg.getWidth() / 2, 2) * 2); + } +} diff --git a/chapter8,9/compositepattern/src/Demo.java b/chapter8,9/compositepattern/src/Demo.java new file mode 100644 index 0000000..8d1ac11 --- /dev/null +++ b/chapter8,9/compositepattern/src/Demo.java @@ -0,0 +1,28 @@ +import editor.ImageEditor; +import shapes.Circle; +import shapes.CompoundShape; +import shapes.Dot; +import shapes.Rectangle; + +public class Demo { + public static void main(String[] args) { + ImageEditor editor = new ImageEditor(); + + editor.loadShapes( + new Circle(10, 10, 10), + + new CompoundShape( + new Circle(110, 110, 50), + new Dot(160, 160) + ), + + new CompoundShape( + new Rectangle(250, 250, 100, 100), + new Dot(240, 240), + new Dot(240, 360), + new Dot(360, 360), + new Dot(360, 240) + ) + ); + } +} diff --git a/chapter8,9/compositepattern/src/editor/ImageEditor.java b/chapter8,9/compositepattern/src/editor/ImageEditor.java new file mode 100644 index 0000000..271c637 --- /dev/null +++ b/chapter8,9/compositepattern/src/editor/ImageEditor.java @@ -0,0 +1,18 @@ +package editor; + +import shapes.BaseShape; +import shapes.CompoundShape; + +public class ImageEditor { + private CompoundShape allShapes = new CompoundShape(); + + public void loadShapes(BaseShape... shapes) { + allShapes.clear(); + allShapes.add(shapes); + printCanvas(); + } + + private void printCanvas() { + allShapes.print(); + } +} diff --git a/chapter8,9/compositepattern/src/shapes/BaseShape.java b/chapter8,9/compositepattern/src/shapes/BaseShape.java new file mode 100644 index 0000000..978ae75 --- /dev/null +++ b/chapter8,9/compositepattern/src/shapes/BaseShape.java @@ -0,0 +1,39 @@ +package shapes; + +import java.awt.Graphics; + +public abstract class BaseShape implements Shape { + + private int x; + private int y; + + BaseShape(int x, int y) { + this.x = x; + this.y = y; + + } + + @Override + public int getX() { + return x; + } + + @Override + public int getY() { + return y; + } + + public void print() { + System.out.println(this.getClass().getSimpleName() + ": Position -> (" + getX() + "," + getY() + "), Dimensions -> (" + getWidth() + "," + getHeight() + ")"); + } + protected void print(int depth) { + printTab(depth); + print(); + } + + protected void printTab(int depth) { + for(int i = 0; i < depth; i++) { + System.out.print("\t"); + } + } +} diff --git a/chapter8,9/compositepattern/src/shapes/Circle.java b/chapter8,9/compositepattern/src/shapes/Circle.java new file mode 100644 index 0000000..1ec80ff --- /dev/null +++ b/chapter8,9/compositepattern/src/shapes/Circle.java @@ -0,0 +1,21 @@ +package shapes; + +public class Circle extends BaseShape{ + + private final int radius; + + public Circle(int x, int y, int radius) { + super(x, y); + this.radius = radius; + } + + @Override + public int getWidth() { + return radius * 2; + } + + @Override + public int getHeight() { + return radius * 2; + } +} diff --git a/chapter8,9/compositepattern/src/shapes/CompoundShape.java b/chapter8,9/compositepattern/src/shapes/CompoundShape.java new file mode 100644 index 0000000..8f415da --- /dev/null +++ b/chapter8,9/compositepattern/src/shapes/CompoundShape.java @@ -0,0 +1,52 @@ +package shapes; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CompoundShape extends BaseShape { + protected final List children; + + public CompoundShape() { + super(0, 0); + children = new ArrayList<>(); + } + + public CompoundShape(BaseShape... components) { + super(0, 0); + children = new ArrayList<>(); + add(components); + } + + @Override + public int getWidth() { + return 0; + } + + @Override + public int getHeight() { + return 0; + } + + @Override + public void print() { + print(0); + } + + public void add(BaseShape... components) { + children.addAll(Arrays.asList(components)); + } + + public void clear() { + children.clear(); + } + + @Override + protected void print(int depth) { + printTab(depth); + System.out.println("CompoundShape"); + for (BaseShape child : children) { + child.print(depth + 1); + } + } +} diff --git a/chapter8,9/compositepattern/src/shapes/Dot.java b/chapter8,9/compositepattern/src/shapes/Dot.java new file mode 100644 index 0000000..6b56ae3 --- /dev/null +++ b/chapter8,9/compositepattern/src/shapes/Dot.java @@ -0,0 +1,23 @@ +package shapes; + +import java.awt.Color; +import java.awt.Graphics; + +public class Dot extends BaseShape { + + private final int DOT_SIZE = 3; + + public Dot(int x, int y) { + super(x, y); + } + + @Override + public int getWidth() { + return DOT_SIZE; + } + + @Override + public int getHeight() { + return DOT_SIZE; + } +} diff --git a/chapter8,9/compositepattern/src/shapes/Rectangle.java b/chapter8,9/compositepattern/src/shapes/Rectangle.java new file mode 100644 index 0000000..434ee3f --- /dev/null +++ b/chapter8,9/compositepattern/src/shapes/Rectangle.java @@ -0,0 +1,23 @@ +package shapes; + +public class Rectangle extends BaseShape{ + + private final int width; + private final int height; + + public Rectangle(int x, int y, int width, int height) { + super(x, y); + this.width = width; + this.height = height; + } + + @Override + public int getWidth() { + return width; + } + + @Override + public int getHeight() { + return height; + } +} diff --git a/chapter8,9/compositepattern/src/shapes/Shape.java b/chapter8,9/compositepattern/src/shapes/Shape.java new file mode 100644 index 0000000..54a7007 --- /dev/null +++ b/chapter8,9/compositepattern/src/shapes/Shape.java @@ -0,0 +1,12 @@ +package shapes; + +import java.awt.Graphics; + +public interface Shape { + int getX(); + int getY(); + int getWidth(); + int getHeight(); + + void print(); +} diff --git a/chapter8,9/iteratorpattern/src/Demo.java b/chapter8,9/iteratorpattern/src/Demo.java new file mode 100644 index 0000000..f1e4ded --- /dev/null +++ b/chapter8,9/iteratorpattern/src/Demo.java @@ -0,0 +1,50 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; +import profile.Profile; +import social_networks.Facebook; +import social_networks.LinkedIn; +import social_networks.SocialNetwork; +import spammer.SocialSpammer; + +public class Demo { + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + System.out.println("Please specify social network to target spam tool (default:Facebook):"); + System.out.println("1. Facebook"); + System.out.println("2. LinkedIn"); + String choice = scanner.nextLine(); + + SocialNetwork network = getNetwork(choice); + + SocialSpammer spammer = new SocialSpammer(network); + spammer.sendSpamToFriends("anna.smith@bing.com", + "Hey! This is Anna's friend Josh. Can you do me a favor and like this post [link]?"); + spammer.sendSpamToCoworkers("anna.smith@bing.com", + "Hey! This is Anna's boss Jason. Anna told me you would be interested in [link]."); + } + + private static SocialNetwork getNetwork(String choice) { + switch (choice) { + case "1": + return new Facebook(generateTestProfiles()); + case "2": + return new LinkedIn(generateTestProfiles()); + default: + throw new IllegalArgumentException("구현되지 않은 메뉴입니다: " + choice); + } + } + + private static List generateTestProfiles() { + List data = new ArrayList<>(); + data.add(new Profile("anna.smith@bing.com", "Anna Smith", "friends:mad_max@ya.com", "friends:catwoman@yahoo.com", "coworkers:sam@amazon.com")); + data.add(new Profile("mad_max@ya.com", "Maximilian", "friends:anna.smith@bing.com", "coworkers:sam@amazon.com")); + data.add(new Profile("bill@microsoft.eu", "Billie", "coworkers:avanger@ukr.net")); + data.add(new Profile("avanger@ukr.net", "John Day", "coworkers:bill@microsoft.eu")); + data.add(new Profile("sam@amazon.com", "Sam Kitting", "coworkers:anna.smith@bing.com", "coworkers:mad_max@ya.com", "friends:catwoman@yahoo.com")); + data.add(new Profile("catwoman@yahoo.com", "Liza", "friends:anna.smith@bing.com", "friends:sam@amazon.com")); + return data; + } +} diff --git a/chapter8,9/iteratorpattern/src/iterators/FacebookIterator.java b/chapter8,9/iteratorpattern/src/iterators/FacebookIterator.java new file mode 100644 index 0000000..181d69a --- /dev/null +++ b/chapter8,9/iteratorpattern/src/iterators/FacebookIterator.java @@ -0,0 +1,68 @@ +package iterators; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import profile.Profile; +import social_networks.Facebook; + +public class FacebookIterator implements ProfileIterator { + + private final Facebook facebook; + private final String type; + private final String email; + private List emails; + private List profiles; + + private int currentPosition; + + public FacebookIterator(Facebook facebook, String type, String email) { + this.facebook = facebook; + this.type = type; + this.email = email; + + emails = Collections.emptyList(); + profiles = Collections.emptyList(); + + currentPosition = 0; + } + + @Override + public boolean hasNext() { + lazyLoad(); + return currentPosition < emails.size(); + } + + @Override + public Profile getNext() { + if (!hasNext()) { + return null; + } + + String obtainedEmail = emails.get(currentPosition); + Profile obtainedProfile = profiles.get(currentPosition); + if (obtainedProfile == null) { + obtainedProfile = facebook.requestProfile(obtainedEmail); + profiles.set(currentPosition, obtainedProfile); + } + currentPosition++; + return obtainedProfile; + } + + @Override + public void reset() { + currentPosition = 0; + } + + private void lazyLoad() { + if (emails == Collections.EMPTY_LIST) { + emails = new ArrayList<>(); + profiles = new ArrayList<>(); + List requestedProfiles = facebook.requestProfiles(this.email, this.type); + for (String requestedProfile : requestedProfiles) { + emails.add(requestedProfile); + profiles.add(null); + } + } + } +} diff --git a/chapter8,9/iteratorpattern/src/iterators/LinkedInIterator.java b/chapter8,9/iteratorpattern/src/iterators/LinkedInIterator.java new file mode 100644 index 0000000..53a0186 --- /dev/null +++ b/chapter8,9/iteratorpattern/src/iterators/LinkedInIterator.java @@ -0,0 +1,68 @@ +package iterators; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import profile.Profile; +import social_networks.Facebook; +import social_networks.LinkedIn; + +public class LinkedInIterator implements ProfileIterator { + + private final LinkedIn linkedIn; + private final String type; + private final String email; + private List emails; + private List profiles; + + private int currentPosition; + public LinkedInIterator(LinkedIn linkedIn, String type, String email) { + this.linkedIn = linkedIn; + this.type = type; + this.email = email; + + emails = Collections.emptyList(); + profiles = Collections.emptyList(); + + currentPosition = 0; + } + + @Override + public boolean hasNext() { + lazyLoad(); + return currentPosition < emails.size(); + } + + @Override + public Profile getNext() { + if (!hasNext()) { + return null; + } + + String obtainedEmail = emails.get(currentPosition); + Profile obtainedProfile = profiles.get(currentPosition); + if (obtainedProfile == null) { + obtainedProfile = linkedIn.requestProfile(obtainedEmail); + profiles.set(currentPosition, obtainedProfile); + } + currentPosition++; + return obtainedProfile; + } + + @Override + public void reset() { + currentPosition = 0; + } + + private void lazyLoad() { + if (emails == Collections.EMPTY_LIST) { + emails = new ArrayList<>(); + profiles = new ArrayList<>(); + List requestedProfiles = linkedIn.requestProfiles(this.email, this.type); + for (String requestedProfile : requestedProfiles) { + emails.add(requestedProfile); + profiles.add(null); + } + } + } +} diff --git a/chapter8,9/iteratorpattern/src/iterators/ProfileIterator.java b/chapter8,9/iteratorpattern/src/iterators/ProfileIterator.java new file mode 100644 index 0000000..2929634 --- /dev/null +++ b/chapter8,9/iteratorpattern/src/iterators/ProfileIterator.java @@ -0,0 +1,12 @@ +package iterators; + +import profile.Profile; + +public interface ProfileIterator { + + boolean hasNext(); + + Profile getNext(); + + void reset(); +} diff --git a/chapter8,9/iteratorpattern/src/profile/Profile.java b/chapter8,9/iteratorpattern/src/profile/Profile.java new file mode 100644 index 0000000..36b76c1 --- /dev/null +++ b/chapter8,9/iteratorpattern/src/profile/Profile.java @@ -0,0 +1,57 @@ +package profile; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Profile { + private final String name; + private final String email; + private final Map> contacts; + + public Profile(String email, String name, String... contacts) { + this.email = email; + this.name = name; + this.contacts = new HashMap<>(); + + addContacts(contacts); + } + + private void addContacts(String[] contacts) { + for (String contact : contacts) { + addContact(contact); + } + } + + private void addContact(String contact) { + String[] parts = contact.split(":"); + + String contactType = "friend"; + String contactEmail = parts[0]; + if (parts.length != 1) { + contactType = parts[0]; + contactEmail = parts[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 (!contacts.containsKey(contactType)) { + this.contacts.put(contactType, new ArrayList<>()); + } + return contacts.get(contactType); + } +} diff --git a/chapter8,9/iteratorpattern/src/social_networks/Facebook.java b/chapter8,9/iteratorpattern/src/social_networks/Facebook.java new file mode 100644 index 0000000..1beb89d --- /dev/null +++ b/chapter8,9/iteratorpattern/src/social_networks/Facebook.java @@ -0,0 +1,63 @@ +package social_networks; + +import iterators.FacebookIterator; +import iterators.ProfileIterator; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import profile.Profile; + +public class Facebook implements SocialNetwork { + + private final List profiles; + + public Facebook(List cache) { + this.profiles = Objects.requireNonNullElseGet(cache, ArrayList::new); + } + + @Override + public ProfileIterator createFriendsIterator(String profileEmail) { + return new FacebookIterator(this, "friends", profileEmail); + } + + @Override + public ProfileIterator createCoworkersIterator(String profileEmail) { + return new FacebookIterator(this, "coworkers", profileEmail); + } + + public List requestProfiles(String profileEmail, String contactType) { + simulateNetworkLatency(); + 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; + } + + public Profile requestProfile(String profileEmail) { + simulateNetworkLatency(); + System.out.println("Facebook: Loading profile '" + profileEmail + "' over the network..."); + + return findProfile(profileEmail); + } + + private void simulateNetworkLatency() { + try { + Thread.sleep(2500); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + + private Profile findProfile(String profileEmail) { + for (Profile profile : profiles) { + if (Objects.equals(profile.getEmail(), profileEmail)) { + return profile; + } + } + return null; + } +} diff --git a/chapter8,9/iteratorpattern/src/social_networks/LinkedIn.java b/chapter8,9/iteratorpattern/src/social_networks/LinkedIn.java new file mode 100644 index 0000000..801bd44 --- /dev/null +++ b/chapter8,9/iteratorpattern/src/social_networks/LinkedIn.java @@ -0,0 +1,63 @@ +package social_networks; + +import iterators.LinkedInIterator; +import iterators.ProfileIterator; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import profile.Profile; + +public class LinkedIn implements SocialNetwork { + + private final List profiles; + + public LinkedIn(List cache) { + this.profiles = Objects.requireNonNullElseGet(cache, ArrayList::new); + } + + @Override + public ProfileIterator createFriendsIterator(String profileEmail) { + return new LinkedInIterator(this, "friends", profileEmail); + } + + @Override + public ProfileIterator createCoworkersIterator(String profileEmail) { + return new LinkedInIterator(this, "coworkers", profileEmail); + } + + public List requestProfiles(String profileEmail, String contactType) { + simulateNetworkLatency(); + System.out.println("LinkedIn: Loading '" + contactType + "' list of '" + profileEmail + + "' over the network..."); + + Profile profile = findProfile(profileEmail); + if (profile != null) { + return profile.getContacts(contactType); + } + return null; + } + + public Profile requestProfile(String profileEmail) { + simulateNetworkLatency(); + System.out.println("LinkedIn: Loading profile '" + profileEmail + "' over the network..."); + + return findProfile(profileEmail); + } + + private void simulateNetworkLatency() { + try { + Thread.sleep(2500); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + + private Profile findProfile(String profileEmail) { + for (Profile profile : profiles) { + if (Objects.equals(profile.getEmail(), profileEmail)) { + return profile; + } + } + return null; + } +} diff --git a/chapter8,9/iteratorpattern/src/social_networks/SocialNetwork.java b/chapter8,9/iteratorpattern/src/social_networks/SocialNetwork.java new file mode 100644 index 0000000..8c9e8ea --- /dev/null +++ b/chapter8,9/iteratorpattern/src/social_networks/SocialNetwork.java @@ -0,0 +1,9 @@ +package social_networks; + +import iterators.ProfileIterator; + +public interface SocialNetwork { + + ProfileIterator createFriendsIterator(String profileEmail); + ProfileIterator createCoworkersIterator(String profileEmail); +} diff --git a/chapter8,9/iteratorpattern/src/spammer/SocialSpammer.java b/chapter8,9/iteratorpattern/src/spammer/SocialSpammer.java new file mode 100644 index 0000000..b7aa36a --- /dev/null +++ b/chapter8,9/iteratorpattern/src/spammer/SocialSpammer.java @@ -0,0 +1,35 @@ +package spammer; + +import iterators.ProfileIterator; +import profile.Profile; +import social_networks.SocialNetwork; + +public class SocialSpammer { + public SocialNetwork network; + + public SocialSpammer(SocialNetwork network) { + this.network = network; + } + + public void sendSpamToFriends(String profileEmail, String message) { + System.out.println("\nIterating over friends...\n"); + ProfileIterator iterator = network.createFriendsIterator(profileEmail); + while (iterator.hasNext()) { + Profile profile = iterator.getNext(); + sendMessage(profile.getEmail(), message); + } + } + + public void sendSpamToCoworkers(String profileEmail, String message) { + System.out.println("\nIterating over coworkers...\n"); + ProfileIterator iterator = network.createCoworkersIterator(profileEmail); + while (iterator.hasNext()) { + Profile profile = iterator.getNext(); + sendMessage(profile.getEmail(), message); + } + } + + public void sendMessage(String email, String message) { + System.out.println("Sent message to: '" + email + "'. Message body: '" + message + "'"); + } +} diff --git a/chapter8,9/templatemethodpattern/src/Demo.java b/chapter8,9/templatemethodpattern/src/Demo.java new file mode 100644 index 0000000..de4c9ae --- /dev/null +++ b/chapter8,9/templatemethodpattern/src/Demo.java @@ -0,0 +1,40 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import networks.FaceBook; +import networks.Network; +import networks.Twitter; + +public class Demo { + + public static void main(String[] args) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + System.out.print("Input user name: "); + String userName = reader.readLine(); + System.out.print("Input password: "); + String password = reader.readLine(); + + // Enter the message. + System.out.print("Input message: "); + String message = reader.readLine(); + + System.out.println("\nChoose social network for posting message.\n" + + "1 - Facebook\n" + + "2 - Twitter"); + int choice = Integer.parseInt(reader.readLine()); + + Network network = getNetwork(choice); + network.post(message, userName, password); + } + + private static Network getNetwork(int choice) { + switch (choice) { + case 1: + return new FaceBook(); + case 2: + return new Twitter(); + default: + throw new IllegalArgumentException("존재하지 않는 번호입니다: " + choice); + } + } +} diff --git a/chapter8,9/templatemethodpattern/src/networks/FaceBook.java b/chapter8,9/templatemethodpattern/src/networks/FaceBook.java new file mode 100644 index 0000000..2e0feb5 --- /dev/null +++ b/chapter8,9/templatemethodpattern/src/networks/FaceBook.java @@ -0,0 +1,42 @@ +package networks; + +public class FaceBook extends Network { + + @Override + protected boolean logIn(String userName, String password) { + System.out.println("\nChecking user's parameters"); + System.out.println("Name: " + userName); + System.out.print("Password: "); + for (int i = 0; i < password.length(); i++) { + System.out.print("*"); + } + simulateNetworkLatency(); + System.out.println("\n\nLogIn success on Facebook"); + return true; + } + + @Override + protected boolean sendData(byte[] data) { + System.out.println("Message: '" + new String(data) + "' was posted on Facebook"); + return true; + } + + @Override + protected void logOut(String userName) { + System.out.println("User: '" + userName + "' was logged out from Facebook"); + } + + private void simulateNetworkLatency() { + try { + int i = 0; + System.out.println(); + while (i < 10) { + System.out.print("."); + Thread.sleep(500); + i++; + } + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } +} diff --git a/chapter8,9/templatemethodpattern/src/networks/Network.java b/chapter8,9/templatemethodpattern/src/networks/Network.java new file mode 100644 index 0000000..36b073b --- /dev/null +++ b/chapter8,9/templatemethodpattern/src/networks/Network.java @@ -0,0 +1,19 @@ +package networks; + +public abstract class Network { + + public boolean post(String message, String userName, String password) { + if (logIn(userName, password)) { + boolean result = sendData(message.getBytes()); + logOut(userName); + return result; + } + return false; + } + + protected abstract boolean logIn(String userName, String password); + + protected abstract boolean sendData(byte[] data); + + protected abstract void logOut(String userName); +} diff --git a/chapter8,9/templatemethodpattern/src/networks/Twitter.java b/chapter8,9/templatemethodpattern/src/networks/Twitter.java new file mode 100644 index 0000000..f5a0410 --- /dev/null +++ b/chapter8,9/templatemethodpattern/src/networks/Twitter.java @@ -0,0 +1,42 @@ +package networks; + +public class Twitter extends Network{ + + @Override + protected boolean logIn(String userName, String password) { + System.out.println("\nChecking user's parameters"); + System.out.println("Name: " + userName); + System.out.print("Password: "); + for (int i = 0; i < password.length(); i++) { + System.out.print("*"); + } + simulateNetworkLatency(); + System.out.println("\n\nLogIn success on Twitter"); + return true; + } + + @Override + protected boolean sendData(byte[] data) { + System.out.println("Message: '" + new String(data) + "' was posted on Twitter"); + return true; + } + + @Override + protected void logOut(String userName) { + System.out.println("User: '" + userName + "' was logged out from Twitter"); + } + + private void simulateNetworkLatency() { + try { + int i = 0; + System.out.println(); + while (i < 10) { + System.out.print("."); + Thread.sleep(500); + i++; + } + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } +} diff --git a/commandpattern/src/Command.java b/commandpattern/src/Command.java new file mode 100644 index 0000000..0a485e5 --- /dev/null +++ b/commandpattern/src/Command.java @@ -0,0 +1,22 @@ +public abstract class Command { + + protected String name = "abstract"; + protected final Editor editor; + protected String backup; + + public Command(Editor editor) { + this.editor = editor; + } + + public String getName() { + return name; + } + + public abstract boolean execute(); + + public abstract void undo(); + + protected void backup() { + backup = editor.text.toString(); + } +} diff --git a/commandpattern/src/CommandHistory.java b/commandpattern/src/CommandHistory.java new file mode 100644 index 0000000..3736577 --- /dev/null +++ b/commandpattern/src/CommandHistory.java @@ -0,0 +1,22 @@ +import java.util.Stack; + +public class CommandHistory { + + private final Stack history = new Stack<>(); + + public void push(Command command) { + history.push(command); + } + + public Command pop() { + return history.pop(); + } + + public Command peek() { + return history.peek(); + } + + public boolean isEmpty() { + return history.isEmpty(); + } +} diff --git a/commandpattern/src/CopyCommand.java b/commandpattern/src/CopyCommand.java new file mode 100644 index 0000000..a7ec8e8 --- /dev/null +++ b/commandpattern/src/CopyCommand.java @@ -0,0 +1,28 @@ +import java.util.Scanner; + +public class CopyCommand extends Command { + + public CopyCommand(Editor editor) { + super(editor); + } + + @Override + public boolean execute() { + System.out.println("카피를 시작합니다."); + Scanner scanner = new Scanner(System.in); + + System.out.print("Start Index: "); + int start = scanner.nextInt(); + + System.out.print("End Index: "); + int end = scanner.nextInt(); + + editor.clipboard = editor.text.substring(start, end); + return false; + } + + @Override + public void undo() { + throw new UnsupportedOperationException(); + } +} diff --git a/commandpattern/src/CutCommand.java b/commandpattern/src/CutCommand.java new file mode 100644 index 0000000..4811bec --- /dev/null +++ b/commandpattern/src/CutCommand.java @@ -0,0 +1,34 @@ +import java.util.Scanner; +import javax.print.AttributeException; + +public class CutCommand extends Command{ + + public CutCommand(Editor editor) { + super(editor); + } + + @Override + public boolean execute() { + System.out.println("자를 문자열의 인덱스를 입력해주세요."); + Scanner scanner = new Scanner(System.in); + + System.out.print("Start Index: "); + int start = scanner.nextInt(); + + System.out.print("End Index: "); + int end = scanner.nextInt(); + if (start >= end) { + return false; + } + + backup(); + editor.clipboard = editor.text.substring(start, end); + editor.text.delete(start, end); + return true; + } + + @Override + public void undo() { + editor.text = new StringBuilder(backup); + } +} diff --git a/commandpattern/src/Editor.java b/commandpattern/src/Editor.java new file mode 100644 index 0000000..0248e73 --- /dev/null +++ b/commandpattern/src/Editor.java @@ -0,0 +1,59 @@ +import java.util.Scanner; + +public class Editor { + + public StringBuilder text = new StringBuilder(); + public String clipboard; + public final CommandHistory history = new CommandHistory(); + + public void start() { + Scanner scanner = new Scanner(System.in); + while (true) { + System.out.print("커맨드를 입력해주세요: "); + String command = scanner.nextLine(); + + switch (command) { + case "input": + text.append(scanner.nextLine()); + break; + + case "copy": + executeCommand(new CopyCommand(this)); + break; + + case "cut": + executeCommand(new CutCommand(this)); + break; + + case "paste": + executeCommand(new PasteCommand(this)); + break; + + case "undo": + undo(); + break; + + case "exit": + System.exit(0); + } + System.out.println(text.toString()); + } + } + + private void undo() { + if (history.isEmpty()) { + return; + } + + Command command = history.pop(); + if (command != null) { + command.undo(); + } + } + + private void executeCommand(Command command) { + if (command.execute()) { + history.push(command); + } + } +} diff --git a/commandpattern/src/Main.java b/commandpattern/src/Main.java new file mode 100644 index 0000000..6a6e30e --- /dev/null +++ b/commandpattern/src/Main.java @@ -0,0 +1,8 @@ +public class Main { + + public static void main(String[] args) { + Editor editor = new Editor(); + + editor.start(); + } +} \ No newline at end of file diff --git a/commandpattern/src/PasteCommand.java b/commandpattern/src/PasteCommand.java new file mode 100644 index 0000000..0efcb03 --- /dev/null +++ b/commandpattern/src/PasteCommand.java @@ -0,0 +1,30 @@ +import java.util.Scanner; + +public class PasteCommand extends Command{ + + public PasteCommand(Editor editor) { + super(editor); + } + + @Override + public boolean execute() { + if (editor.clipboard == null) { + return false; + } + + backup(); + System.out.println("붙여 넣을 시작 인덱스를 입력해주세요."); + Scanner scanner = new Scanner(System.in); + + System.out.print("Start Index: "); + int start = scanner.nextInt(); + + editor.text.insert(start, editor.clipboard); + return true; + } + + @Override + public void undo() { + editor.text = new StringBuilder(backup); + } +}