├── .gitignore
├── .idea
├── .gitignore
├── checkstyle-idea.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── wsa-design-pattern.iml
├── README.md
├── c1-物件導向之不新手的新手村
└── OOP-技法
│ ├── Main.java
│ ├── abstractclass
│ ├── AI.java
│ ├── Decision.java
│ ├── Game.java
│ ├── Human.java
│ ├── OOAD.png
│ ├── Player.java
│ └── Test.java
│ ├── hero
│ ├── Fruit.java
│ ├── Guild.java
│ ├── Hero.java
│ ├── LevelSheet.java
│ ├── Pet.java
│ ├── Test.java
│ ├── Test2.java
│ ├── Test3.java
│ ├── case1.png
│ ├── case2.png
│ └── case3.png
│ ├── lecture
│ ├── Lecture.java
│ ├── LectureAttendance.java
│ ├── Student.java
│ ├── Test4.java
│ └── case4.png
│ └── utils
│ └── ValidationUtils.java
├── c2-Christopher-Alexander-設計模式
├── 景點-樣板方法
│ ├── .gitignore
│ ├── .idea
│ │ ├── .gitignore
│ │ ├── checkstyle-idea.xml
│ │ ├── compiler.xml
│ │ ├── jarRepositories.xml
│ │ ├── misc.xml
│ │ ├── modules.xml
│ │ └── vcs.xml
│ ├── astah.asta
│ ├── c2m2s1-樣板方法.iml
│ ├── common
│ │ ├── Group.java
│ │ ├── GroupingStrategy.java
│ │ ├── ReadStudents.java
│ │ ├── Student.java
│ │ ├── StudentGenerations.java
│ │ └── Utils.java
│ ├── pom.xml
│ ├── student.data
│ ├── v0
│ │ ├── LanguageBasedGroupingStrategy.java
│ │ └── Main.java
│ ├── v1
│ │ ├── LanguageBasedGroupingStrategy.java
│ │ ├── Main.java
│ │ └── TimeSlotsBasedGroupingStrategy.java
│ ├── v2
│ │ ├── CutBasedGroupingStrategy.java
│ │ ├── JobTitleBasedGroupingStrategy.java
│ │ ├── LanguageBasedGroupingStrategy.java
│ │ ├── Main.java
│ │ └── TimeSlotsBasedGroupingStrategy.java
│ └── v3
│ │ ├── CutBasedGroupingStrategy.java
│ │ ├── JobTitleBasedGroupingStrategy.java
│ │ ├── LanguageBasedGroupingStrategy.java
│ │ ├── Main.java
│ │ └── TimeSlotsBasedGroupingStrategy.java
├── 景點-策略模式
│ ├── .gitignore
│ ├── astah.asta
│ ├── commons
│ │ └── Utils.java
│ ├── v1
│ │ ├── Game.java
│ │ ├── Hero.java
│ │ └── Main.java
│ └── v2
│ │ ├── AttackType.java
│ │ ├── Earth.java
│ │ ├── Fireball.java
│ │ ├── Game.java
│ │ ├── Hero.java
│ │ ├── Main.java
│ │ ├── Powerball.java
│ │ └── Waterball.java
└── 景點-責任鏈模式
│ ├── .gitignore
│ ├── .idea
│ ├── .gitignore
│ ├── .name
│ ├── checkstyle-idea.xml
│ ├── compiler.xml
│ ├── jarRepositories.xml
│ ├── misc.xml
│ ├── modules.xml
│ └── vcs.xml
│ ├── C2M3S1.asta
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ └── tw
│ │ └── waterballsa
│ │ └── degisnpattern
│ │ └── c2m3s1
│ │ ├── v1
│ │ ├── Main.java
│ │ └── WaterballBot.java
│ │ ├── v2
│ │ ├── CurrencyHandler.java
│ │ ├── DcardHandler.java
│ │ ├── HelpHandler.java
│ │ ├── Main.java
│ │ ├── MessageHandler.java
│ │ └── WaterballBot.java
│ │ └── v3
│ │ ├── CurrencyHandler.java
│ │ ├── DcardHandler.java
│ │ ├── HelpMessageHandler.java
│ │ ├── Main.java
│ │ ├── MessageHandler.java
│ │ └── WaterballBot.java
│ └── resources
│ ├── .gitignore
│ └── token.example.properties
├── c3-掌握所有複雜行為變動
├── 景點-指令模式
│ ├── .idea
│ │ ├── .gitignore
│ │ ├── checkstyle-idea.xml
│ │ ├── inspectionProfiles
│ │ │ └── Project_Default.xml
│ │ ├── misc.xml
│ │ ├── modules.xml
│ │ ├── uiDesigner.xml
│ │ └── vcs.xml
│ ├── commons
│ │ ├── AirConditioner.java
│ │ ├── Fan.java
│ │ └── Television.java
│ ├── v1a
│ │ └── Controller.java
│ ├── v1b
│ │ ├── Controller.java
│ │ └── Main.java
│ ├── v2
│ │ ├── Command.java
│ │ ├── Controller.java
│ │ ├── FanNextLevelCommand.java
│ │ ├── FanPreviousLevelCommand.java
│ │ ├── Main.java
│ │ ├── TurnOffAirConditionerCommand.java
│ │ ├── TurnOffTvCommand.java
│ │ ├── TurnOnAirConditionerCommand.java
│ │ └── TurnOnTvCommand.java
│ └── v3
│ │ ├── Command.java
│ │ ├── Controller.java
│ │ ├── FanNextLevelCommand.java
│ │ ├── FanPreviousLevelCommand.java
│ │ ├── Main.java
│ │ ├── TurnOffAirConditionerCommand.java
│ │ ├── TurnOffTvCommand.java
│ │ ├── TurnOnAirConditionerCommand.java
│ │ └── TurnOnTvCommand.java
├── 景點-狀態模式
│ ├── .idea
│ │ ├── .gitignore
│ │ ├── checkstyle-idea.xml
│ │ ├── inspectionProfiles
│ │ │ └── Project_Default.xml
│ │ ├── misc.xml
│ │ ├── modules.xml
│ │ ├── uiDesigner.xml
│ │ └── vcs.xml
│ ├── img_1.png
│ ├── v0
│ │ ├── Main.java
│ │ └── TicketSystem.java
│ ├── v1
│ │ ├── Main.java
│ │ └── TicketSystem.java
│ └── v2
│ │ ├── Main.java
│ │ └── ticketsystem
│ │ ├── EnoughCoinsState.java
│ │ ├── InStockState.java
│ │ ├── SoldOutState.java
│ │ ├── State.java
│ │ └── TicketSystem.java
└── 景點-觀察者模式
│ ├── .gitignore
│ ├── .idea
│ ├── c3m1s1-觀察者模式.iml
│ ├── checkstyle-idea.xml
│ ├── compiler.xml
│ ├── inspectionProfiles
│ │ └── Project_Default.xml
│ ├── jarRepositories.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── uiDesigner.xml
│ └── vcs.xml
│ ├── common
│ ├── BarChart.java
│ ├── PieChart.java
│ ├── ReadStudents.java
│ ├── Student.java
│ └── Utils.java
│ ├── pom.xml
│ ├── student.data
│ ├── v1
│ ├── Main.java
│ ├── StudentDataFile.java
│ ├── StudentDataFileBackup.java
│ ├── StudentJobTitlePieChart.java
│ └── StudentLanguageBarChart.java
│ ├── v2pull
│ ├── Main.java
│ ├── StudentDataFile.java
│ ├── StudentDataFileBackup.java
│ ├── StudentDataObserver.java
│ ├── StudentJobTitlePieChart.java
│ └── StudentLanguageBarChart.java
│ ├── v3push
│ ├── Main.java
│ ├── StudentDataFile.java
│ ├── StudentDataFileBackup.java
│ ├── StudentDataObserver.java
│ ├── StudentJobTitlePieChart.java
│ └── StudentLanguageBarChart.java
│ └── xchart-3.8.1.jar
├── c4-規模化架構思維
├── 景點-代理人模式
│ ├── .idea
│ │ ├── .gitignore
│ │ ├── checkstyle-idea.xml
│ │ ├── compiler.xml
│ │ ├── discord.xml
│ │ ├── jarRepositories.xml
│ │ ├── libraries
│ │ │ ├── Maven__com_fasterxml_jackson_core_jackson_annotations_2_13_2.xml
│ │ │ ├── Maven__com_fasterxml_jackson_core_jackson_core_2_13_2.xml
│ │ │ ├── Maven__com_fasterxml_jackson_core_jackson_databind_2_13_2_2.xml
│ │ │ ├── Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_13_3.xml
│ │ │ └── Maven__org_apache_commons_commons_csv_1_9_0.xml
│ │ ├── misc.xml
│ │ ├── modules.xml
│ │ └── vcs.xml
│ ├── expenses.json
│ ├── food.ls
│ ├── img.png
│ ├── pom.xml
│ ├── utils
│ │ └── ScannerUtils.java
│ ├── v1
│ │ ├── Expense.java
│ │ ├── ExpenseTrackingCLI.java
│ │ ├── ExpenseTrackingSystem.java
│ │ ├── Main.java
│ │ └── SuperExpenseTrackingSystem.java
│ ├── v2
│ │ ├── Main.java
│ │ └── VirtualSuperExpenseTrackingSystemProxy.java
│ └── v3
│ │ ├── Main.java
│ │ └── TrialVersionSuperExpenseTrackingSystemProxy.java
├── 景點-裝飾者模式
│ ├── .idea
│ │ ├── .gitignore
│ │ ├── checkstyle-idea.xml
│ │ ├── discord.xml
│ │ ├── inspectionProfiles
│ │ │ └── Project_Default.xml
│ │ ├── misc.xml
│ │ ├── modules.xml
│ │ ├── uiDesigner.xml
│ │ └── vcs.xml
│ ├── commons
│ │ ├── Email.java
│ │ ├── Message.java
│ │ ├── User.java
│ │ └── ValidationUtils.java
│ ├── img.png
│ ├── v1
│ │ ├── EmailFormattingAndParagraphingMessenger.java
│ │ ├── EmailHidingAndParagraphingMessenger.java
│ │ ├── Main.java
│ │ └── Messenger.java
│ ├── v2
│ │ ├── ConsoleMessenger.java
│ │ ├── DiscordMessenger.java
│ │ ├── EmailFormatting.java
│ │ ├── HideEmails.java
│ │ ├── Main.java
│ │ ├── MessageProcessor.java
│ │ ├── Messenger.java
│ │ ├── Paragraphing.java
│ │ └── SendMessagesRequest.java
│ └── wsa.mail
├── 景點-複合模式
│ ├── .idea
│ │ ├── .gitignore
│ │ ├── checkstyle-idea.xml
│ │ ├── discord.xml
│ │ ├── inspectionProfiles
│ │ │ └── Project_Default.xml
│ │ ├── misc.xml
│ │ ├── modules.xml
│ │ └── vcs.xml
│ ├── utils
│ │ └── ValidationUtils.java
│ ├── v1
│ │ ├── CLI.java
│ │ ├── Directory.java
│ │ ├── File.java
│ │ └── Main.java
│ └── v2
│ │ ├── CLI.java
│ │ ├── Directory.java
│ │ ├── File.java
│ │ ├── Item.java
│ │ └── Main.java
├── 景點-轉接器模式
│ ├── .idea
│ │ ├── .gitignore
│ │ ├── checkstyle-idea.xml
│ │ ├── compiler.xml
│ │ ├── discord.xml
│ │ ├── inspectionProfiles
│ │ │ └── Project_Default.xml
│ │ ├── jarRepositories.xml
│ │ ├── libraries
│ │ │ └── Maven__org_jsoup_jsoup_1_15_2.xml
│ │ ├── misc.xml
│ │ ├── modules.xml
│ │ ├── uiDesigner.xml
│ │ └── vcs.xml
│ ├── pom.xml
│ └── v1and2
│ │ ├── Main.java
│ │ ├── VocabCrawlerAdapter.java
│ │ ├── VocabDictionary.java
│ │ ├── VocabLookupCLI.java
│ │ ├── Word.java
│ │ ├── WordNotExistsException.java
│ │ └── crawler
│ │ ├── SuperVocabCrawler.java
│ │ ├── SuperWORD.java
│ │ └── YouSpellItWrongException.java
└── 景點-門面模式
│ ├── .idea
│ ├── .gitignore
│ ├── checkstyle-idea.xml
│ ├── discord.xml
│ ├── inspectionProfiles
│ │ └── Project_Default.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── uiDesigner.xml
│ └── vcs.xml
│ ├── data.table
│ ├── v1
│ ├── Main.java
│ └── lib
│ │ ├── CountRows.java
│ │ ├── MarkdownParser.java
│ │ ├── StatsOperation.java
│ │ ├── Table.java
│ │ ├── TableStatsPerformer.java
│ │ └── TotalColumn.java
│ └── v2
│ ├── Main.java
│ ├── StatsFacade.java
│ └── lib
│ ├── CountRows.java
│ ├── MarkdownParser.java
│ ├── StatsOperation.java
│ ├── Table.java
│ ├── TableStatsPerformer.java
│ └── TotalColumn.java
├── c5-生命週期及控制反轉
├── 景點-單體模式
│ ├── pom.xml
│ ├── remaining-budget
│ ├── script.json
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ ├── Main.java
│ │ │ ├── app
│ │ │ │ ├── discord
│ │ │ │ │ ├── Channel.java
│ │ │ │ │ ├── ChatMessageResponse.java
│ │ │ │ │ ├── Events.java
│ │ │ │ │ └── Platform.java
│ │ │ │ ├── fb
│ │ │ │ │ ├── Bot.java
│ │ │ │ │ ├── Cart.java
│ │ │ │ │ ├── Client.java
│ │ │ │ │ ├── ECommercePlatformBot.java
│ │ │ │ │ └── Events.java
│ │ │ │ └── sdk
│ │ │ │ │ ├── v1
│ │ │ │ │ └── ChatBot.java
│ │ │ │ │ ├── v2
│ │ │ │ │ ├── ChatBot.java
│ │ │ │ │ └── Main.java
│ │ │ │ │ └── v3
│ │ │ │ │ └── ChatBot.java
│ │ │ └── lib
│ │ │ │ ├── commands
│ │ │ │ └── AndCommand.java
│ │ │ │ ├── ioc
│ │ │ │ ├── Command.java
│ │ │ │ ├── CommandInterpreter.java
│ │ │ │ ├── CommandLine.java
│ │ │ │ ├── DuplicateInstanceTypeException.java
│ │ │ │ ├── Instantiator.java
│ │ │ │ └── WaterballContainer.java
│ │ │ │ └── utils
│ │ │ │ └── IteratorUtils.java
│ │ └── resources
│ │ │ └── .gitignore
│ │ └── test
│ │ └── java
│ │ └── lib
│ │ ├── commands
│ │ ├── EchoCommandTask.java
│ │ └── RepeatCommandTask.java
│ │ └── ioc
│ │ └── WaterballContainerTest.java
├── 景點-工廠方法
│ └── src
│ │ ├── tunnel
│ │ ├── Tunnel.java
│ │ └── WaterballTunnel.java
│ │ ├── v1
│ │ └── ChatRoomServer.java
│ │ ├── v2
│ │ ├── ChatRoomServer.java
│ │ ├── Main.java
│ │ └── WaterballChatRoomServer.java
│ │ └── v3
│ │ ├── ChatRoomServer.java
│ │ ├── Database.java
│ │ ├── DatabaseFactory.java
│ │ ├── Main.java
│ │ ├── TunnelFactory.java
│ │ └── WaterballTunnelFactory.java
└── 景點-抽象工廠
│ ├── c5m3s1.iml
│ ├── floor1.questions
│ ├── floor2.questions
│ ├── floor3.questions
│ ├── requirement.md
│ ├── v1
│ ├── Floor.java
│ ├── Game.java
│ ├── Main.java
│ ├── Player.java
│ ├── Portable.java
│ ├── Portal.java
│ ├── Question.java
│ ├── Region.java
│ ├── Stage.java
│ └── TopFloor.java
│ ├── v2
│ ├── BasePortal.java
│ ├── BaseRegion.java
│ ├── BaseStage.java
│ ├── Floor.java
│ ├── Game.java
│ ├── Main.java
│ ├── Player.java
│ ├── Portable.java
│ ├── Portal.java
│ ├── PortalDecorator.java
│ ├── Question.java
│ ├── Region.java
│ ├── RegionDecorator.java
│ ├── Stage.java
│ ├── TopFloor.java
│ ├── defaults
│ │ ├── BasePortalFactory.java
│ │ ├── BaseRegionFactory.java
│ │ └── BaseStageFactory.java
│ ├── factories
│ │ ├── PortalFactory.java
│ │ ├── RegionFactory.java
│ │ └── StageFactory.java
│ └── thirdparty
│ │ ├── SuperPortal.java
│ │ ├── SuperPortalFactory.java
│ │ ├── SuperRegion.java
│ │ ├── SuperRegionFactory.java
│ │ ├── SuperStage.java
│ │ └── SuperStageFactory.java
│ ├── v3
│ ├── BasePortal.java
│ ├── BaseRegion.java
│ ├── BaseStage.java
│ ├── Floor.java
│ ├── Game.java
│ ├── Main.java
│ ├── Player.java
│ ├── Portable.java
│ ├── Portal.java
│ ├── PortalDecorator.java
│ ├── PortalFactory.java
│ ├── Question.java
│ ├── Region.java
│ ├── RegionDecorator.java
│ ├── RegionFactory.java
│ ├── Stage.java
│ ├── StageFactory.java
│ ├── SuperPortal.java
│ ├── SuperRegion.java
│ ├── SuperStage.java
│ ├── TopFloor.java
│ ├── defaults
│ │ └── BaseFloorAbstractFactory.java
│ ├── factories
│ │ └── FloorAbstractFactory.java
│ └── thirdparty
│ │ ├── SuperFloorAbstractFactory.java
│ │ ├── SuperPortal.java
│ │ ├── SuperRegion.java
│ │ └── SuperStage.java
│ └── waterball.questions
└── wsa-design-pattern.iml
/.gitignore:
--------------------------------------------------------------------------------
1 | overs JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
2 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
3 | # User-specific stuff
4 | .idea/**/workspace.xml
5 | .idea/**/tasks.xml
6 | .idea/**/usage.statistics.xml
7 | .idea/**/dictionaries
8 | .idea/**/shelf
9 | .idea/gradle.xml
10 | .idea/libraries
11 |
12 |
13 | # AWS User-specific
14 | .idea/**/aws.xml
15 |
16 |
17 | # IntelliJ
18 | out/
19 |
20 | # Maven
21 | target/
22 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/wsa-design-pattern.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 軟體設計模式精通之旅:影片範例程式
2 |
3 | 大家好,這是「[軟體設計模式精通之旅](https://waterballsa.tw/design-pattern)」這門課所有影片的範例程式碼!
4 |
5 | 各位學員菁英們,若發現有教材上的疑問或勘誤,歡迎提出。
6 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/Main.java:
--------------------------------------------------------------------------------
1 | public class Main {
2 | public static void main(String[] args) {
3 | System.out.println("Hello world!");
4 | }
5 | }
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/abstractclass/AI.java:
--------------------------------------------------------------------------------
1 | package abstractclass;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class AI extends Player {
7 | public AI(int number) {
8 | super(number);
9 | }
10 |
11 | @Override
12 | public Decision decide() {
13 | int randomNum = (int) (Math.random() * 3);
14 | switch (randomNum) {
15 | case 0:
16 | return Decision.SCISSORS;
17 | case 1:
18 | return Decision.PAPER;
19 | default:
20 | return Decision.STONE;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/abstractclass/Decision.java:
--------------------------------------------------------------------------------
1 | package abstractclass;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public enum Decision {
7 | PAPER("布"), SCISSORS("剪刀"), STONE("石頭");
8 |
9 | private final String name;
10 |
11 | Decision(String name) {
12 | this.name = name;
13 | }
14 |
15 | @Override
16 | public String toString() {
17 | return name;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/abstractclass/Human.java:
--------------------------------------------------------------------------------
1 | package abstractclass;
2 |
3 | import java.util.Scanner;
4 |
5 | /**
6 | * @author johnny@waterballsa.tw
7 | */
8 | public class Human extends Player {
9 | private final static Scanner in = new Scanner(System.in);
10 |
11 | public Human(int number) {
12 | super(number);
13 | }
14 |
15 | @Override
16 | public Decision decide() {
17 | System.out.println("請出拳 (1) 剪刀 (2) 拳頭 (3) 布:");
18 | int num = in.nextInt();
19 | switch (num) {
20 | case 1:
21 | return Decision.SCISSORS;
22 | case 2:
23 | return Decision.STONE;
24 | case 3:
25 | return Decision.PAPER;
26 | default:
27 | System.out.println("只能輸入範圍 1~3 的數字,請再輸入一次。");
28 | return decide();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/abstractclass/OOAD.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c1-物件導向之不新手的新手村/OOP-技法/abstractclass/OOAD.png
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/abstractclass/Player.java:
--------------------------------------------------------------------------------
1 | package abstractclass;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public abstract class Player {
7 | private final int number;
8 |
9 | public Player(int number) {
10 | this.number = number;
11 | }
12 |
13 | public abstract Decision decide();
14 |
15 | public int getNumber() {
16 | return number;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/abstractclass/Test.java:
--------------------------------------------------------------------------------
1 | package abstractclass;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class Test {
7 | public static void main(String[] args) {
8 | Game game = new Game(new Human(2), new AI(2));
9 | game.start();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/hero/Fruit.java:
--------------------------------------------------------------------------------
1 | package hero;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class Fruit {
7 | }
8 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/hero/LevelSheet.java:
--------------------------------------------------------------------------------
1 | package hero;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class LevelSheet {
7 | public int queryLevel(int totalExp) {
8 | return totalExp / 1000 + 1;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/hero/Pet.java:
--------------------------------------------------------------------------------
1 | package hero;
2 |
3 | import org.jetbrains.annotations.Nullable;
4 |
5 | /**
6 | * @author johnny@waterballsa.tw
7 | */
8 | public class Pet {
9 | private final String name;
10 |
11 | @Nullable
12 | private Hero owner;
13 |
14 | public Pet(String name) {
15 | this.name = name;
16 | }
17 |
18 | public void eat(Fruit fruit) {
19 | System.out.println("寵物吃水果⋯⋯");
20 |
21 | if (owner != null) {
22 | owner.setHp(owner.getHp() + 10);
23 | }
24 | }
25 |
26 | public String getName() {
27 | return name;
28 | }
29 |
30 | public void setOwner(@Nullable Hero owner) {
31 | this.owner = owner;
32 | }
33 |
34 | public Hero getOwner() {
35 | return owner;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/hero/Test.java:
--------------------------------------------------------------------------------
1 | package hero;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class Test {
7 |
8 | public static void main(String[] args) {
9 | Hero hero = new Hero();
10 | LevelSheet levelSheet = new LevelSheet();
11 |
12 | hero.gainExp(0, levelSheet);
13 | hero.gainExp(100, levelSheet);
14 | hero.gainExp(900, levelSheet);
15 |
16 | hero.gainExp(-200, levelSheet);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/hero/Test2.java:
--------------------------------------------------------------------------------
1 | package hero;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class Test2 {
7 | public static void main(String[] args) {
8 | Hero hero = new Hero();
9 | Pet cat = new Pet("Cat");
10 | hero.setPet(cat);
11 |
12 | System.out.printf("Hero 目前血量: %d\n", hero.getHp());
13 | assert hero.getPet() != null;
14 | System.out.printf("Hero's 寵物名稱: %s\n", hero.getPet().getName());
15 |
16 | for (int i = 0; i < 5; i++) {
17 | cat.eat(new Fruit());
18 | }
19 |
20 | hero.removePet();
21 |
22 | for (int i = 0; i < 5; i++) {
23 | cat.eat(new Fruit());
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/hero/case1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c1-物件導向之不新手的新手村/OOP-技法/hero/case1.png
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/hero/case2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c1-物件導向之不新手的新手村/OOP-技法/hero/case2.png
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/hero/case3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c1-物件導向之不新手的新手村/OOP-技法/hero/case3.png
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/lecture/LectureAttendance.java:
--------------------------------------------------------------------------------
1 | package lecture;
2 |
3 | import org.jetbrains.annotations.Nullable;
4 |
5 | import static utils.ValidationUtils.shouldBeWithinRange;
6 |
7 | /**
8 | * @author johnny@waterballsa.tw
9 | */
10 | public class LectureAttendance {
11 | private final Student student;
12 | private final Lecture lecture;
13 |
14 | @Nullable
15 | private Integer grade;
16 |
17 | public LectureAttendance(Student student, Lecture lecture) {
18 | this.student = student;
19 | this.lecture = lecture;
20 | }
21 |
22 | public void receiveGrade(int grade) {
23 | this.grade = shouldBeWithinRange("Grade", grade, 0, 100);
24 | System.out.printf("在 '%s' 課程中,學生 '%s' 拿了 '%d' 分。\n",
25 | lecture.getName(), student.getName(), grade);
26 | }
27 |
28 | @Nullable
29 | public Integer getGrade() {
30 | return grade;
31 | }
32 |
33 | public Student getStudent() {
34 | return student;
35 | }
36 |
37 | public Lecture getLecture() {
38 | return lecture;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/lecture/Student.java:
--------------------------------------------------------------------------------
1 | package lecture;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import static java.util.Collections.unmodifiableList;
7 |
8 | /**
9 | * @author johnny@waterballsa.tw
10 | */
11 | public class Student {
12 | private final String name;
13 |
14 | private final List lectureAttendances = new ArrayList<>(); // 代表他修了哪些課 (0..*)
15 |
16 | public Student(String name) {
17 | this.name = name;
18 | }
19 |
20 | public String getName() {
21 | return name;
22 | }
23 |
24 | public List getLectureAttendances() {
25 | return unmodifiableList(lectureAttendances);
26 | }
27 |
28 | public void addLectureAttendance(LectureAttendance lectureAttendance) {
29 | lectureAttendances.add(lectureAttendance);
30 | }
31 |
32 | public void removeLectureAttendance(LectureAttendance lectureAttendance) {
33 | lectureAttendances.remove(lectureAttendance);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/lecture/Test4.java:
--------------------------------------------------------------------------------
1 | package lecture;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class Test4 {
7 | public static void main(String[] args) {
8 | Student student1 = new Student("Johnny");
9 | Student student2 = new Student("Peter");
10 | Lecture lecture1 = new Lecture("軟體設計模式精通之旅");
11 | Lecture lecture2 = new Lecture("GenAI 工程師產能爆發之路");
12 |
13 | lecture1.signUp(student1);
14 | lecture2.signUp(student1);
15 | lecture2.signUp(student2);
16 |
17 | try {
18 | lecture1.signUp(student1);
19 | } catch (Exception err) {
20 | System.out.println("不能重複註冊!");
21 | }
22 |
23 | for (LectureAttendance attendance : lecture1.getLectureAttendances()) {
24 | attendance.receiveGrade(60); // 打分數
25 | }
26 |
27 | for (LectureAttendance attendance : lecture2.getLectureAttendances()) {
28 | attendance.receiveGrade(100); // 打分數
29 | }
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/lecture/case4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c1-物件導向之不新手的新手村/OOP-技法/lecture/case4.png
--------------------------------------------------------------------------------
/c1-物件導向之不新手的新手村/OOP-技法/utils/ValidationUtils.java:
--------------------------------------------------------------------------------
1 | package utils;
2 |
3 | import static java.lang.String.format;
4 |
5 | /**
6 | * @author johnny@waterballsa.tw
7 | */
8 | public class ValidationUtils {
9 |
10 | public static int shouldBeGreaterThanOrEqual(String name, int num, int target) {
11 | if (num < target) {
12 | throw new IllegalArgumentException(format("'%s' must be greater than or equal %d.", name, target));
13 | }
14 | return num;
15 | }
16 |
17 | public static int shouldBeWithinRange(String name, int num, int min, int max) {
18 | if (min > max) {
19 | throw new IllegalArgumentException("Min must be <= Max!");
20 | }
21 | if (num < min || num > max) {
22 | throw new IllegalArgumentException(format("'%s' must be within 0~100.", name));
23 | }
24 | return num;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/.gitignore:
--------------------------------------------------------------------------------
1 | overs JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
2 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
3 | # User-specific stuff
4 | .idea/**/workspace.xml
5 | .idea/**/tasks.xml
6 | .idea/**/usage.statistics.xml
7 | .idea/**/dictionaries
8 | .idea/**/shelf
9 | .idea/gradle.xml
10 | .idea/libraries
11 |
12 | # AWS User-specific
13 | .idea/**/aws.xml
14 |
15 |
16 | # IntelliJ
17 | out/
18 |
19 | # Maven
20 | target/
21 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/astah.asta:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c2-Christopher-Alexander-設計模式/景點-樣板方法/astah.asta
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/c2m2s1-樣板方法.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/common/GroupingStrategy.java:
--------------------------------------------------------------------------------
1 | package common;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public interface GroupingStrategy {
9 | List group(List students);
10 | }
11 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/common/Utils.java:
--------------------------------------------------------------------------------
1 | package common;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class Utils {
9 | public static void printGroups(List groups) {
10 | for (Group group : groups) {
11 | System.out.print("[");
12 | for (int i = 0; i < group.size(); i++) {
13 | if (i % 2 == 0) {
14 | System.out.print(group.get(i));
15 | } else {
16 | System.out.printf(", %s", group.get(i));
17 | if (i != group.size() - 1) {
18 | System.out.println();
19 | }
20 | }
21 | }
22 | System.out.print("]\n\n");
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | tw.waterballsa
8 | c2m2s1
9 | 1.0-SNAPSHOT
10 |
11 |
12 | 11
13 | 11
14 |
15 |
16 |
17 |
18 | com.github.javafaker
19 | javafaker
20 | 0.12
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/v0/Main.java:
--------------------------------------------------------------------------------
1 | package v0;
2 |
3 | import common.Group;
4 | import common.GroupingStrategy;
5 | import common.ReadStudents;
6 | import common.Student;
7 |
8 | import java.io.IOException;
9 | import java.util.List;
10 |
11 | import static common.Utils.printGroups;
12 |
13 | /**
14 | * @author - johnny850807@gmail.com (Waterball)
15 | */
16 | public class Main {
17 | public static void main(String[] args) throws IOException {
18 | LanguageBasedGroupingStrategy groupingStrategy = new LanguageBasedGroupingStrategy();
19 |
20 | List students = ReadStudents.fromFile("student.data");
21 | List groups = groupingStrategy.group(students);
22 |
23 | printGroups(groups);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/v1/LanguageBasedGroupingStrategy.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import common.Group;
4 | import common.GroupingStrategy;
5 | import common.Student;
6 | import v2.CutBasedGroupingStrategy;
7 |
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | /**
14 | * @author - johnny850807@gmail.com (Waterball)
15 | */
16 | public class LanguageBasedGroupingStrategy extends CutBasedGroupingStrategy {
17 |
18 | @Override
19 | protected Object cutBy(Student student) {
20 | return student.getLanguage();
21 | }
22 |
23 | @Override
24 | protected boolean meetMergeCriteria(Group nonFullGroup, Group fullGroup) {
25 | return nonFullGroup.get(0).getLanguage().equals(fullGroup.get(0).getLanguage());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/v1/Main.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import common.Group;
4 | import common.GroupingStrategy;
5 | import common.ReadStudents;
6 | import common.Student;
7 | import v2.JobTitleBasedGroupingStrategy;
8 |
9 | import java.io.IOException;
10 | import java.util.List;
11 |
12 | import static common.Utils.printGroups;
13 |
14 | /**
15 | * @author - johnny850807@gmail.com (Waterball)
16 | */
17 | public class Main {
18 | public static void main(String[] args) throws IOException {
19 | GroupingStrategy groupingStrategy = new JobTitleBasedGroupingStrategy();
20 | List students = ReadStudents.fromFile("student.data");
21 | List groups = groupingStrategy.group(students);
22 |
23 | printGroups(groups);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/v1/TimeSlotsBasedGroupingStrategy.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import common.Student;
4 | import v2.CutBasedGroupingStrategy;
5 |
6 | import static java.lang.String.format;
7 |
8 | /**
9 | * @author - johnny850807@gmail.com (Waterball)
10 | */
11 | public class TimeSlotsBasedGroupingStrategy extends CutBasedGroupingStrategy {
12 |
13 | @Override
14 | protected Object cutBy(Student student) {
15 | return hashMemberTimeSlots(student);
16 | }
17 |
18 | private String hashMemberTimeSlots(Student student) {
19 | // Hash to four s 9AM-12AM 1PM-4PM 5PM-7PM 8PM-9PM
20 | boolean[] s = student.getAvailableTimeSlots();
21 | return format("%d%d%d%d", convertBooleanToNumber(s[0] && s[1] && s[2] && s[3]),
22 | convertBooleanToNumber(s[4] & s[5] & s[6] & s[7]),
23 | convertBooleanToNumber(s[8] && s[9] && s[10]),
24 | convertBooleanToNumber(s[11] && s[12]));
25 | }
26 |
27 | private int convertBooleanToNumber(boolean b) {
28 | return b ? 1 : 0;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/v2/JobTitleBasedGroupingStrategy.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import common.Group;
4 | import common.Student;
5 |
6 | /**
7 | * @author - johnny850807@gmail.com (Waterball)
8 | */
9 | public class JobTitleBasedGroupingStrategy extends CutBasedGroupingStrategy {
10 | @Override
11 | protected Object cutBy(Student student) {
12 | return student.getJobTitle();
13 | }
14 |
15 | @Override
16 | protected boolean meetMergeCriteria(Group nonFullGroup, Group fullGroup) {
17 | return nonFullGroup.get(0).getJobTitle().equals(fullGroup.get(0).getJobTitle());
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/v2/Main.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import common.Group;
4 | import common.GroupingStrategy;
5 | import common.ReadStudents;
6 | import common.Student;
7 |
8 | import java.io.IOException;
9 | import java.util.List;
10 |
11 | import static common.Utils.printGroups;
12 |
13 | /**
14 | * @author - johnny850807@gmail.com (Waterball)
15 | */
16 | public class Main {
17 | public static void main(String[] args) throws IOException {
18 | GroupingStrategy groupingStrategy = new LanguageBasedGroupingStrategy();
19 |
20 | List students = ReadStudents.fromFile("student.data");
21 | List groups = groupingStrategy.group(students);
22 |
23 | printGroups(groups);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/v3/JobTitleBasedGroupingStrategy.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import common.Group;
4 | import common.Student;
5 |
6 | /**
7 | * @author - johnny850807@gmail.com (Waterball)
8 | */
9 | public class JobTitleBasedGroupingStrategy extends CutBasedGroupingStrategy {
10 |
11 | protected JobTitleBasedGroupingStrategy(int groupMinSize) {
12 | super(groupMinSize);
13 | }
14 |
15 | @Override
16 | protected Object cutGroupBy(Student student) {
17 | return student.getJobTitle();
18 | }
19 |
20 | @Override
21 | protected boolean meetMergeCriterial(Group nonFullGroup, Group fullGroup) {
22 | return nonFullGroup.get(0).getJobTitle().equals(fullGroup.get(0).getJobTitle());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/v3/LanguageBasedGroupingStrategy.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import common.Group;
4 | import common.Student;
5 |
6 | /**
7 | * @author - johnny850807@gmail.com (Waterball)
8 | */
9 | public class LanguageBasedGroupingStrategy extends CutBasedGroupingStrategy {
10 |
11 | protected LanguageBasedGroupingStrategy() {
12 | super(6);
13 | }
14 |
15 | @Override
16 | protected Object cutGroupBy(Student student) {
17 | return student.getLanguage();
18 | }
19 |
20 | @Override
21 | protected boolean meetMergeCriterial(Group nonFullGroup, Group fullGroup) {
22 | return nonFullGroup.get(0).getLanguage().equals(fullGroup.get(0).getLanguage());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/v3/Main.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import common.Group;
4 | import common.GroupingStrategy;
5 | import common.Student;
6 | import common.ReadStudents;
7 |
8 | import java.io.IOException;
9 | import java.util.List;
10 |
11 | import static common.Utils.printGroups;
12 |
13 | /**
14 | * @author - johnny850807@gmail.com (Waterball)
15 | */
16 | public class Main {
17 | public static void main(String[] args) throws IOException {
18 | GroupingStrategy groupingStrategy = new TimeSlotsBasedGroupingStrategy();
19 |
20 | List students = ReadStudents.fromFile("student.data");
21 | List groups = groupingStrategy.group(students);
22 |
23 | printGroups(groups);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-樣板方法/v3/TimeSlotsBasedGroupingStrategy.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import common.Student;
4 |
5 | import static java.lang.String.format;
6 |
7 | /**
8 | * @author - johnny850807@gmail.com (Waterball)
9 | */
10 | public class TimeSlotsBasedGroupingStrategy extends CutBasedGroupingStrategy {
11 |
12 | protected TimeSlotsBasedGroupingStrategy() {
13 | super(6);
14 | }
15 |
16 | @Override
17 | protected Object cutGroupBy(Student student) {
18 | return hashMemberTimeSlots(student);
19 | }
20 |
21 | private String hashMemberTimeSlots(Student student) {
22 | // Hash to four s 9AM-12AM 1PM-4PM 5PM-7PM 8PM-9PM
23 | boolean[] s = student.getAvailableTimeSlots();
24 | return format("%d%d%d%d", convertBooleanToNumber(s[0] && s[1] && s[2] && s[3]),
25 | convertBooleanToNumber(s[4] & s[5] & s[6] & s[7]),
26 | convertBooleanToNumber(s[8] && s[9] && s[10]),
27 | convertBooleanToNumber(s[11] && s[12]));
28 | }
29 |
30 | private int convertBooleanToNumber(boolean b) {
31 | return b ? 1 : 0;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/.gitignore:
--------------------------------------------------------------------------------
1 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
2 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
3 | # User-specific stuff
4 | .idea/**/workspace.xml
5 | .idea/**/tasks.xml
6 | .idea/**/usage.statistics.xml
7 | .idea/**/dictionaries
8 | .idea/**/shelf
9 |
10 | # AWS User-specific
11 | .idea/**/aws.xml
12 |
13 |
14 | # IntelliJ
15 | out/
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/astah.asta:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c2-Christopher-Alexander-設計模式/景點-策略模式/astah.asta
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/commons/Utils.java:
--------------------------------------------------------------------------------
1 | package commons;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Utils {
7 | public static void printf(String format, Object... args) {
8 | System.out.printf(format, args);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/v1/Game.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import java.util.List;
4 |
5 | import static java.util.Arrays.asList;
6 | import static java.util.Collections.swap;
7 | import static commons.Utils.printf;
8 |
9 | public class Game {
10 | private final List heroes;
11 |
12 | public Game(Hero hero1, Hero hero2) {
13 | this.heroes = asList(hero1, hero2);
14 | }
15 |
16 | public void start() {
17 | nextTurn();
18 | }
19 |
20 | private void nextTurn() {
21 | Hero attacker = heroes.get(0);
22 | Hero attacked = heroes.get(1);
23 | attacker.attack(attacked);
24 | swap(heroes, 0, 1);
25 | if (attacked.isDead()) {
26 | printf("英雄 %s 死亡!%s 獲勝!\n", attacked.getName(), attacker.getName());
27 | } else {
28 | nextTurn();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/v1/Main.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Main {
7 | public static void main(String[] args) {
8 | Hero hero1 = new Hero("水之球", "Waterball");
9 | Hero hero2 = new Hero("大潘", "Fireball");
10 | Game game = new Game(hero1, hero2);
11 | game.start();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/v2/AttackType.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | public interface AttackType {
4 | void attack(Hero attacker, Hero attacked);
5 | }
6 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/v2/Earth.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | public class Earth implements AttackType {
4 |
5 | public void attack(Hero attacker, Hero attacked) {
6 | for (int i = 0; i < 10; i++) {
7 | attacked.damage(20);
8 | }
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/v2/Fireball.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | public class Fireball implements AttackType {
4 |
5 | public void attack(Hero attacker, Hero attacked) {
6 | for (int i = 0; i < 3; i++) {
7 | attacked.damage(50);
8 | }
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/v2/Game.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import java.util.List;
4 |
5 | import static java.util.Arrays.asList;
6 | import static java.util.Collections.swap;
7 | import static commons.Utils.printf;
8 |
9 | public class Game {
10 | private final List heroes;
11 |
12 | public Game(Hero hero1, Hero hero2) {
13 | this.heroes = asList(hero1, hero2);
14 | }
15 |
16 | public void start() {
17 | nextTurn();
18 | }
19 |
20 | private void nextTurn() {
21 | Hero attacker = heroes.get(0);
22 | Hero attacked = heroes.get(1);
23 | attacker.attack(attacked);
24 | swap(heroes, 0, 1);
25 | if (attacked.isDead()) {
26 | printf("英雄 %s 死亡!%s 獲勝!\n", attacked.getName(), attacker.getName());
27 | } else {
28 | nextTurn();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/v2/Hero.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import static commons.Utils.printf;
4 | import static java.lang.Math.max;
5 |
6 | public class Hero {
7 | private int hp = 500;
8 | private final String name;
9 | private final AttackType attackType;
10 |
11 | public Hero(String name, AttackType attackType) {
12 | this.name = name;
13 | this.attackType = attackType;
14 | }
15 |
16 | public void attack(Hero hero) {
17 | attackType.attack(this, hero);
18 | }
19 |
20 | public void damage(int damage) {
21 | setHp(getHp() - damage);
22 | printf("英雄 %s 受到了 %d 點傷害,生命值剩下 %d。\n", name, damage, hp);
23 | }
24 |
25 | public boolean isDead() {
26 | return hp <= 0;
27 | }
28 |
29 | public String getName() {
30 | return name;
31 | }
32 |
33 | public void setHp(int hp) {
34 | this.hp = max(0, hp);
35 | }
36 |
37 | public int getHp() {
38 | return hp;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/v2/Main.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Main {
7 | public static void main(String[] args) {
8 | Hero hero1 = new Hero("水之球", new Powerball());
9 | Hero hero2 = new Hero("大潘", new Earth());
10 | Game game = new Game(hero1, hero2);
11 | game.start();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/v2/Powerball.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Powerball implements AttackType {
7 | @Override
8 | public void attack(Hero attacker, Hero attacked) {
9 | attacked.damage(500);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-策略模式/v2/Waterball.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | public class Waterball implements AttackType {
4 |
5 | public void attack(Hero attacker, Hero attacked) {
6 | attacked.damage((int) (attacker.getHp() * 0.5));
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/.gitignore:
--------------------------------------------------------------------------------
1 | overs JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
2 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
3 | # User-specific stuff
4 | .idea/**/workspace.xml
5 | .idea/**/tasks.xml
6 | .idea/**/usage.statistics.xml
7 | .idea/**/dictionaries
8 | .idea/**/shelf
9 | .idea/gradle.xml
10 | .idea/libraries
11 |
12 | # AWS User-specific
13 | .idea/**/aws.xml
14 |
15 |
16 | # IntelliJ
17 | out/
18 |
19 | # Maven
20 | target/
21 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/.idea/.name:
--------------------------------------------------------------------------------
1 | c2m3s1
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/C2M3S1.asta:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/C2M3S1.asta
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/src/main/java/tw/waterballsa/degisnpattern/c2m3s1/v1/Main.java:
--------------------------------------------------------------------------------
1 | package tw.waterballsa.degisnpattern.c2m3s1.v1;
2 |
3 | import java.io.IOException;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class Main {
9 | public static void main(String[] args) throws IOException {
10 | WaterballBot waterballBot = new WaterballBot();
11 | waterballBot.connect();
12 | }
13 | }
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/src/main/java/tw/waterballsa/degisnpattern/c2m3s1/v2/HelpHandler.java:
--------------------------------------------------------------------------------
1 | package tw.waterballsa.degisnpattern.c2m3s1.v2;
2 |
3 | import discord4j.core.object.entity.Message;
4 | import discord4j.core.object.entity.channel.MessageChannel;
5 |
6 | /**
7 | * @author - johnny850807@gmail.com (Waterball)
8 | */
9 | public class HelpHandler extends MessageHandler {
10 |
11 | public HelpHandler(MessageHandler next) {
12 | super(next);
13 | }
14 |
15 | @Override
16 | public void handle(Message message, MessageChannel channel) {
17 | if ("help".equalsIgnoreCase(message.getContent())) {
18 | channel.createMessage("▋ HELP ▋").block();
19 | channel.createMessage("Commands: dcard, currency").block();
20 | } else if (next != null) {
21 | next.handle(message, channel);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/src/main/java/tw/waterballsa/degisnpattern/c2m3s1/v2/Main.java:
--------------------------------------------------------------------------------
1 | package tw.waterballsa.degisnpattern.c2m3s1.v2;
2 |
3 | import java.io.IOException;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class Main {
9 | public static void main(String[] args) throws IOException {
10 | WaterballBot waterballBot = new WaterballBot(new HelpHandler((new CurrencyHandler(null))));
11 | waterballBot.connect();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/src/main/java/tw/waterballsa/degisnpattern/c2m3s1/v2/MessageHandler.java:
--------------------------------------------------------------------------------
1 | package tw.waterballsa.degisnpattern.c2m3s1.v2;
2 |
3 | import discord4j.core.object.entity.Message;
4 | import discord4j.core.object.entity.channel.MessageChannel;
5 |
6 | /**
7 | * @author - johnny850807@gmail.com (Waterball)
8 | */
9 | public abstract class MessageHandler {
10 | protected MessageHandler next;
11 |
12 | public MessageHandler(MessageHandler next) {
13 | this.next = next;
14 | }
15 |
16 | public abstract void handle(Message message, MessageChannel channel);
17 | }
18 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/src/main/java/tw/waterballsa/degisnpattern/c2m3s1/v3/HelpMessageHandler.java:
--------------------------------------------------------------------------------
1 | package tw.waterballsa.degisnpattern.c2m3s1.v3;
2 |
3 | import discord4j.core.object.entity.Message;
4 | import discord4j.core.object.entity.channel.MessageChannel;
5 |
6 | /**
7 | * @author - johnny850807@gmail.com (Waterball)
8 | */
9 | public class HelpMessageHandler extends MessageHandler {
10 | public HelpMessageHandler(MessageHandler next) {
11 | super(next);
12 | }
13 |
14 | @Override
15 | protected boolean match(Message message) {
16 | return "help".equalsIgnoreCase(message.getContent());
17 | }
18 |
19 | @Override
20 | protected void doHandling(Message message, MessageChannel channel) {
21 | channel.createMessage("▋ HELP ▋").block();
22 | channel.createMessage("Commands: dcard, currency").block();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/src/main/java/tw/waterballsa/degisnpattern/c2m3s1/v3/Main.java:
--------------------------------------------------------------------------------
1 | package tw.waterballsa.degisnpattern.c2m3s1.v3;
2 |
3 | import java.io.IOException;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class Main {
9 |
10 | public static void main(String[] args) throws IOException {
11 | WaterballBot waterballBot = new WaterballBot(
12 | new HelpMessageHandler(new DcardHandler(new CurrencyHandler(null))));
13 | waterballBot.connect();
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/src/main/java/tw/waterballsa/degisnpattern/c2m3s1/v3/MessageHandler.java:
--------------------------------------------------------------------------------
1 | package tw.waterballsa.degisnpattern.c2m3s1.v3;
2 |
3 | import discord4j.core.object.entity.Message;
4 | import discord4j.core.object.entity.channel.MessageChannel;
5 |
6 | /**
7 | * @author - johnny850807@gmail.com (Waterball)
8 | */
9 | public abstract class MessageHandler {
10 | protected MessageHandler next;
11 |
12 | public MessageHandler(MessageHandler next) {
13 | this.next = next;
14 | }
15 |
16 | public void handle(Message message, MessageChannel channel) {
17 | if (match(message)) {
18 | doHandling(message, channel);
19 | } else if (next != null) {
20 | next.handle(message, channel);
21 | }
22 | }
23 |
24 | protected abstract boolean match(Message message);
25 | protected abstract void doHandling(Message message, MessageChannel channel);
26 | }
27 |
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/src/main/resources/.gitignore:
--------------------------------------------------------------------------------
1 | token.properties
--------------------------------------------------------------------------------
/c2-Christopher-Alexander-設計模式/景點-責任鏈模式/src/main/resources/token.example.properties:
--------------------------------------------------------------------------------
1 | TOKEN=
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/commons/AirConditioner.java:
--------------------------------------------------------------------------------
1 | package commons;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class AirConditioner {
7 | private boolean on;
8 |
9 | public boolean isOn() {
10 | return on;
11 | }
12 |
13 | public void turnOn() {
14 | this.on = true;
15 | System.out.println("【 AC 】Turned ON.");
16 | }
17 |
18 | public void turnOff() {
19 | this.on = false;
20 | System.out.println("【 AC 】Turned OFF.");
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/commons/Fan.java:
--------------------------------------------------------------------------------
1 | package commons;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Fan {
7 | private int level; // {0, 1, 2, 3}
8 |
9 | public int getLevel() {
10 | return level;
11 | }
12 |
13 | public void nextLevel() {
14 | level = (level + 1) % 4;
15 | System.out.println("【 Fan 】Level -> " + level);
16 | }
17 |
18 | public void previousLevel() {
19 | level = level - 1 == -1 ? 3 : level - 1;
20 | System.out.println("【 Fan 】Level -> " + level);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/commons/Television.java:
--------------------------------------------------------------------------------
1 | package commons;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Television {
7 | private boolean on;
8 |
9 | public void turnOn() {
10 | this.on = true;
11 | System.out.println("【 TV 】Turned ON.");
12 | }
13 |
14 | public void turnOff() {
15 | this.on = false;
16 | System.out.println("【 TV 】Turned OFF.");
17 | }
18 |
19 | public boolean isOn() {
20 | return on;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v1a/Controller.java:
--------------------------------------------------------------------------------
1 | package v1a;
2 |
3 | import commons.AirConditioner;
4 | import commons.Fan;
5 | import commons.Television;
6 |
7 | /**
8 | * @author - johnny850807@gmail.com (Waterball)
9 | */
10 | public class Controller {
11 | private final AirConditioner ac;
12 | private final Fan fan;
13 | private final Television tv;
14 |
15 | public Controller(AirConditioner ac, Fan fan, Television tv) {
16 | this.ac = ac;
17 | this.fan = fan;
18 | this.tv = tv;
19 | }
20 |
21 | public void press0() {
22 | fan.nextLevel();
23 | }
24 |
25 | public void press1() {
26 | fan.previousLevel();
27 | }
28 |
29 | public void press2() {
30 | ac.turnOn();
31 | }
32 |
33 | public void press3() {
34 | ac.turnOff();
35 | }
36 |
37 | public void press4() {
38 | tv.turnOn();
39 | }
40 |
41 | public void press5() {
42 | tv.turnOff();
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v1b/Controller.java:
--------------------------------------------------------------------------------
1 | package v1b;
2 |
3 | import commons.AirConditioner;
4 | import commons.Fan;
5 | import commons.Television;
6 |
7 | /**
8 | * @author - johnny850807@gmail.com (Waterball)
9 | */
10 | public class Controller {
11 | private final AirConditioner ac;
12 | private final Fan fan;
13 | private final Television tv;
14 |
15 | public Controller(AirConditioner ac, Fan fan, Television tv) {
16 | this.ac = ac;
17 | this.fan = fan;
18 | this.tv = tv;
19 | }
20 |
21 | public void press(int button) {
22 | switch (button) {
23 | case 0:
24 | fan.nextLevel();
25 | break;
26 | case 1:
27 | fan.previousLevel();
28 | break;
29 | case 2:
30 | ac.turnOn();
31 | break;
32 | case 3:
33 | ac.turnOff();
34 | break;
35 | case 4:
36 | tv.turnOn();
37 | break;
38 | case 5:
39 | tv.turnOff();
40 | break;
41 | default:
42 | throw new IllegalArgumentException("Non-recognizable button.");
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v1b/Main.java:
--------------------------------------------------------------------------------
1 | package v1b;
2 |
3 | import commons.AirConditioner;
4 | import commons.Fan;
5 | import commons.Television;
6 |
7 | import java.util.Scanner;
8 |
9 | /**
10 | * @author - johnny850807@gmail.com (Waterball)
11 | */
12 | @SuppressWarnings("InfiniteLoopStatement")
13 | public class Main {
14 | public static void main(String[] args) {
15 | AirConditioner ac = new AirConditioner();
16 | Fan fan = new Fan();
17 | Television tv = new Television();
18 | Controller controller = new Controller(ac, fan, tv);
19 |
20 | Scanner in = new Scanner(System.in);
21 | while (true) {
22 | System.out.println("Click a button (0~5): ");
23 | int button = in.nextInt();
24 | controller.press(button);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v2/Command.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public interface Command {
7 | void execute();
8 | }
9 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v2/Controller.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Controller {
7 | private final Command[] commands = new Command[6];
8 |
9 | public void setCommand(int button, Command command) {
10 | commands[button] = command;
11 | }
12 |
13 | public void press(int button) {
14 | if (button >= 0 && button < commands.length) {
15 | commands[button].execute();
16 | } else {
17 | throw new IllegalArgumentException("Button " + button + " unsupported.");
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v2/FanNextLevelCommand.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.Fan;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class FanNextLevelCommand implements Command {
9 | private final Fan fan;
10 |
11 | public FanNextLevelCommand(Fan fan) {
12 | this.fan = fan;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | fan.nextLevel();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v2/FanPreviousLevelCommand.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.Fan;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class FanPreviousLevelCommand implements Command {
9 | private final Fan fan;
10 |
11 | public FanPreviousLevelCommand(Fan fan) {
12 | this.fan = fan;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | fan.previousLevel();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v2/Main.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.AirConditioner;
4 | import commons.Fan;
5 | import commons.Television;
6 |
7 | import java.util.Scanner;
8 |
9 | /**
10 | * @author - johnny850807@gmail.com (Waterball)
11 | */
12 | @SuppressWarnings("InfiniteLoopStatement")
13 | public class Main {
14 | public static void main(String[] args) {
15 | AirConditioner ac = new AirConditioner();
16 | Fan fan = new Fan();
17 | Television tv = new Television();
18 |
19 | Controller controller = new Controller();
20 | // dependency injection
21 | controller.setCommand(0, new FanNextLevelCommand(fan));
22 | controller.setCommand(1, new FanPreviousLevelCommand(fan));
23 | controller.setCommand(2, new TurnOnAirConditionerCommand(ac));
24 | controller.setCommand(3, new TurnOffAirConditionerCommand(ac));
25 | controller.setCommand(4, new TurnOnTvCommand(tv));
26 | controller.setCommand(5, new TurnOffTvCommand(tv));
27 |
28 | Scanner in = new Scanner(System.in);
29 | while (true) {
30 | System.out.println("Click a button (0~5): ");
31 | int button = in.nextInt();
32 | controller.press(button);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v2/TurnOffAirConditionerCommand.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.AirConditioner;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class TurnOffAirConditionerCommand implements Command {
9 | private final AirConditioner ac;
10 |
11 | public TurnOffAirConditionerCommand(AirConditioner ac) {
12 | this.ac = ac;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | ac.turnOff();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v2/TurnOffTvCommand.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.Television;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class TurnOffTvCommand implements Command {
9 | private final Television tv;
10 |
11 | public TurnOffTvCommand(Television tv) {
12 | this.tv = tv;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | tv.turnOff();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v2/TurnOnAirConditionerCommand.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.AirConditioner;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class TurnOnAirConditionerCommand implements Command {
9 | private final AirConditioner ac;
10 |
11 | public TurnOnAirConditionerCommand(AirConditioner ac) {
12 | this.ac = ac;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | ac.turnOn();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v2/TurnOnTvCommand.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.Television;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class TurnOnTvCommand implements Command {
9 | private final Television tv;
10 |
11 | public TurnOnTvCommand(Television tv) {
12 | this.tv = tv;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | tv.turnOn();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v3/Command.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public interface Command {
7 | void execute();
8 | void undo();
9 | }
10 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v3/FanNextLevelCommand.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import commons.Fan;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class FanNextLevelCommand implements Command {
9 | private final Fan fan;
10 |
11 | public FanNextLevelCommand(Fan fan) {
12 | this.fan = fan;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | fan.nextLevel();
18 | }
19 |
20 | @Override
21 | public void undo() {
22 | fan.previousLevel();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v3/FanPreviousLevelCommand.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import commons.Fan;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class FanPreviousLevelCommand implements Command {
9 | private final Fan fan;
10 |
11 | public FanPreviousLevelCommand(Fan fan) {
12 | this.fan = fan;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | fan.previousLevel();
18 | }
19 |
20 | @Override
21 | public void undo() {
22 | fan.nextLevel();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v3/TurnOffAirConditionerCommand.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import commons.AirConditioner;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class TurnOffAirConditionerCommand implements Command {
9 | private final AirConditioner ac;
10 |
11 | public TurnOffAirConditionerCommand(AirConditioner ac) {
12 | this.ac = ac;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | ac.turnOff();
18 | }
19 |
20 | @Override
21 | public void undo() {
22 | ac.turnOn();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v3/TurnOffTvCommand.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import commons.Television;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class TurnOffTvCommand implements Command {
9 | private final Television tv;
10 |
11 | public TurnOffTvCommand(Television tv) {
12 | this.tv = tv;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | tv.turnOff();
18 | }
19 |
20 | @Override
21 | public void undo() {
22 | tv.turnOn();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v3/TurnOnAirConditionerCommand.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import commons.AirConditioner;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class TurnOnAirConditionerCommand implements Command {
9 | private final AirConditioner ac;
10 |
11 | public TurnOnAirConditionerCommand(AirConditioner ac) {
12 | this.ac = ac;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | ac.turnOn();
18 | }
19 |
20 | @Override
21 | public void undo() {
22 | ac.turnOff();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-指令模式/v3/TurnOnTvCommand.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import commons.Television;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class TurnOnTvCommand implements Command {
9 | private final Television tv;
10 |
11 | public TurnOnTvCommand(Television tv) {
12 | this.tv = tv;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | tv.turnOn();
18 | }
19 |
20 | @Override
21 | public void undo() {
22 | tv.turnOff();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-狀態模式/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-狀態模式/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-狀態模式/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-狀態模式/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-狀態模式/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-狀態模式/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-狀態模式/img_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c3-掌握所有複雜行為變動/景點-狀態模式/img_1.png
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-狀態模式/v1/Main.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 |
4 | import static v1.TicketSystem.State.*;
5 |
6 | /**
7 | * @author - johnny850807@gmail.com (Waterball)
8 | */
9 | public class Main {
10 | public static void main(String[] args) {
11 | TicketSystem ticketSystem = new TicketSystem(2);
12 |
13 | System.out.println("【Case 1】 Enough coins -> Error 不再接受新硬幣");
14 | ticketSystem.setState(ENOUGH_COINS);
15 | ticketSystem.insertCoin();
16 |
17 | System.out.println("\n【Case 2】 Enough Coins + Refund -> 吐 3 枚、熄燈");
18 | ticketSystem.pressRefundButton();
19 |
20 | System.out.println("\n【Case 3】 Enough coins + Buy -> 將硬幣總數歸零、出一張票、熄燈");
21 | ticketSystem.setState(ENOUGH_COINS);
22 | ticketSystem.pressBuyButton();
23 |
24 | System.out.println("\n【Case 4】 In-Stock(0 Coins) + Buy -> Error 金幣不足");
25 | ticketSystem.setState(IN_STOCK);
26 | ticketSystem.pressBuyButton();
27 |
28 | System.out.println("\n【Case 5】 In-Stock(0 Coins) + Refund -> 吐 0 枚");
29 | ticketSystem.pressRefundButton();
30 |
31 | System.out.println("\n【Case 6】 Sold-Out + Insert Coin -> 立即吐出 1 枚硬幣");
32 | ticketSystem.setState(SOLD_OUT);
33 | ticketSystem.insertCoin();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-狀態模式/v2/ticketsystem/SoldOutState.java:
--------------------------------------------------------------------------------
1 | package v2.ticketsystem;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class SoldOutState extends State {
7 | public SoldOutState(TicketSystem ticketSystem) {
8 | super(ticketSystem);
9 | ticketSystem.turnLight(false);
10 | }
11 |
12 | @Override
13 | public void insertCoin() {
14 | ticketSystem.setTotal(ticketSystem.getTotal() + 1);
15 | ticketSystem.spitCoins(ticketSystem.getTotal());
16 | }
17 |
18 | @Override
19 | public void fillInTickets(int tickets) {
20 | ticketSystem.setState(new InStockState(ticketSystem,
21 | ticketSystem.getTickets() + tickets));
22 | }
23 |
24 | @Override
25 | public void pressBuyButton() {
26 | System.out.println("[ERROR] You haven't inserted enough coins.");
27 | }
28 |
29 | @Override
30 | public void pressRefundButton() {
31 | ticketSystem.spitCoins(ticketSystem.getTotal());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-狀態模式/v2/ticketsystem/State.java:
--------------------------------------------------------------------------------
1 | package v2.ticketsystem;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public abstract class State {
7 | protected TicketSystem ticketSystem;
8 | public abstract void insertCoin();
9 | public abstract void fillInTickets(int tickets);
10 | public abstract void pressBuyButton();
11 | public abstract void pressRefundButton();
12 |
13 | public State(TicketSystem ticketSystem) {
14 | this.ticketSystem = ticketSystem;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/.gitignore:
--------------------------------------------------------------------------------
1 | overs JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
2 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
3 | # User-specific stuff
4 | .idea/**/workspace.xml
5 | .idea/**/tasks.xml
6 | .idea/**/usage.statistics.xml
7 | .idea/**/dictionaries
8 | .idea/**/shelf
9 | .idea/gradle.xml
10 | .idea/libraries
11 |
12 | # AWS User-specific
13 | .idea/**/aws.xml
14 |
15 |
16 | # IntelliJ
17 | out/
18 |
19 | # Maven
20 | target/
21 |
22 | *.backup.data
23 | students.bar.png
24 | students.pie.png
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/common/BarChart.java:
--------------------------------------------------------------------------------
1 | package common;
2 |
3 | import common.ReadStudents;
4 | import org.knowm.xchart.BitmapEncoder;
5 | import org.knowm.xchart.CategoryChart;
6 | import org.knowm.xchart.CategoryChartBuilder;
7 | import org.knowm.xchart.style.Styler;
8 |
9 | import java.io.IOException;
10 | import java.util.List;
11 |
12 | import static org.knowm.xchart.BitmapEncoder.saveBitmap;
13 |
14 | /**
15 | * @author - johnny850807@gmail.com (Waterball)
16 | */
17 | public class BarChart {
18 | public void export(String fileName, List x, List y) throws IOException {
19 | CategoryChart chart = categoryChart();
20 | chart.addSeries("histogram", x, y);
21 | saveBitmap(chart, fileName, BitmapEncoder.BitmapFormat.PNG);
22 | }
23 |
24 | private CategoryChart categoryChart() {
25 | CategoryChart chart = new CategoryChartBuilder().width(800).height(600).title("Bar Chart").xAxisTitle("Language").yAxisTitle("Count").build();
26 | chart.getStyler().setLegendPosition(Styler.LegendPosition.InsideNW);
27 | chart.getStyler().setAvailableSpaceFill(.96);
28 | chart.getStyler().setOverlapped(true);
29 | return chart;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/common/Utils.java:
--------------------------------------------------------------------------------
1 | package common;
2 |
3 | import java.util.Collection;
4 | import java.util.List;
5 | import java.util.function.Function;
6 | import java.util.function.Predicate;
7 | import java.util.stream.Collectors;
8 |
9 | import static java.util.stream.Collectors.toList;
10 |
11 | /**
12 | * @author - johnny850807@gmail.com (Waterball)
13 | */
14 | public class Utils {
15 | public static void delay(long ms) {
16 | try {
17 | Thread.sleep(ms);
18 | } catch (InterruptedException ignored) {
19 | }
20 | }
21 |
22 | public static List selectDistinct(Collection t, Function mapping) {
23 | return t.stream().map(mapping).distinct().collect(toList());
24 | }
25 | public static List count(Collection t, Collection v, Function mapping) {
26 | return t.stream().map(val -> (int) v.stream().filter(s -> val.equals(mapping.apply(s))).count()).collect(toList());
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v1/Main.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Main {
7 | public static void main(String[] args) {
8 | StudentDataFile studentDataFile = new StudentDataFile("student.data");
9 | studentDataFile.startMonitoring();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v1/StudentDataFileBackup.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import common.Student;
4 |
5 | import java.io.IOException;
6 | import java.nio.file.Files;
7 | import java.nio.file.Paths;
8 | import java.text.SimpleDateFormat;
9 | import java.util.Date;
10 | import java.util.Locale;
11 | import java.util.stream.Collectors;
12 |
13 | import static java.util.stream.Collectors.joining;
14 |
15 | /**
16 | * @author - johnny850807@gmail.com (Waterball)
17 | */
18 | public class StudentDataFileBackup {
19 | private final StudentDataFile dataFile;
20 |
21 | public StudentDataFileBackup(StudentDataFile dataFile) {
22 | this.dataFile = dataFile;
23 | }
24 |
25 | public void backup() throws IOException {
26 | String fileName = new SimpleDateFormat("yyyyMMdd-HH:mm:ss'.backup.data'", Locale.getDefault()).format(new Date());
27 | Files.writeString(Paths.get(fileName), dataFile.getStudents().stream()
28 | .map(Student::toString).collect(joining("\n")));
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v1/StudentJobTitlePieChart.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import common.PieChart;
4 | import common.Student;
5 |
6 | import java.io.IOException;
7 | import java.util.Collection;
8 | import java.util.List;
9 |
10 | import static common.Utils.count;
11 | import static common.Utils.selectDistinct;
12 |
13 | /**
14 | * @author - johnny850807@gmail.com (Waterball)
15 | */
16 | public class StudentJobTitlePieChart {
17 | private final StudentDataFile dataFile;
18 |
19 | public StudentJobTitlePieChart(StudentDataFile dataFile) {
20 | this.dataFile = dataFile;
21 | }
22 |
23 | public void renderPieChart() throws IOException {
24 | Collection students = dataFile.getStudents();
25 | List series = selectDistinct(students, Student::getJobTitle);
26 | List numbers = count(series, students, Student::getJobTitle);
27 | PieChart pieChart = new PieChart();
28 | pieChart.export("students.pie.png", series, numbers);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v1/StudentLanguageBarChart.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import common.BarChart;
4 | import common.Student;
5 |
6 | import java.io.IOException;
7 | import java.util.Collection;
8 | import java.util.List;
9 |
10 | import static common.Utils.count;
11 | import static common.Utils.selectDistinct;
12 |
13 | /**
14 | * @author - johnny850807@gmail.com (Waterball)
15 | */
16 | public class StudentLanguageBarChart {
17 | private final StudentDataFile dataFile;
18 |
19 | public StudentLanguageBarChart(StudentDataFile dataFile) {
20 | this.dataFile = dataFile;
21 | }
22 |
23 | public void renderBarChart() throws IOException {
24 | BarChart barChart = new BarChart();
25 | Collection students = dataFile.getStudents();
26 | List x = selectDistinct(students, Student::getLanguage);
27 | List y = count(x, students, Student::getLanguage);
28 | barChart.export("students.bar.png", x, y);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v2pull/Main.java:
--------------------------------------------------------------------------------
1 | package v2pull;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Main {
7 | public static void main(String[] args) {
8 | StudentDataFile studentDataFile = new StudentDataFile("student.data");
9 | StudentLanguageBarChart barChart = new StudentLanguageBarChart(studentDataFile);
10 | StudentJobTitlePieChart pieChart = new StudentJobTitlePieChart(studentDataFile);
11 | StudentDataFileBackup dataFileBackup = new StudentDataFileBackup(studentDataFile);
12 | studentDataFile.register(barChart);
13 | studentDataFile.register(pieChart);
14 | studentDataFile.register(dataFileBackup);
15 | studentDataFile.startMonitoring();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v2pull/StudentDataFileBackup.java:
--------------------------------------------------------------------------------
1 | package v2pull;
2 |
3 | import common.Student;
4 |
5 | import java.io.IOException;
6 | import java.nio.file.Files;
7 | import java.nio.file.Paths;
8 | import java.text.SimpleDateFormat;
9 | import java.util.Date;
10 | import java.util.Locale;
11 |
12 | import static java.util.stream.Collectors.joining;
13 |
14 | /**
15 | * @author - johnny850807@gmail.com (Waterball)
16 | */
17 | public class StudentDataFileBackup implements StudentDataObserver {
18 | private final StudentDataFile dataFile;
19 |
20 | public StudentDataFileBackup(StudentDataFile dataFile) {
21 | this.dataFile = dataFile;
22 | }
23 |
24 | @Override
25 | public void update() throws IOException {
26 | String fileName = new SimpleDateFormat("yyyyMMdd-HH:mm:ss'.backup.data'", Locale.getDefault()).format(new Date());
27 | Files.writeString(Paths.get(fileName), dataFile.getStudents().stream()
28 | .map(Student::toString)
29 | .collect(joining("\n")));
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v2pull/StudentDataObserver.java:
--------------------------------------------------------------------------------
1 | package v2pull;
2 |
3 | import java.io.IOException;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public interface StudentDataObserver {
9 | void update() throws IOException;
10 | }
11 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v2pull/StudentJobTitlePieChart.java:
--------------------------------------------------------------------------------
1 | package v2pull;
2 |
3 | import common.BarChart;
4 | import common.PieChart;
5 | import common.Student;
6 |
7 | import java.io.IOException;
8 | import java.util.Collection;
9 | import java.util.List;
10 |
11 | import static common.Utils.count;
12 | import static common.Utils.selectDistinct;
13 | import static java.util.stream.Collectors.toList;
14 |
15 | /**
16 | * @author - johnny850807@gmail.com (Waterball)
17 | */
18 | public class StudentJobTitlePieChart implements StudentDataObserver {
19 | private final StudentDataFile dataFile;
20 |
21 | public StudentJobTitlePieChart(StudentDataFile dataFile) {
22 | this.dataFile = dataFile;
23 | }
24 |
25 | @Override
26 | public void update() throws IOException {
27 | PieChart pieChart = new PieChart();
28 | Collection students = dataFile.getStudents();
29 | List x = selectDistinct(students, Student::getLanguage);
30 | List y = count(x, students, Student::getLanguage);
31 | pieChart.export("students.bar.png", x, y);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v2pull/StudentLanguageBarChart.java:
--------------------------------------------------------------------------------
1 | package v2pull;
2 |
3 | import common.BarChart;
4 | import common.Student;
5 | import org.knowm.xchart.CategoryChart;
6 | import org.knowm.xchart.CategoryChartBuilder;
7 | import org.knowm.xchart.style.Styler;
8 |
9 | import java.io.IOException;
10 | import java.util.Collection;
11 | import java.util.List;
12 |
13 | import static common.Utils.count;
14 | import static common.Utils.selectDistinct;
15 | import static java.util.stream.Collectors.toList;
16 |
17 | /**
18 | * @author - johnny850807@gmail.com (Waterball)
19 | */
20 | public class StudentLanguageBarChart implements StudentDataObserver {
21 | private final StudentDataFile dataFile;
22 |
23 | public StudentLanguageBarChart(StudentDataFile dataFile) {
24 | this.dataFile = dataFile;
25 | }
26 |
27 | @Override
28 | public void update() throws IOException {
29 | BarChart barChart = new BarChart();
30 | Collection students = dataFile.getStudents();
31 | List x = selectDistinct(students, Student::getLanguage);
32 | List y = count(x, students, Student::getLanguage);
33 | barChart.export("students.bar.png", x, y);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v3push/Main.java:
--------------------------------------------------------------------------------
1 | package v3push;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Main {
7 | public static void main(String[] args) {
8 | StudentDataFile studentDataFile = new StudentDataFile("student.data");
9 | StudentLanguageBarChart barChart = new StudentLanguageBarChart();
10 | StudentJobTitlePieChart pieChart = new StudentJobTitlePieChart();
11 | StudentDataFileBackup dataFileBackup = new StudentDataFileBackup();
12 | studentDataFile.register(barChart);
13 | studentDataFile.register(pieChart);
14 | studentDataFile.register(dataFileBackup);
15 | studentDataFile.startMonitoring();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v3push/StudentDataFileBackup.java:
--------------------------------------------------------------------------------
1 | package v3push;
2 |
3 | import common.Student;
4 |
5 | import java.io.IOException;
6 | import java.nio.file.Files;
7 | import java.nio.file.Paths;
8 | import java.text.SimpleDateFormat;
9 | import java.util.Collection;
10 | import java.util.Date;
11 | import java.util.Locale;
12 |
13 | import static java.util.stream.Collectors.joining;
14 |
15 | /**
16 | * @author - johnny850807@gmail.com (Waterball)
17 | */
18 | @SuppressWarnings("ALL")
19 | public class StudentDataFileBackup implements StudentDataObserver {
20 | @Override
21 | public void update(Collection students) throws IOException {
22 | String fileName = new SimpleDateFormat("yyyyMMdd-HH:mm:ss'.backup.data'", Locale.getDefault()).format(new Date());
23 | Files.writeString(Paths.get(fileName), students.stream()
24 | .map(Student::toString)
25 | .collect(joining("\n")));
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v3push/StudentDataObserver.java:
--------------------------------------------------------------------------------
1 | package v3push;
2 |
3 | import common.Student;
4 |
5 | import java.io.IOException;
6 | import java.util.Collection;
7 |
8 | /**
9 | * @author - johnny850807@gmail.com (Waterball)
10 | */
11 | public interface StudentDataObserver {
12 | void update(Collection students) throws IOException;
13 | }
14 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v3push/StudentJobTitlePieChart.java:
--------------------------------------------------------------------------------
1 | package v3push;
2 |
3 | import common.BarChart;
4 | import common.PieChart;
5 | import common.Student;
6 |
7 | import java.io.IOException;
8 | import java.util.Collection;
9 | import java.util.List;
10 |
11 | import static common.Utils.count;
12 | import static common.Utils.selectDistinct;
13 |
14 | /**
15 | * @author - johnny850807@gmail.com (Waterball)
16 | */
17 | public class StudentJobTitlePieChart implements StudentDataObserver {
18 | @Override
19 | public void update(Collection students) throws IOException {
20 | PieChart pieChart = new PieChart();
21 | List x = selectDistinct(students, Student::getLanguage);
22 | List y = count(x, students, Student::getLanguage);
23 | pieChart.export("students.bar.png", x, y);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/v3push/StudentLanguageBarChart.java:
--------------------------------------------------------------------------------
1 | package v3push;
2 |
3 | import common.BarChart;
4 | import common.Student;
5 | import org.knowm.xchart.BitmapEncoder;
6 | import org.knowm.xchart.CategoryChart;
7 | import org.knowm.xchart.CategoryChartBuilder;
8 | import org.knowm.xchart.style.Styler;
9 |
10 | import java.io.IOException;
11 | import java.util.Collection;
12 | import java.util.List;
13 |
14 | import static common.Utils.count;
15 | import static common.Utils.selectDistinct;
16 | import static java.util.stream.Collectors.toList;
17 | import static org.knowm.xchart.BitmapEncoder.saveBitmap;
18 |
19 | /**
20 | * @author - johnny850807@gmail.com (Waterball)
21 | */
22 | public class StudentLanguageBarChart implements StudentDataObserver {
23 | @Override
24 | public void update(Collection students) throws IOException {
25 | BarChart barChart = new BarChart();
26 | List x = selectDistinct(students, Student::getLanguage);
27 | List y = count(x, students, Student::getLanguage);
28 | barChart.export("students.bar.png", x, y);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/c3-掌握所有複雜行為變動/景點-觀察者模式/xchart-3.8.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c3-掌握所有複雜行為變動/景點-觀察者模式/xchart-3.8.1.jar
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/discord.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_13_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_13_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_13_2_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_13_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/libraries/Maven__org_apache_commons_commons_csv_1_9_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c4-規模化架構思維/景點-代理人模式/img.png
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/v1/Expense.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import java.math.BigDecimal;
4 | import java.time.LocalDateTime;
5 | import java.util.UUID;
6 |
7 | /**
8 | * @author - johnny850807@gmail.com (Waterball)
9 | */
10 | public class Expense {
11 | private final String id;
12 | private final String description;
13 | private final BigDecimal cost;
14 | private final LocalDateTime createdTime;
15 |
16 | public Expense(String description, BigDecimal cost) {
17 | this(UUID.randomUUID().toString(),
18 | description, cost, LocalDateTime.now());
19 | }
20 |
21 | public Expense(String id, String description, BigDecimal cost, LocalDateTime createdTime) {
22 | this.id = id;
23 | this.description = description;
24 | this.cost = cost;
25 | this.createdTime = createdTime;
26 | }
27 |
28 | public Expense edit(String description, BigDecimal cost) {
29 | return new Expense(id, description, cost, createdTime);
30 | }
31 |
32 | public String getId() {
33 | return id;
34 | }
35 |
36 | public String getDescription() {
37 | return description;
38 | }
39 |
40 | public BigDecimal getCost() {
41 | return cost;
42 | }
43 |
44 | public LocalDateTime getCreatedTime() {
45 | return createdTime;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/v1/ExpenseTrackingSystem.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public interface ExpenseTrackingSystem {
9 | List getExpenses();
10 | void addExpense(Expense expense);
11 | void editExpense(Expense expense);
12 | void exportCSV(String filename);
13 | }
14 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/v1/Main.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Main {
7 | public static void main(String[] args) {
8 | ExpenseTrackingCLI cli = new ExpenseTrackingCLI(new SuperExpenseTrackingSystem());
9 | cli.start();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/v2/Main.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import v1.ExpenseTrackingCLI;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class Main {
9 | public static void main(String[] args) {
10 | ExpenseTrackingCLI cli = new ExpenseTrackingCLI(new VirtualSuperExpenseTrackingSystemProxy());
11 | cli.start();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/v2/VirtualSuperExpenseTrackingSystemProxy.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import v1.Expense;
4 | import v1.ExpenseTrackingSystem;
5 | import v1.SuperExpenseTrackingSystem;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * @author - johnny850807@gmail.com (Waterball)
11 | */
12 | public class VirtualSuperExpenseTrackingSystemProxy implements ExpenseTrackingSystem {
13 | private SuperExpenseTrackingSystem superSystem;
14 |
15 | @Override
16 | public List getExpenses() {
17 | lazyInitialization();
18 | return superSystem.getExpenses();
19 | }
20 |
21 | @Override
22 | public void addExpense(Expense expense) {
23 | lazyInitialization();
24 | superSystem.addExpense(expense);
25 | }
26 |
27 | @Override
28 | public void editExpense(Expense expense) {
29 | lazyInitialization();
30 | superSystem.editExpense(expense);
31 | }
32 |
33 | @Override
34 | public void exportCSV(String filename) {
35 | lazyInitialization();
36 | superSystem.exportCSV(filename);
37 | }
38 |
39 | private void lazyInitialization() {
40 | if (superSystem == null) {
41 | superSystem = new SuperExpenseTrackingSystem();
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/v3/Main.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import v1.ExpenseTrackingCLI;
4 | import v1.SuperExpenseTrackingSystem;
5 |
6 | /**
7 | * @author - johnny850807@gmail.com (Waterball)
8 | */
9 | public class Main {
10 | public static void main(String[] args) {
11 | ExpenseTrackingCLI cli = new ExpenseTrackingCLI(new TrialVersionSuperExpenseTrackingSystemProxy());
12 | cli.start();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-代理人模式/v3/TrialVersionSuperExpenseTrackingSystemProxy.java:
--------------------------------------------------------------------------------
1 | package v3;
2 |
3 | import v2.VirtualSuperExpenseTrackingSystemProxy;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class TrialVersionSuperExpenseTrackingSystemProxy extends VirtualSuperExpenseTrackingSystemProxy {
9 | @Override
10 | public void exportCSV(String filename) {
11 | throw new UnsupportedOperationException("CSV exporting is not supported in the trial version.");
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/.idea/discord.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/commons/Email.java:
--------------------------------------------------------------------------------
1 | package commons;
2 |
3 | import java.util.Objects;
4 |
5 | import static java.lang.String.format;
6 |
7 | /**
8 | * @author - johnny850807@gmail.com (Waterball)
9 | */
10 | public class Email {
11 | private final String username;
12 | private final String domain;
13 |
14 | public Email(String username, String domain) {
15 | this.username = username;
16 | this.domain = domain;
17 | }
18 |
19 | public String getUsername() {
20 | return username;
21 | }
22 |
23 | public String getDomain() {
24 | return domain;
25 | }
26 |
27 | @Override
28 | public String toString() {
29 | return format("%s@%s", username, domain);
30 | }
31 |
32 | @Override
33 | public boolean equals(Object o) {
34 | if (this == o) return true;
35 | if (o == null || getClass() != o.getClass()) return false;
36 | Email email = (Email) o;
37 | return username.equals(email.username) && domain.equals(email.domain);
38 | }
39 |
40 | @Override
41 | public int hashCode() {
42 | return Objects.hash(username, domain);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/commons/User.java:
--------------------------------------------------------------------------------
1 | package commons;
2 |
3 | import static java.lang.String.format;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class User {
9 | private final Email email;
10 | private final String nickname;
11 |
12 | public User(Email email, String nickname) {
13 | this.email = email;
14 | this.nickname = nickname;
15 | }
16 |
17 | public String getNickname() {
18 | return nickname;
19 | }
20 |
21 | public Email getEmail() {
22 | return email;
23 | }
24 |
25 | @Override
26 | public String toString() {
27 | return format("%s (%s)", nickname, email);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/commons/ValidationUtils.java:
--------------------------------------------------------------------------------
1 | package commons;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class ValidationUtils {
7 | public static String lengthShouldBeWithin(String content, int min, int max) {
8 | if (content.length() < min || content.length() > max) {
9 | throw new IllegalArgumentException(String.format("The length must be within %d~%d.", min, max));
10 | }
11 | return content;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Waterball-Software-Academy/Software-Design-Pattern/0d833dc792f953af40df43132dc555df20bd481b/c4-規模化架構思維/景點-裝飾者模式/img.png
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/v1/Main.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import commons.Email;
4 | import commons.Message;
5 | import commons.User;
6 |
7 | public class Main {
8 | public static void main(String[] args) {
9 | User waterball = new User(new Email("johnny", "waterballsa.tw"), "水球");
10 | User tsen = new User(new Email("tsen", "waterballsa.tw"), "岑岑");
11 | Message message = new Message(waterball, tsen,
12 | "Could you tell the following people (wally@waterballsa.tw, fixiabis@waterballsa.tw, fong-putao@waterballsa.tw)\n\n" +
13 | "that I'm gonna take a leave today? Thanks!"
14 | );
15 |
16 | System.out.println("====== EmailFormattingAndParagraphingMessenger =====");
17 | new EmailFormattingAndParagraphingMessenger().sendMessage(message);
18 | System.out.println("\n====== EmailHidingAndParagraphingMessenger =====");
19 | new EmailHidingAndParagraphingMessenger().sendMessage(message);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/v1/Messenger.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import commons.Message;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public abstract class Messenger {
9 | public abstract void sendMessage(Message message);
10 | }
11 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/v2/ConsoleMessenger.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.Message;
4 |
5 | import java.time.format.DateTimeFormatter;
6 | import java.util.List;
7 |
8 | /**
9 | * @author - johnny850807@gmail.com (Waterball)
10 | */
11 | public class ConsoleMessenger implements Messenger {
12 | @Override
13 | public void send(List messages) {
14 | System.out.println("以下訊息已經送到了 Console ...");
15 | for (Message message : messages) {
16 | System.out.printf("[%s] %s: \n%s\n",
17 | message.getCreatedTime().format(DateTimeFormatter.ofPattern("MM/dd hh:mm")),
18 | message.getAuthor(), message.getContent());
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/v2/DiscordMessenger.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.Message;
4 |
5 | import java.time.format.DateTimeFormatter;
6 | import java.util.List;
7 |
8 | /**
9 | * @author - johnny850807@gmail.com (Waterball)
10 | */
11 | public class DiscordMessenger implements Messenger {
12 | @Override
13 | public void send(List messages) {
14 | System.out.println("以下訊息已經送到了 Discord ...");
15 | for (Message message : messages) {
16 | System.out.printf("[%s] %s: \n%s\n",
17 | message.getCreatedTime().format(DateTimeFormatter.ofPattern("MM/dd hh:mm")),
18 | message.getAuthor(), message.getContent());
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/v2/EmailFormatting.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.Message;
4 |
5 | import java.util.List;
6 |
7 | import static java.lang.String.format;
8 | import static java.util.stream.Collectors.toUnmodifiableList;
9 |
10 | /**
11 | * @author - johnny850807@gmail.com (Waterball)
12 | */
13 | public class EmailFormatting extends MessageProcessor {
14 | public EmailFormatting(Messenger next) {
15 | super(next);
16 | }
17 |
18 | @Override
19 | public void send(List messages) {
20 | messages = messages
21 | .stream().map(this::mailFormatting)
22 | .collect(toUnmodifiableList());
23 |
24 | next.send(messages);
25 | }
26 |
27 |
28 | private Message mailFormatting(Message message) {
29 | return message.edit(format("Dear %s,\n\n%s\n\nBest regards,\n%s",
30 | message.getTargetName(), message.getContent(), message.getAuthorName()));
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/v2/Main.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.Email;
4 | import commons.Message;
5 | import commons.User;
6 |
7 | public class Main {
8 | public static void main(String[] args) {
9 | User waterball = new User(new Email("johnny", "waterballsa.tw"), "水球");
10 | User tsen = new User(new Email("tsen", "waterballsa.tw"), "岑岑");
11 | Message message = new Message(waterball, tsen,
12 | "Could you tell the following people (wally@waterballsa.tw, fixiabis@waterballsa.tw, fong-putao@waterballsa.tw)\n\n" +
13 | "that I'm gonna take a leave today? Thanks!"
14 | );
15 |
16 | System.out.println("====== EmailFormattingAndParagraphingMessenger =====");
17 | new EmailFormatting(new Paragraphing(new DiscordMessenger())).send(message);
18 | System.out.println("\n====== EmailHidingAndParagraphingMessenger =====");
19 | new HideEmails(new Paragraphing(new ConsoleMessenger())).send(message);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/v2/MessageProcessor.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public abstract class MessageProcessor implements Messenger {
7 | protected Messenger next;
8 | public MessageProcessor(Messenger next) {
9 | this.next = next;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/v2/Messenger.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.Message;
4 |
5 | import java.util.List;
6 |
7 | import static java.util.Collections.singletonList;
8 |
9 | /**
10 | * @author - johnny850807@gmail.com (Waterball)
11 | */
12 | public interface Messenger {
13 | default void send(Message message) {
14 | send(singletonList(message));
15 | }
16 | void send(List messages);
17 | }
18 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/v2/Paragraphing.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.Message;
4 |
5 | import java.util.List;
6 |
7 | import static java.util.Arrays.stream;
8 | import static java.util.stream.Collectors.toList;
9 | import static java.util.stream.Collectors.toUnmodifiableList;
10 |
11 | /**
12 | * @author - johnny850807@gmail.com (Waterball)
13 | */
14 | public class Paragraphing extends MessageProcessor {
15 | public Paragraphing(Messenger next) {
16 | super(next);
17 | }
18 |
19 | @Override
20 | public void send(List messages) {
21 | messages = messages
22 | .stream().flatMap(msg -> paragraph(msg).stream())
23 | .collect(toUnmodifiableList());
24 |
25 | next.send(messages);
26 | }
27 |
28 | private List paragraph(Message message) {
29 | return stream(message.getContent().split("\n\n"))
30 | .map(message::edit)
31 | .collect(toList());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-裝飾者模式/v2/SendMessagesRequest.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import commons.Message;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * @author - johnny850807@gmail.com (Waterball)
9 | */
10 | public class SendMessagesRequest {
11 | private final List messages;
12 |
13 | public SendMessagesRequest(List messages) {
14 | this.messages = messages;
15 | }
16 |
17 | public List getMessages() {
18 | return messages;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/.idea/discord.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/utils/ValidationUtils.java:
--------------------------------------------------------------------------------
1 | package utils;
2 |
3 | import java.util.regex.Pattern;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class ValidationUtils {
9 | public static String shouldMatch(String regex, String content) {
10 | if (!Pattern.matches(regex, content)) {
11 | throw new IllegalArgumentException(
12 | String.format("Content '%s' doesn't match '%s'",
13 | content, regex));
14 | }
15 | return content;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/v1/File.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import static utils.ValidationUtils.shouldMatch;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class File {
9 | private Directory parent;
10 | private final String name;
11 | private final byte[] content;
12 |
13 | public File(String name, String content) {
14 | this.name = shouldMatch("[A-Za-z0-9.\\-_]+", name);
15 | this.content = content.getBytes();
16 | }
17 |
18 | public String getName() {
19 | return name;
20 | }
21 |
22 | public long bytes() {
23 | return content.length;
24 | }
25 |
26 | public Directory getParent() {
27 | return parent;
28 | }
29 |
30 | public void setParent(Directory parent) {
31 | this.parent = parent;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/v1/Main.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Main {
7 | public static void main(String[] args) {
8 | Directory root = Directory.root();
9 | Directory document = new Directory("document");
10 | Directory notes = new Directory("notes");
11 | root.addDirectory(document);
12 | document.addDirectory(notes);
13 | root.addFile(new File("me.txt", "Hello, I'm Waterball."));
14 | notes.addFile(new File("meeting-0825.txt", "Lauren: To be or not to be."));
15 | notes.addFile(new File("meeting-0824.txt", "Waterball: Composition over Inheritance."));
16 |
17 | CLI cli = new CLI(root);
18 | cli.start();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/v2/File.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import java.util.Collections;
4 | import java.util.List;
5 |
6 | import static java.util.Collections.emptyList;
7 | import static utils.ValidationUtils.shouldMatch;
8 |
9 | /**
10 | * @author - johnny850807@gmail.com (Waterball)
11 | */
12 | public class File extends Item {
13 | private final byte[] content;
14 |
15 | public File(String name, String content) {
16 | super(name);
17 | this.content = content.getBytes();
18 | }
19 |
20 | public String getName() {
21 | return name;
22 | }
23 |
24 | @Override
25 | public long totalBytes() {
26 | return content.length;
27 | }
28 |
29 | @Override
30 | public List- search(String keyword) {
31 | return emptyList();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/v2/Item.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import java.util.List;
4 |
5 | import static utils.ValidationUtils.shouldMatch;
6 |
7 | /**
8 | * @author - johnny850807@gmail.com (Waterball)
9 | */
10 | public abstract class Item {
11 | protected final String name;
12 | protected Directory parent;
13 |
14 | public Item(String name) {
15 | this.name = shouldMatch("[A-Za-z0-9.\\-_]+", name);
16 | }
17 |
18 | public abstract long totalBytes();
19 |
20 | public abstract List
- search(String keyword);
21 |
22 | public void setParent(Directory parent) {
23 | this.parent = parent;
24 | }
25 |
26 | public String getName() {
27 | return name;
28 | }
29 |
30 | public Directory getParent() {
31 | return parent;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-複合模式/v2/Main.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Main {
7 | public static void main(String[] args) {
8 | Directory root = Directory.root();
9 | Directory document = new Directory("document");
10 | Directory notes = new Directory("notes");
11 | root.addDirectory(document);
12 | document.addDirectory(notes);
13 | root.addFile(new File("me.txt", "Hello, I'm Waterball."));
14 | notes.addFile(new File("meeting-0825.txt", "Lauren: To be or not to be."));
15 | notes.addFile(new File("meeting-0824.txt", "Waterball: Composition over Inheritance."));
16 |
17 | CLI cli = new CLI(root);
18 | cli.start();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/.idea/discord.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/.idea/libraries/Maven__org_jsoup_jsoup_1_15_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | tw.wateballsa.design-pattern
8 | c4m2s1
9 | 1.0-SNAPSHOT
10 |
11 |
12 | 11
13 | 11
14 |
15 |
16 |
17 |
18 | org.jsoup
19 | jsoup
20 | 1.15.2
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/v1and2/Main.java:
--------------------------------------------------------------------------------
1 | package v1and2;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class Main {
7 | public static void main(String[] args) {
8 | VocabLookupCLI cli = new VocabLookupCLI(new VocabCrawlerAdapter());
9 | cli.start();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/v1and2/VocabDictionary.java:
--------------------------------------------------------------------------------
1 | package v1and2;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public interface VocabDictionary {
9 |
10 | /**
11 | * @param wordSpelling the exact whole spelling of the word
12 | * @return the word that exactly matches that spelling
13 | */
14 | Word lookup(String wordSpelling) throws WordNotExistsException;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/v1and2/VocabLookupCLI.java:
--------------------------------------------------------------------------------
1 | package v1and2;
2 |
3 | import java.util.Scanner;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class VocabLookupCLI {
9 | private static final Scanner in = new Scanner(System.in);
10 | private final VocabDictionary dictionary;
11 |
12 | public VocabLookupCLI(VocabDictionary dictionary) {
13 | this.dictionary = dictionary;
14 | }
15 |
16 | public void start() {
17 | while (true) {
18 | System.out.println("Lookup a word: ");
19 | String spelling = in.nextLine();
20 | if (!spelling.isBlank()) {
21 | try {
22 | Word word = dictionary.lookup(spelling);
23 | System.out.println(word);
24 | } catch (WordNotExistsException e) {
25 | System.out.printf("Can't find the word '%s'.\n", spelling);
26 | }
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/v1and2/WordNotExistsException.java:
--------------------------------------------------------------------------------
1 | package v1and2;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class WordNotExistsException extends RuntimeException {
7 | private final String wordSpelling;
8 | public WordNotExistsException(String wordSpelling, Exception e) {
9 | super(e);
10 | this.wordSpelling = wordSpelling;
11 | }
12 |
13 | public String getWordSpelling() {
14 | return wordSpelling;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/v1and2/crawler/SuperWORD.java:
--------------------------------------------------------------------------------
1 | package v1and2.crawler;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class SuperWORD {
9 | public String raw;
10 | public List definitions; // format:
11 |
12 | public SuperWORD(String raw, List definitions) {
13 | this.raw = raw;
14 | this.definitions = definitions;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-轉接器模式/v1and2/crawler/YouSpellItWrongException.java:
--------------------------------------------------------------------------------
1 | package v1and2.crawler;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public class YouSpellItWrongException extends Exception {
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/.idea/discord.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/data.table:
--------------------------------------------------------------------------------
1 | | Id | Name | Cost | Revenue |
2 | |---------|-------------|---------|-----------|
3 | | 1 | Waterball | 20 | 0 |
4 | | 2 | Lauren | 200000 | 2000 |
5 | | 3 | Eric | 150 | 5000 |
6 | | 4 | Steven | 150 | 3000 |
7 | | 5 | Timm | 300 | 300 |
8 | | 6 | Saker | 150 | 2000 |
9 | | 7 | Steven | 300 | 2000 |
10 | | 8 | Snowman | 150 | 2000 |
11 | | 9 | Jack | 150 | 2000 |
12 | | 10 | Victor | 150 | 2000 |
13 | | 11 | Rumiu | 150 | 2000 |
14 | | 12 | Mily | 150 | 2000 |
15 | | 13 | Winnie | 150 | 2000 |
16 | | 14 | Shengpo | 200 | 2000 |
17 | | 15 | Adam | 150 | 2000 |
18 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v1/Main.java:
--------------------------------------------------------------------------------
1 | package v1;
2 |
3 | import v1.lib.CountRows;
4 | import v1.lib.MarkdownParser;
5 | import v1.lib.Table;
6 | import v1.lib.TableStatsPerformer;
7 | import v1.lib.TotalColumn;
8 |
9 | import java.io.IOException;
10 |
11 | /**
12 | * @author - johnny850807@gmail.com (Waterball)
13 | */
14 | public class Main {
15 | public static void main(String[] args) throws IOException {
16 | MarkdownParser parser = new MarkdownParser();
17 | Table table = parser.parseTableFromFile("data.table");
18 | TableStatsPerformer statsPerformer = new TableStatsPerformer();
19 | statsPerformer.addStatsOperation(new TotalColumn("Cost"));
20 | statsPerformer.addStatsOperation(new CountRows("Members"));
21 | statsPerformer.print(table);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v1/lib/CountRows.java:
--------------------------------------------------------------------------------
1 | package v1.lib;
2 |
3 | import static java.lang.String.format;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class CountRows implements StatsOperation {
9 | public CountRows(String statsName) {
10 | this.rowName = statsName;
11 | }
12 |
13 | private final String rowName;
14 | @Override
15 | public String getName() {
16 | return format("Count %s", rowName);
17 | }
18 |
19 | @Override
20 | public Object perform(Table table) {
21 | return table.getData().size();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v1/lib/MarkdownParser.java:
--------------------------------------------------------------------------------
1 | package v1.lib;
2 |
3 |
4 | import java.io.IOException;
5 | import java.nio.file.Paths;
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | import static java.nio.file.Files.readString;
10 | import static java.util.Arrays.asList;
11 |
12 | /**
13 | * @author - johnny850807@gmail.com (Waterball)
14 | */
15 | public class MarkdownParser {
16 | public Table parseTableFromFile(String fileName) throws IOException {
17 | String markdown = readString(Paths.get(fileName));
18 | String[] lines = markdown.split("\n");
19 | List> fields = new ArrayList<>();
20 | fields.add(parseRow(0, lines));
21 | for (int i = 2; i < lines.length; i++) {
22 | fields.add(parseRow(i, lines));
23 | }
24 | return new Table(fields);
25 | }
26 |
27 | private List parseRow(int i, String[] lines) {
28 | return asList(lines[i].replaceFirst("[|\\s]+", "")
29 | .split("[|\\s]+"));
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v1/lib/StatsOperation.java:
--------------------------------------------------------------------------------
1 | package v1.lib;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public interface StatsOperation {
7 | String getName();
8 | Object perform(Table table);
9 | }
10 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v1/lib/Table.java:
--------------------------------------------------------------------------------
1 | package v1.lib;
2 |
3 | import java.util.List;
4 |
5 | import static java.util.stream.Collectors.toList;
6 |
7 | /**
8 | * @author - johnny850807@gmail.com (Waterball)
9 | */
10 | public class Table {
11 | private final List header;
12 | private final List> data;
13 |
14 | public Table(List> data) {
15 | this.header = data.get(0);
16 | this.data = data;
17 | }
18 |
19 | public List getColumn(String fieldName) {
20 | int column = header.indexOf(fieldName);
21 | return data.stream()
22 | .skip(1) // skip the header
23 | .map(row -> row.get(column)).collect(toList());
24 | }
25 |
26 | public List getRow(int row) {
27 | return data.get(row);
28 | }
29 |
30 | public List> getRows() {
31 | return data.subList(1 /*skip the header*/, data.size());
32 | }
33 |
34 | public List> getData() {
35 | return data;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v1/lib/TableStatsPerformer.java:
--------------------------------------------------------------------------------
1 | package v1.lib;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * @author - johnny850807@gmail.com (Waterball)
8 | */
9 | public class TableStatsPerformer {
10 | private final List statsOperations = new ArrayList<>();
11 |
12 | public void addStatsOperation(StatsOperation statsOperation) {
13 | statsOperations.add(statsOperation);
14 | }
15 |
16 | public void print(Table table) {
17 | StringBuilder stats = new StringBuilder();
18 | for (StatsOperation operation : statsOperations) {
19 | stats.append(operation.getName()).append(": ")
20 | .append(operation.perform(table)).append("\n");
21 | }
22 | System.out.println(stats);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v1/lib/TotalColumn.java:
--------------------------------------------------------------------------------
1 | package v1.lib;
2 |
3 | import static java.lang.String.format;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class TotalColumn implements StatsOperation {
9 | private final String fieldName;
10 |
11 | public TotalColumn(String fieldName) {
12 | this.fieldName = fieldName;
13 | }
14 |
15 | @Override
16 | public String getName() {
17 | return format("Total %s", fieldName);
18 | }
19 |
20 | @Override
21 | public Object perform(Table table) {
22 | return table.getColumn(fieldName)
23 | .stream().mapToDouble(Double::parseDouble)
24 | .sum();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v2/Main.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import java.io.IOException;
4 |
5 | import static v2.StatsFacade.COUNT_MEMBERS;
6 | import static v2.StatsFacade.TOTAL_COST;
7 |
8 | /**
9 | * @author - johnny850807@gmail.com (Waterball)
10 | */
11 | public class Main {
12 | public static void main(String[] args) throws IOException {
13 | StatsFacade statsFacade = new StatsFacade();
14 | statsFacade.printMarkdownTableStats("data.table",
15 | TOTAL_COST | COUNT_MEMBERS);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v2/StatsFacade.java:
--------------------------------------------------------------------------------
1 | package v2;
2 |
3 | import v2.lib.*;
4 |
5 | import java.io.IOException;
6 |
7 | /**
8 | * @author - johnny850807@gmail.com (Waterball)
9 | */
10 | public class StatsFacade {
11 | public static final int TOTAL_COST = 0x01;
12 | public static final int COUNT_MEMBERS = 0x01 << 1;
13 | private final MarkdownParser parser = new MarkdownParser();
14 |
15 | public void printMarkdownTableStats(String fileName, int statOpsFlag) throws IOException {
16 | Table table = parser.parseTableFromFile(fileName);
17 |
18 | TableStatsPerformer statsPerformer = new TableStatsPerformer();
19 |
20 | if ((statOpsFlag & TOTAL_COST) != 0) {
21 | statsPerformer.addStatsOperation(new TotalColumn("Cost"));
22 | }
23 | if ((statOpsFlag & COUNT_MEMBERS) != 0) {
24 | statsPerformer.addStatsOperation(new CountRows("Members"));
25 | }
26 |
27 | statsPerformer.print(table);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v2/lib/CountRows.java:
--------------------------------------------------------------------------------
1 | package v2.lib;
2 |
3 | import static java.lang.String.format;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class CountRows implements StatsOperation {
9 | public CountRows(String rowName) {
10 | this.rowName = rowName;
11 | }
12 |
13 | private final String rowName;
14 | @Override
15 | public String getName() {
16 | return format("Count %s", rowName);
17 | }
18 |
19 | @Override
20 | public Object perform(Table table) {
21 | return table.getData().size();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v2/lib/MarkdownParser.java:
--------------------------------------------------------------------------------
1 | package v2.lib;
2 |
3 |
4 | import java.io.IOException;
5 | import java.nio.file.Paths;
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | import static java.nio.file.Files.readString;
10 | import static java.util.Arrays.asList;
11 |
12 | /**
13 | * @author - johnny850807@gmail.com (Waterball)
14 | */
15 | public class MarkdownParser {
16 |
17 | public Table parseTableFromFile(String fileName) throws IOException {
18 | String markdown = readString(Paths.get(fileName));
19 | String[] lines = markdown.split("\n");
20 | List> fields = new ArrayList<>();
21 | fields.add(parseRow(0, lines));
22 | for (int i = 2; i < lines.length; i++) {
23 | fields.add(parseRow(i, lines));
24 | }
25 | return new Table(fields);
26 | }
27 |
28 | private List parseRow(int i, String[] lines) {
29 | return asList(lines[i].replaceFirst("[|\\s]+", "")
30 | .split("[|\\s]+"));
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v2/lib/StatsOperation.java:
--------------------------------------------------------------------------------
1 | package v2.lib;
2 |
3 | /**
4 | * @author - johnny850807@gmail.com (Waterball)
5 | */
6 | public interface StatsOperation {
7 | String getName();
8 | Object perform(Table table);
9 | }
10 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v2/lib/Table.java:
--------------------------------------------------------------------------------
1 | package v2.lib;
2 |
3 | import java.util.List;
4 |
5 | import static java.util.stream.Collectors.toList;
6 |
7 | /**
8 | * @author - johnny850807@gmail.com (Waterball)
9 | */
10 | public class Table {
11 | private final List header;
12 | private final List> data;
13 |
14 | public Table(List> data) {
15 | this.header = data.get(0);
16 | this.data = data;
17 | }
18 |
19 | public List getColumn(String fieldName) {
20 | int column = header.indexOf(fieldName);
21 | return data.stream()
22 | .skip(1) // skip the header
23 | .map(row -> row.get(column)).collect(toList());
24 | }
25 |
26 | public List getRow(int row) {
27 | return data.get(row);
28 | }
29 |
30 | public List> getRows() {
31 | return data.subList(1 /*skip the header*/, data.size());
32 | }
33 |
34 | public List> getData() {
35 | return data;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v2/lib/TableStatsPerformer.java:
--------------------------------------------------------------------------------
1 | package v2.lib;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * @author - johnny850807@gmail.com (Waterball)
8 | */
9 | public class TableStatsPerformer {
10 | private final List statsOperations = new ArrayList<>();
11 |
12 | public void addStatsOperation(StatsOperation statsOperation) {
13 | statsOperations.add(statsOperation);
14 | }
15 |
16 | public void print(Table table) {
17 | StringBuilder stats = new StringBuilder();
18 | for (StatsOperation operation : statsOperations) {
19 | stats.append(operation.getName()).append(": ")
20 | .append(operation.perform(table)).append("\n");
21 | }
22 | System.out.println(stats);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/c4-規模化架構思維/景點-門面模式/v2/lib/TotalColumn.java:
--------------------------------------------------------------------------------
1 | package v2.lib;
2 |
3 | import static java.lang.String.format;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class TotalColumn implements StatsOperation {
9 | private final String fieldName;
10 |
11 | public TotalColumn(String fieldName) {
12 | this.fieldName = fieldName;
13 | }
14 |
15 | @Override
16 | public String getName() {
17 | return format("Total %s", fieldName);
18 | }
19 |
20 | @Override
21 | public Object perform(Table table) {
22 | return table.getColumn(fieldName)
23 | .stream().mapToDouble(Double::parseDouble)
24 | .sum();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/remaining-budget:
--------------------------------------------------------------------------------
1 | 50
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/script.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "name": "and",
4 | "children": [
5 | {
6 | "name": "echo",
7 | "args": ["Hello World"]
8 | },
9 | {
10 | "name": "repeat",
11 | "args": [3],
12 | "children": [
13 | {
14 | "name": "echo",
15 | "args": ["Yo"]
16 | }
17 | ]
18 | }
19 | ]
20 | }
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/src/main/java/Main.java:
--------------------------------------------------------------------------------
1 | import app.sdk.v1.ChatBot;
2 |
3 | import java.io.IOException;
4 |
5 | /**
6 | * @author - johnny850807@gmail.com (Waterball)
7 | */
8 | public class Main {
9 | public static void main(String[] args) throws IOException {
10 | ChatBot chatBot = new ChatBot();
11 | String chat = chatBot.chat("水球軟體學院想要名正言順地串接你這個猛 AI 到學院" +
12 | "Discord 中應用,說說你第一個最想被應用的地方吧!(我們有2200人和各種論壇喔)!)");
13 | System.out.println(chat);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/src/main/java/app/discord/Channel.java:
--------------------------------------------------------------------------------
1 | package app.discord;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class Channel {
7 | public void sendResponse(ChatMessageResponse chatMessageResponse) {
8 |
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/src/main/java/app/discord/ChatMessageResponse.java:
--------------------------------------------------------------------------------
1 | package app.discord;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class ChatMessageResponse {
7 | public ChatMessageResponse(String response) {
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/src/main/java/app/discord/Events.java:
--------------------------------------------------------------------------------
1 | package app.discord;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class Events {
7 | public static class MessageEvent {
8 | public String getContent() {
9 | return null;
10 | }
11 |
12 | public String getUsername() {
13 | return null;
14 | }
15 | }
16 | public static class InquiryEvent {}
17 | }
18 |
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/src/main/java/app/fb/Bot.java:
--------------------------------------------------------------------------------
1 | package app.fb;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class Bot {
7 | public void addMessage(String message) {
8 |
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/src/main/java/app/fb/Cart.java:
--------------------------------------------------------------------------------
1 | package app.fb;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class Cart {
7 | public int getSize() {
8 | return 0;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/src/main/java/app/fb/Client.java:
--------------------------------------------------------------------------------
1 | package app.fb;
2 |
3 | /**
4 | * @author johnny@waterballsa.tw
5 | */
6 | public class Client {
7 | public Bot getBot() {
8 | return null;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/src/main/java/app/fb/ECommercePlatformBot.java:
--------------------------------------------------------------------------------
1 | package app.fb;
2 |
3 | import app.fb.Events.AddToCartEvent;
4 | import app.sdk.v1.ChatBot;
5 |
6 | import java.io.IOException;
7 | import java.nio.file.Files;
8 | import java.nio.file.Path;
9 |
10 | import static java.lang.String.format;
11 |
12 | /**
13 | * @author johnny@waterballsa.tw
14 | */
15 | public class ECommercePlatformBot {
16 | private final static String thingsBotNeedToKnow = readContext();
17 | private final static ChatBot chatBot = new ChatBot();
18 | private static String readContext() {
19 | try {
20 | return Files.readString(Path.of("EC-Things-Bot-Need-To-Know"));
21 | } catch (IOException e) {
22 | throw new RuntimeException(e);
23 | }
24 | }
25 |
26 | public void reactToEvent(AddToCartEvent event) {
27 | Cart cart = event.getCart();
28 | if (cart.getSize() % 3 == 0) {
29 | String suggestion =chatBot.chat(format("%s 剛剛將 %s 加入購物車,現在已經買了 %d 項商品,你覺得他可能還想買哪一項商品?推一項吧。",
30 | event.getUsername(), event.getProductName(), cart.getSize()));
31 |
32 | Client client = event.getUserClient();
33 | client.getBot().addMessage(suggestion);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/src/main/java/app/fb/Events.java:
--------------------------------------------------------------------------------
1 | package app.fb;
2 |
3 | import java.awt.*;
4 |
5 | /**
6 | * @author johnny@waterballsa.tw
7 | */
8 | public class Events {
9 | public static class AddToCartEvent {
10 | public String getContent() {
11 | return null;
12 | }
13 |
14 | public String getUsername() {
15 | return null;
16 | }
17 |
18 | public Cart getCart() {
19 | return null;
20 | }
21 |
22 | public String getProductName() {
23 | return null;
24 | }
25 |
26 | public Client getUserClient() {
27 | return null;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/src/main/java/app/sdk/v2/Main.java:
--------------------------------------------------------------------------------
1 | package app.sdk.v2;
2 |
3 |
4 | /**
5 | * @author johnny@waterballsa.tw
6 | */
7 | public class Main {
8 | public static void main(String[] args) {
9 | ChatBot chatBot = ChatBot.getInstance();
10 |
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/c5-生命週期及控制反轉/景點-單體模式/src/main/java/lib/commands/AndCommand.java:
--------------------------------------------------------------------------------
1 | package lib.commands;
2 |
3 | import lib.ioc.Command;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * @author - johnny850807@gmail.com (Waterball)
9 | */
10 | public class AndCommand implements Command {
11 | private List children;
12 |
13 | @Override
14 | public int execute() {
15 | for (Command child : children) {
16 | int status = child.execute();
17 | if (status != 0) {
18 | return status;
19 | }
20 | }
21 | return 0;
22 | }
23 |
24 | @Override
25 | public void setChildren(List children) {
26 | this.children = children;
27 | }
28 |
29 | @Override
30 | public void setArguments(List