2017年12月24日 星期日

7天學會設計模式 筆記

7天學會設計模式
http://www.books.com.tw/products/0010750585

chap01.
物件導向程式設計5項基本原則
SOLID
S:Single Responsbility Principle(SRP) 單一職責
O:Open/Close Principle(OCP) 開放/封閉原則
L:Liskov Substitution Principle (LSP) Liskov替換原則
I:Interface Segregation Principle(ISP) 介面隔離原則
D:Dependency Inversion Principle(DIP) 依賴反轉原則

chap02.
單例模式 Singleton
目的:保證一個類別只會產生一個物件,而且要提供存取物件的統一方法。

package com.ssc24.chap02.demo01;
public class Singleton {
private static Singleton instance = new Singleton();
 private Singleton() { 
 }
 public  static Singleton getInstance() {
  if (instance == null) {
   synchronized(Singleton.class) {
    instance = new Singleton();
   }
  }
  return instance;
 }
}


package com.ssc24.chap02.demo01;
public class SingletonGreed {
 private static SingletonGreed instance = new SingletonGreed();
 
 private SingletonGreed() {
 }
 public static SingletonGreed getInstance() {
  return instance;
 }
}

package com.ssc24.chap02.demo01;
public class SingletonTest extends Thread {
 String myId;
 public SingletonTest(String id){
  myId = id;
 }
 public void run() {
  Singleton singleton = Singleton.getInstance();
  if (singleton != null) {
   System.out.println(myId + "產生Singleton:" + singleton.hashCode());
  }
 }
 public static void main(String[] args) {
  /**
  Singleton s1 = Singleton.getInstance();
  Singleton s2 = Singleton.getInstance();
  System.out.println("S1:" + s1.hashCode() + "\nS2:" + s2.hashCode());
  */
  Thread t1 = new SingletonTest("執行緒T1");
  Thread t2 = new SingletonTest("執行緒T2");
  t1.start();
  t2.start();
 }
}
/**
執行緒T1產生Singleton:935563448
執行緒T2產生Singleton:935563448
**/


chap03.
簡單工廠模式 Simple Factory
目的:定義一個簡單工廠,傳入不同的參數取得不同的類別物件。

package com.ssc24.chap03.demo01;
public interface Adventurer {
 public String getType();
}

package com.ssc24.chap03.demo01;
public class Archer implements Adventurer {
 @Override
 public String getType() {
  System.out.println("我是弓箭手");
  return this.getClass().getSimpleName();
 }
}

package com.ssc24.chap03.demo01;
public class Warrior implements Adventurer {
 @Override
 public String getType() {
  System.out.println("我是戰士");
  return this.getClass().getSimpleName();
 }
}

package com.ssc24.chap03.demo01;
public class TrainingCampFactory {
 public static Adventurer trainAdventurer(String type) {
  switch (type) {
   case "archer": {
    System.out.println("弓箭手生產完成");
    return new Archer();
   }
   case "warrior" : {
    System.out.println("戰士生產完成");
    return new Warrior();
   }
   default:
    return null;
  }
 }
}

package com.ssc24.chap03.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
import junit.framework.Assert;
public class VillageTest {
 @SuppressWarnings("deprecation")
 @Test
 public void test() {
  Adventurer memberA = TrainingCampFactory.trainAdventurer("archer");
  Assert.assertEquals(memberA.getType(), "Archer");
  
  Adventurer memberB = TrainingCampFactory.trainAdventurer("warrior");
  Assert.assertEquals(memberB.getType(), "Warrior");
 }
}

/**
===簡單工廠模式測試===
弓箭手生產完成
我是弓箭手
戰士生產完成
我是戰士
**/



chap04.
工廠模式 Factory
目的:提供一個工廠介面,將產生實體的程式碼交由子類別各自實現。

package com.ssc24.chap04.demo01;
public interface Adventurer {
 public String getType();
}

package com.ssc24.chap04.demo01;
public class Archer implements Adventurer {
 @Override
 public String getType() {
  System.out.println("我是弓箭手");
  return this.getClass().getSimpleName();
 }
}

package com.ssc24.chap04.demo01;
public class Warrior implements Adventurer {
 @Override
 public String getType() {
  System.out.println("我是戰士");
  return this.getClass().getSimpleName();
 }
}

package com.ssc24.chap04.demo01;
public interface ITrainingCamp {
 public Adventurer trainAdventurer();
}

package com.ssc24.chap04.demo01;
public class ArcherTrainingCamp implements ITrainingCamp {
 @Override
 public Adventurer trainAdventurer() {
  System.out.println("產生一個弓箭手");
  return new Archer();
 }
}

package com.ssc24.chap04.demo01;
public class WarriorTrainingCamp implements ITrainingCamp {
 @Override
 public Adventurer trainAdventurer() {
  System.out.println("產生一個戰士");
  return new Warrior();
 }
}

package com.ssc24.chap04.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
import junit.framework.Assert;
public class TrainingCampTest {
 @Test
 public void test() {
  System.out.println("=========== 工廠模式測試 ===========");
  ITrainingCamp trainCamp = new ArcherTrainingCamp();
  Adventurer memberA = trainCamp.trainAdventurer();
  Assert.assertEquals(memberA.getType(), "Archer");
  trainCamp = new WarriorTrainingCamp();
  Adventurer memberB = trainCamp.trainAdventurer();
  Assert.assertEquals(memberB.getType(), "Warrior");
 }
}

/**
=========== 工廠模式測試 ===========
產生一個弓箭手
我是弓箭手
產生一個戰士
我是戰士
**/




chap05.
抽象工廠模式 Abstract Factory
目的:用一個工廠介面來產生一系列相關的物件,但實際建立哪些物件由實作工廠的子類別來實現。

package com.ssc24.chap05.demo01;
public abstract class Adventurer {
 public Weapon weapon;
 public Clothes clothes;
 public abstract void display();
 public Weapon getWeapon() {
  return weapon;
 }
 public void setWeapon(Weapon weapon) {
  this.weapon = weapon;
 }
 public Clothes getClothes() {
  return clothes;
 }
 public void setClothes(Clothes clothes) {
  this.clothes = clothes;
 }
}

package com.ssc24.chap05.demo01;
public class Archer extends Adventurer {
 @Override
 public void display() {
  System.out.println("我是弓箭手,裝備:");
  weapon.display();
  clothes.disPlay();
 }
}

package com.ssc24.chap05.demo01;
public class ArcherEquipFactory implements EquipFactory {
 @Override
 public Weapon productWeapon() {
  Bow product = new Bow();
  product.setAtk(10);
  product.setRange(10);
  return product;
 }
 @Override
 public Clothes productArmor() {
  Leather product = new Leather();
  product.setDef(5);
  return product;
 }
}

package com.ssc24.chap05.demo01;
public class ArcherTrainingCamp implements TrainingCamp {
 @Override
 public Adventurer trainAdventurer() {
  System.out.println("訓練一個弓箭手");
  Archer archer = new Archer();
  EquipFactory factory = new ArcherEquipFactory();
  archer.setWeapon(factory.productWeapon());
  archer.setClothes(factory.productArmor());
  return archer;
 }
}

package com.ssc24.chap05.demo01;
public class Armor extends Clothes {
}

package com.ssc24.chap05.demo01;
public class Bow extends Weapon {
}

package com.ssc24.chap05.demo01;
public abstract class Clothes {
 protected int def;
 public void disPlay() {
  System.out.println(this.getClass().getSimpleName() + "def=" + this.def);
 }
 public int getDef() {
  return def;
 }
 public void setDef(int def) {
  this.def = def;
 }
}

package com.ssc24.chap05.demo01;
public interface EquipFactory {
 Weapon productWeapon();
 Clothes productArmor();
}

package com.ssc24.chap05.demo01;
public class Leather extends Clothes {
}

package com.ssc24.chap05.demo01;
public class LongSword extends Weapon {
}

package com.ssc24.chap05.demo01;
public interface TrainingCamp {
 public Adventurer trainAdventurer();
}

package com.ssc24.chap05.demo01;
public class Warrior extends Adventurer {
 @Override
 public void display() {
  System.out.println("我是一個鬥士,裝備:");
  weapon.display();
  clothes.disPlay();
  
 }
}

package com.ssc24.chap05.demo01;
public class WarriorEquipFactory implements EquipFactory {
 @Override
 public Weapon productWeapon() {
  LongSword product = new LongSword();
  product.setAtk(10);
  product.setRange(1);
  return product;
 }
 @Override
 public Clothes productArmor() {
  Armor product = new Armor(); 
  product.setDef(10);
  return product;
 }
}

package com.ssc24.chap05.demo01;
public class WarriorTrainingCamp implements TrainingCamp {
 @Override
 public Adventurer trainAdventurer() {
  System.out.println("訓練一個鬥士");
  Warrior warrior = new Warrior();
  EquipFactory factory = new WarriorEquipFactory();
  warrior.setWeapon(factory.productWeapon());
  warrior.setClothes(factory.productArmor());
  return warrior;
 }
}

package com.ssc24.chap05.demo01;
public abstract class Weapon {
 protected int atk;
 protected int range;
 public void display() {
  System.out.println(this.getClass().getSimpleName() + 
    " atk=" + this.atk + " , range=" + this.range);
 }
 public int getAtk() {
  return atk;
 }
 public void setAtk(int atk) {
  this.atk = atk;
 }
 public int getRange() {
  return range;
 }
 public void setRange(int range) {
  this.range = range;
 }
}

package com.ssc24.chap05.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class EquipFactoryTest {
 @Test
 public void test() {
  System.out.println("===抽象工廠模式測試===");
//  EquipFactory equipFactory = new ArcherEquipFactory();
//  Clothes archerLeather =  equipFactory.productArmor();
//  Weapon archerBow = equipFactory.productWeapon();
  TrainingCamp archerCamp = new ArcherTrainingCamp();
  Adventurer archer = archerCamp.trainAdventurer();
  archer.display();
  TrainingCamp warriorCamp = new WarriorTrainingCamp();
  Adventurer warrior = warriorCamp.trainAdventurer();
  warrior.display();
 }
}

/**
===抽象工廠模式測試===
訓練一個弓箭手
我是弓箭手,裝備:
Bow atk=10 , range=10
Leatherdef=5
訓練一個鬥士
我是一個鬥士,裝備:
LongSword atk=10 , range=1
Armordef=10
**/



chap06.
策略模式 Strategy
目的:將各種可以互換的演算法(策略)包裝成一個類別。

package com.ssc24.chap06.demo01;
public class Adventurer {
 FightStrategy fightStrategy;
 public Adventurer() {
  System.out.println("冒險者");
 }
 public void attack() {
  if (fightStrategy == null) {
   fightStrategy = new NormalAttack();
  }
  fightStrategy.execute();
 }
 public void choiceStrategy(FightStrategy fightStrategy) {
  this.fightStrategy = fightStrategy;
 }
}

package com.ssc24.chap06.demo01;
public interface FightStrategy {
 void execute();
}

package com.ssc24.chap06.demo01;
public class NormalAttack implements FightStrategy {
 @Override
 public void execute() {
  System.out.println("使用一般攻擊");
 }
}

package com.ssc24.chap06.demo01;
public class UseItem implements FightStrategy {
 @Override
 public void execute() {
  System.out.println("使用道具,丟火把");

 }
}

package com.ssc24.chap06.demo01;
public class UseSkill implements FightStrategy {
 @Override
 public void execute() {
  System.out.println("使用超級痛的攻擊技能");

 }
}

package com.ssc24.chap06.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class FightStrategyTest {
 @Test
 public void test() {
  System.out.println("===策略模式測試===");
  Adventurer adventurer = new Adventurer();
  System.out.println("出現史萊姆");
  adventurer.attack();
  System.out.println("出現非常巨大的史萊姆");
  adventurer.choiceStrategy(new UseSkill());
  adventurer.attack();
  System.out.println("出現不怕刀槍的殭屍");
  adventurer.choiceStrategy(new UseItem());
  adventurer.attack();
 }
}

/**
===策略模式測試===
冒險者
出現史萊姆
使用一般攻擊
出現非常巨大的史萊姆
使用超級痛的攻擊技能
出現不怕刀槍的殭屍
使用道具,丟火把
**/


package com.ssc24.chap06.demo02;
import java.util.Comparator;
public class SortVillageByArea implements Comparator {
 @Override
 public int compare(Village o1, Village o2) {
  if (o1.area > o2.area){
   return 1;
  }
  if (o1.area < o2.area){
   return -1;
  }
  return 0;
 }
}

package com.ssc24.chap06.demo02;
import java.util.Comparator;
public class SortVillageById implements Comparator {
 @Override
 public int compare(Village o1, Village o2) {
  if (o1.id > o2.id){
   return 1;
  }
  if (o1.id < o2.id){
   return -1;
  }
  return 0;
 }
}

package com.ssc24.chap06.demo02;
import java.util.Comparator;
public class SortVillageByName implements Comparator {
 @Override
 public int compare(Village o1, Village o2) {
  if (o1.name.charAt(0) > o2.name.charAt(0)){
   return 1;
  }
  if (o1.name.charAt(0) < o2.name.charAt(0)){
   return -1;
  }
  return 0;
 }
}

package com.ssc24.chap06.demo02;
import java.util.Comparator;
public class SortVillageByPopulation implements Comparator {
 @Override
 public int compare(Village o1, Village o2) {
  if (o1.population > o2.population){
   return 1;
  }
  if (o1.population < o2.population){
   return -1;
  }
  return 0;
 }
}

package com.ssc24.chap06.demo02;
public class Village {
 public int id;
 public String name;
 public int population;
 public double area;
 public Village ( int id,String name,int population,double area){
  this.id = id;
  this.name = name;
  this.population = population;
  this.area = area;
 }
 public String toString(){
  return id + "." + name + "(人口:" + population + " 面積: " + area + ")"; 
 }
}

package com.ssc24.chap06.demo02;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class StrategyExample {
 public static void main(String[] args) {
  System.out.println("===裝飾者模式 測試===");
  Village appleFarm = new Village(3, "apple farm", 32, 5.1);
  Village barnField = new Village(1, "barn field", 22, 1.7);
  Village capeValley = new Village(2, "cape valley", 10, 10.2);
  List villages = new ArrayList();
  villages.add(appleFarm);
  villages.add(barnField);
  villages.add(capeValley);
  System.out.println("沒排序過");
  showList(villages);
  System.out.println("根據ID排序");
  Collections.sort(villages,new SortVillageById());
  showList(villages);
  System.out.println("根據名字排序");
  Collections.sort(villages,new SortVillageByName());
  showList(villages);
  System.out.println("根據人口排序");
  Collections.sort(villages,new SortVillageByPopulation());
  showList(villages);
  System.out.println("根據面積排序");
  Collections.sort(villages,new SortVillageByArea());
  showList(villages);
 }
 public static void showList(List list) {
  for (Village v : list) {
   System.out.println(v);
  }
 }
}

/**
===裝飾者模式 測試===
沒排序過
3.apple farm(人口:32 面積: 5.1)
1.barn field(人口:22 面積: 1.7)
2.cape valley(人口:10 面積: 10.2)
根據ID排序
1.barn field(人口:22 面積: 1.7)
2.cape valley(人口:10 面積: 10.2)
3.apple farm(人口:32 面積: 5.1)
根據名字排序
3.apple farm(人口:32 面積: 5.1)
1.barn field(人口:22 面積: 1.7)
2.cape valley(人口:10 面積: 10.2)
根據人口排序
2.cape valley(人口:10 面積: 10.2)
1.barn field(人口:22 面積: 1.7)
3.apple farm(人口:32 面積: 5.1)
根據面積排序
1.barn field(人口:22 面積: 1.7)
3.apple farm(人口:32 面積: 5.1)
2.cape valley(人口:10 面積: 10.2)
**/



chap07
裝飾者模式 Decorator
目的:動態的將功能附加在物件上

package com.ssc24.chap07.demo01;
public interface Adventurer {
 void attack();
}

package com.ssc24.chap07.demo01;
public class Lancer implements Adventurer {
 private String name;
 public Lancer(String name) {
  this.name = name;
 }
 @Override
 public void attack() {
  System.out.println(" 長槍攻擊  by " + this.name);

 }
}

package com.ssc24.chap07.demo01;
public abstract class Title implements Adventurer {
 protected Adventurer adventure;
 public Title(Adventurer adventure) {
  this.adventure = adventure;
 }
 @Override
 public void attack() {
  adventure.attack();

 }
}

package com.ssc24.chap07.demo01;
public class TitleAgile extends Title {
 public TitleAgile(Adventurer adventure) {
  super(adventure);
 }
 @Override
 public void attack() {
  System.out.print(" 快速 ");
  super.attack();
 }
 public void useFlash() {
  System.out.println(" 使用瞬間移動 ");
 }
}

package com.ssc24.chap07.demo01;
public class TitleInFire extends Title {
 public TitleInFire(Adventurer adventure) {
  super(adventure);
 }
 @Override
 public void attack() {
  System.out.print(" 燃燒 ");
  super.attack();
 }
 public void fireball() {
  System.out.println(" 丟火球 ");
 }
}

package com.ssc24.chap07.demo01;
public class TitleStrong extends Title {
 public TitleStrong(Adventurer adventure) {
  super(adventure);
 }
 @Override
 public void attack() {
  System.out.print(" 猛力 ");
  super.attack();
 }
}

package com.ssc24.chap07.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class TitleTest {
 @Test
 public void test() {
  System.out.println("===裝飾者模式===");
  Adventurer lancer = new Lancer("Jacky");
  System.out.println("---長槍兵 Jacky---");
  lancer.attack();
  System.out.println();
  System.out.println("---取得強壯稱號的 Jacky---");
  TitleStrong strongJacky = new TitleStrong(lancer);
  strongJacky.attack();
  System.out.println();
  System.out.println("---取得敏捷號稱的Jacky---");
  TitleAgile agileJacky = new TitleAgile(strongJacky);
  agileJacky.attack();
  agileJacky.useFlash();
  System.out.println();
  System.out.println("---取得燃燒號稱的Jacky---");
  TitleInFire fireJacky = new TitleInFire(agileJacky);
  fireJacky.attack();
  fireJacky.fireball();
 }
}

/**
===裝飾者模式===
---長槍兵 Jacky---
 長槍攻擊  by Jacky

---取得強壯稱號的 Jacky---
 猛力  長槍攻擊  by Jacky

---取得敏捷號稱的Jacky---
 快速  猛力  長槍攻擊  by Jacky
 使用瞬間移動 

---取得燃燒號稱的Jacky---
 燃燒  快速  猛力  長槍攻擊  by Jacky
 丟火球 
**/




package com.ssc24.chap07.demo02;
import java.io.BufferedReader;
import java.io.Reader;
public class ReverseReader extends BufferedReader {
 public ReverseReader(Reader in) {
  super(in);
 }
 public String  reverse(String source) {
  String result = "";
  for (int i = 0;i < source.length(); i++ ) {
   result = source.charAt(i) + result;
  }
  return result;
 }
}

package com.ssc24.chap07.demo02;
import static org.junit.Assert.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import org.junit.Test;
public class JavaIOTest {
 @Test
 public void test() throws IOException {
  System.out.println("===FileReader讀取檔案===");
  File file = new File("D:/test.txt");
  FileReader reader = new FileReader(file);
  int c = 0;
  while ((c=reader.read()) >= 0) {
   System.out.print((char) c);
  }
  reader.close();
  System.out.println();
  System.out.println("===BufferedReader讀取檔案===");
  BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
  String line = "";
  while ((line = bufferedReader.readLine()) != null) {
   System.out.println(line);
  }
  bufferedReader.close();
  System.out.println();
  System.out.println("===Reverse Reader讀取檔案===");
  ReverseReader reverseReader = new ReverseReader(new FileReader(file));
  String rline = "";
  while ((rline = reverseReader.reverse(reverseReader.readLine())) != null) {
   System.out.println(rline);
  }
  reverseReader.close();
 }
}

/**
===FileReader讀取檔案===
apple pen
pineapple pen
===BufferedReader讀取檔案===
apple pen
pineapple pen

===Reverse Reader讀取檔案===
nep elppa
nep elppaenip
**/


chap08.
觀察者模式 Observer
目的:處理一個物件對應多個物件之間的連動關係

package com.ssc24.chap08.demo01;
public abstract class Adventurer {
 protected String name;
 public Adventurer(String name) {
  this.name = name;
 }
 public abstract void getQuestions(String questions);
}

package com.ssc24.chap08.demo01;
public class Association extends Subject {
 @Override
 public void sendQuestions(String questions) {
  for (Adventurer adventurer : list) {
   adventurer.getQuestions(questions);
  }
 }
}

package com.ssc24.chap08.demo01;
public class Bard extends Adventurer {
 public Bard(String name) {
  super(name);
 }
 @Override
 public void getQuestions(String questions) {
  if (questions.length() > 10) {
   System.out.println(this.name + ":任務太難了,我只會唱歌跳舞,不接不接");
  } else {
   System.out.println(this.name + ":當街頭藝人太難賺了,偶爾也要解任務賺點錢的");
  }
 }
}

package com.ssc24.chap08.demo01;
public class Gunman extends Adventurer {
 public Gunman(String name) {
  super(name);
 }
 @Override
 public void getQuestions(String questions) {
  if (questions.length() < 10) {
   System.out.println(this.name + ":任務太簡單了,我不想理他");
  } else {
   System.out.println(this.name + ":只要我的手上有槍,誰都殺不死我,出發執行任務賺獎金啦!!!");
  }
 }
}

package com.ssc24.chap08.demo01;
public class Lancer extends Adventurer {
 public Lancer(String name) {
  super(name);
 }
 @Override
 public void getQuestions(String questions) {
  System.out.println(this.name + " :單來就改,任務來就接,沒在怕的");
 }
}

package com.ssc24.chap08.demo01;
import java.util.ArrayList;
import java.util.List;
public abstract class Subject {
 protected List list = new ArrayList();
 public void add(Adventurer observer) {
  list.add(observer);
 }
 public void remove(Adventurer observer){
  list.remove(observer);
 }
 public abstract void sendQuestions(String question);
}

package com.ssc24.chap08.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class AssociationTest {
 @Test
 public void test() {
  System.out.println("===觀察者模式測試===");
  Adventurer lancer =  new Lancer("Jacky");
  Adventurer lancer2 = new Lancer("Seven");
  Adventurer bard = new Bard("Lee");
  Adventurer gunman = new Gunman("longWu");
  Subject association = new Association();
  association.add(lancer);
  association.add(lancer2);
  association.add(bard);
  association.add(gunman);
  System.out.println("===協會派送簡單任務===");
  association.sendQuestions("run");
  System.out.println("===協會派送複雜任務===");
  association.sendQuestions("run run run,run for your life");
  System.out.println("===協會派送複雜任務===");
  association.remove(lancer2);
  association.sendQuestions("run run run,run for your life");
 }
}

/**
===觀察者模式測試===
===協會派送簡單任務===
Jacky :單來就改,任務來就接,沒在怕的
Seven :單來就改,任務來就接,沒在怕的
Lee:當街頭藝人太難賺了,偶爾也要解任務賺點錢的
longWu:任務太簡單了,我不想理他
===協會派送複雜任務===
Jacky :單來就改,任務來就接,沒在怕的
Seven :單來就改,任務來就接,沒在怕的
Lee:任務太難了,我只會唱歌跳舞,不接不接
longWu:只要我的手上有槍,誰都殺不死我,出發執行任務賺獎金啦!!!
===協會派送複雜任務===
Jacky :單來就改,任務來就接,沒在怕的
Lee:任務太難了,我只會唱歌跳舞,不接不接
longWu:只要我的手上有槍,誰都殺不死我,出發執行任務賺獎金啦!!!
**/



chap09.
命令模式 Command
目的:將各種請求(命令Command)封裝成一個物件。

package com.ssc24.chap09.demo01;
public class Barkeep implements KitchenWorker {
 @Override
 public void finishOrder() {
  System.out.println("拿出杯子->加滿冰塊->把飲料倒進杯子->飲料完成");
 }
}

package com.ssc24.chap09.demo01;
public class Chef implements KitchenWorker {
 @Override
 public void finishOrder() {
  System.out.println("取出麵包->美乃滋塗上滿滿的麵包->丟進烤箱->灑上可以吃的裝飾->點心完成");
 }
}

package com.ssc24.chap09.demo01;
public abstract class Order {
 protected KitchenWorker receiver;
 protected String name;
 public Order(KitchenWorker receiver) {
  this.receiver = receiver;
 }
 public void sendOrder() {
  receiver.finishOrder();
 }
 public String getName() {
  return this.name;
 }
}

package com.ssc24.chap09.demo01;
public class SnackOrder extends Order {
 public SnackOrder(KitchenWorker receiver) {
  super(receiver);
  super.name = "snackOrder";
 }
}

package com.ssc24.chap09.demo01;
import java.util.ArrayList;
import java.util.List;
public class Waitress {
 private int snackQty = 2;
 private int drinkQty = 4;
 private List orderList = new ArrayList();
 public void setOrder(Order order) {
  if (order.name.equals("snackOrder")) {
   if (this.snackQty <= 0) {
    System.out.println("點心賣完了");
   } else {
    System.out.println("增加點心訂單");
    this.snackQty--;
    this.orderList.add(order);
   }
  }
  if (order.name.equals("drinkOrder")) {
   if (this.drinkQty <= 0) {
    System.out.println("影料賣完了");
   } else {
    System.out.println("增加飲料訂單");
    this.drinkQty--;
    this.orderList.add(order);
   }
  }
 } //end setOrder
 public void cancelOrder(Order order) {
  if (order.name.equals("snackOrder")) {
   this.snackQty++;
   System.out.println("取消一個點心");
  }
  if (order.name.equals("drinkOrder")) {
   this.drinkQty++;
   System.out.println("取消一杯飲料");
  }
  this.orderList.remove(order);
 } // end cancelOrder
 public void notifyBaker() {
  for (Order order :orderList) {
   order.sendOrder();
  }
  orderList.clear();
 }
}

package com.ssc24.chap09.demo01;
public class CoffeShopClient {
 public static void main(String[] args) {
  System.out.println("===命令模式測試===");
  Chef snackChef = new Chef();
  Barkeep barkeep = new Barkeep();
  Order snakOrder = new SnackOrder(snackChef);
  Order drinkOrder = new DrinkOrder(barkeep);
  Waitress cuteGirl = new Waitress();
  System.out.println("===客人點餐===");
  cuteGirl.setOrder(snakOrder);
  cuteGirl.setOrder(drinkOrder);
  cuteGirl.setOrder(snakOrder);
  cuteGirl.setOrder(drinkOrder);
  cuteGirl.setOrder(drinkOrder);
  cuteGirl.setOrder(drinkOrder);
  cuteGirl.notifyBaker();
  cuteGirl.setOrder(snakOrder);
  cuteGirl.setOrder(drinkOrder);
 }
}

/**
===命令模式測試===
===客人點餐===
增加點心訂單
增加飲料訂單
增加點心訂單
增加飲料訂單
增加飲料訂單
增加飲料訂單
取出麵包->美乃滋塗上滿滿的麵包->丟進烤箱->灑上可以吃的裝飾->點心完成
拿出杯子->加滿冰塊->把飲料倒進杯子->飲料完成
取出麵包->美乃滋塗上滿滿的麵包->丟進烤箱->灑上可以吃的裝飾->點心完成
拿出杯子->加滿冰塊->把飲料倒進杯子->飲料完成
拿出杯子->加滿冰塊->把飲料倒進杯子->飲料完成
拿出杯子->加滿冰塊->把飲料倒進杯子->飲料完成
點心賣完了
影料賣完了
**/


chap10.
轉接器模式 Adapter
目的:將個介面轉換成另外一個介面,讓原本與客戶端不能相容的介面可以正常工作

package com.ssc24.chap10.demo01;
public class Adapter implements Wizard {
 private Archer archer;
 public Adapter(Archer archer) {
  this.archer = archer;
 }
 @Override
 public void fireBall() {
  System.out.println("在弓箭上包一層布->淋上花生油->點火");
  this.archer.shot();
  System.out.println("火球飛出去了");
 }
}

package com.ssc24.chap10.demo01;
public interface Archer {
 void shot();
}

package com.ssc24.chap10.demo01;
public class NormalArcher implements Archer {
 public NormalArcher() {
  System.out.println("產生 一個弓箭手 ");
 }
 @Override
 public void shot() {
  System.out.println("射箭");
 }
}

package com.ssc24.chap10.demo01;
public interface Wizard {
 void fireBall();
}

package com.ssc24.chap10.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class AdapterClient {
 @Test
 public void test() {
  System.out.println("===轉接器模式測試===");
  System.out.println("我們需要火球才能把樹上的蜂窩砸爛,糟糕的是隊伍中沒有法師");
  System.out.println("幸好隊伍中有一個弓箭手跟馬蓋先工具包,讓弓箭手也能發火球");
  Wizard wizard = new Adapter(new NormalArcher());
  wizard.fireBall();
 }
}

/**
===轉接器模式測試===
我們需要火球才能把樹上的蜂窩砸爛,糟糕的是隊伍中沒有法師
幸好隊伍中有一個弓箭手跟馬蓋先工具包,讓弓箭手也能發火球
產生 一個弓箭手 
在弓箭上包一層布->淋上花生油->點火
射箭
火球飛出去了
**/



chap11.
表象(外觀)模式Facade
目的:用一個介面包裝各個子系統,由介面與客戶端做溝通。

package com.ssc24.chap11.demo01;
public abstract class Electronics {
 private  boolean power = false;
 public void powerOn() {
  this.power = true;
 }
 public void powerOff() {
  this.power = false;
 }
 public boolean  isPowerOn() {
  return this.power;
 }
 protected void showStatus() {
  if (this.power) {
   System.out.println(this.getClass().getSimpleName() + " 運作中");
  } else {
   System.out.println(this.getClass().getSimpleName() + " 電源未開啟");
  }
 }
}

package com.ssc24.chap11.demo01;
public class KTVsystem extends Electronics {
 private String song;
 public void selectSong(String song) {
  this.song = song;
 }
 public void playSong() {
  System.out.println(this.getClass().getSimpleName() + " 播放 " + this.song);
 }
}

package com.ssc24.chap11.demo01;
public class PlayStation3 extends Electronics {
 private String cd;
 public void putCd(String cd) {
  this.cd = cd;
 }
 public String getCd() {
  return this.cd;
 }
 public void play() {
  System.out.println(this.getClass().getSimpleName() + " 開始播放 " + this.cd);
 }
 @Override
 public void showStatus() {
  super.showStatus();
  if(isPowerOn()) {
   System.out.println(this.getClass().getSimpleName() + " 目前放入cd:" + this.cd);
  }
 }
}

package com.ssc24.chap11.demo01;
public class Stereo extends Electronics {
 private int sound = 50;
 public void setSound(int sound) {
  this.sound = sound;
 }
 public int getSound() {
  return this.sound;
 }
 @Override
 public void showStatus() {
  super.showStatus();
  if (isPowerOn()) {
   System.out.println(this.getClass().getSimpleName() + " 音量為:" + this.sound);
  }
 }
}

package com.ssc24.chap11.demo01;
public class Television extends Electronics {
 private int sound = 50;
 private String source = "tvBox";
 private int channel = 9;
 public void setSound(int sound) {
  this.sound = sound;
 }
 public void switchSource(String source) {
  this.source = source;
 }
 public void switchChannel(int channel) {
  this.channel = channel;
 }
 public void showTV() {
  System.out.println("目前觀看的頻道是: " + this.channel);
 }
 @Override
 public void showStatus() {
  super.showStatus();
  if (isPowerOn()) {
   System.out.print(this.getClass().getSimpleName() + " 音量為:" + this.sound);
   if ("tvBox".equals(this.source)) {
    System.out.println(" ,頻道:" + this.channel);
   }
   if ("ktv".equals(this.source)) {
    System.out.println(" ,ktv播放中:" + this.channel);
   }
   if ("ps".equals(this.source)) {
    System.out.println(" ,ps畫面顯示中:" + this.channel);
   }
  }
 }
 public int getSound() {
  return this.sound;
 }
 public int getSource() {
  return this.getSource();
 }
 public int getChannel() {
  return this.channel;
 }
}

package com.ssc24.chap11.demo01;
public class VideoRoomFacade {
 Television tv = new Television();
 Stereo stereo = new Stereo();
 PlayStation3 ps = new PlayStation3();
 KTVsystem ktv = new KTVsystem();
 public void readyPlayMovie(String cd) {
  this.stereo.powerOn();
  this.tv.powerOn();
  this.tv.setSound(50);
  this.tv.switchSource("ps");
  ps.powerOn();
  ps.putCd(cd);
 }
 public void playMovie() {
  if (ps.isPowerOn()) {
   ps.play();
  }
 }
 public void showTV() {
  this.tv.showTV();
 }
 public void turnOffAll() {
  this.stereo.powerOff();
  this.ktv.powerOff();
  this.ps.powerOff();
  this.tv.powerOff();
 }
 public void watchTv() {
  this.tv.powerOn();
  this.tv.switchSource("tvBox");
 }
 public void SwitchChannel(int channel) {
  this.tv.switchChannel(channel);
 }
 public void readyKTV() {
  this.stereo.powerOn();
  this.ktv.powerOn();
  this.tv.powerOn();
  this.tv.setSound(50);
  this.tv.switchSource("ktv");
 }
 public void selectSong(String song) {
  if(this.ktv.isPowerOn()) {
   this.ktv.selectSong(song);
  }
 }
 public void playSong() {
  if(this.ktv.isPowerOn()) {
   this.ktv.playSong();
  }
 }
 public void setSound(int soundLevel) {
  if (this.tv.isPowerOn()) {
   this.tv.setSound(soundLevel);
  }
  if(this.stereo.isPowerOn()) {
   this.stereo.setSound(soundLevel);
  }
 }
 public void showAllStatus() {
  this.tv.showStatus();
  this.stereo.showStatus();
  this.ps.showStatus();
  this.ktv.showStatus();
 }
}

/**
===外觀模式測試===
---看電影---
PlayStation3 開始播放 Life of Pi
Television 運作中
Television 音量為:50 ,ps畫面顯示中:9
Stereo 運作中
Stereo 音量為:50
PlayStation3 運作中
PlayStation3 目前放入cd:Life of Pi
KTVsystem 電源未開啟

---關機器---
Television 電源未開啟
Stereo 電源未開啟
PlayStation3 電源未開啟
KTVsystem 電源未開啟

---看電視---
目前觀看的頻道是: 9
目前觀看的頻道是: 20
Television 電源未開啟
Stereo 電源未開啟
PlayStation3 電源未開啟
KTVsystem 電源未開啟

---唱KTV---
KTVsystem 播放 Moon
Television 運作中
Television 音量為:50 ,ktv播放中:20
Stereo 運作中
Stereo 音量為:50
PlayStation3 電源未開啟
KTVsystem 運作中
Television 電源未開啟
Stereo 電源未開啟
PlayStation3 電源未開啟
KTVsystem 電源未開啟
**/



chap12.
樣版模式 Template
目的:定義一套演算法的架構,但是細節可延遲到子類別再決定。

package com.ssc24.chap12.demo01;
public abstract class Adventurer {
 protected int level;
 protected String type;
 public int getLevel() {
  return level;
 }
 public void setLevel(int level) {
  this.level = level;
 }
 public String getType() {
  return type;
 }
 public void setType(String type) {
  this.type = type;
 }
}

package com.ssc24.chap12.demo01;
public class DifficultMaze extends MazeTemplate {
 public DifficultMaze() {
  super.isDoubleMaze = true;
  super.difficulty = 50;
 }
 @Override
 void createMaze() {
  System.out.println("準備1000*1000的迷宮(包括隱藏迷宮)");
  System.out.println("安排打不完的小怪物");
  System.out.println("安排等級 50  的中BOSS,100隻");
  System.out.println("安排等級 120 的超級BOSS,放隱藏迷宮的寶物");
  System.out.println("拔草整理場地,重新油漆牆壁");
  System.out.println("擺放各種陷阱,擺放假屍體");
  System.out.println("困難迷宮準備完成");
 }
 @Override
 void start() {
  System.out.println("冒險者開始進行困難迷宮的冒險");

 }
}

package com.ssc24.chap12.demo01;
public class EazyMaze extends MazeTemplate {
 public EazyMaze() {
  super.difficulty = 1;
 }
 @Override
 void createMaze() {
  System.out.println("準備100*100的迷宮");
  System.out.println("安排10隻小怪物");
  System.out.println("安排等級10的Boss");
  System.out.println("拔草整理場地");
  System.out.println("簡易迷宮準備完成");

 }
 @Override
 void start() {
  System.out.println("冒險者開始進行簡單迷宮的冒險");
 }
}

package com.ssc24.chap12.demo01;
public class GundamJustice extends Adventurer {
 public GundamJustice() {
  super.type = "Gundam-Justice";
  super.level = 100;
 }
}

package com.ssc24.chap12.demo01;
public abstract class MazeTemplate {
 protected int difficulty;
 protected Adventurer adventurer;
 protected boolean isDoubleMaze = false;
 public Adventurer adventurer(Adventurer adventurer) {
  this.adventurer = adventurer;
  if (!this.checkLevel(adventurer.getLevel())) {
   System.out.println("冒險者等級不足,請提升等級至 " + this.difficulty + " 後開放迷宮");
  } else {
   System.out.println("---" + this.adventurer.getType() + " 開始進行困難度 " + this.difficulty + " 的迷宮");
   this.createMaze();
   this.start();
   
   if (isDoubleMaze) {
    this.hiddenMaze();
   }
   this.showReslt();
  }
  return this.adventurer;
 }
 private boolean checkLevel(int level) {
  if (level < this.difficulty) {
   return false;
  }
  return true;
 }
 abstract void createMaze();
 abstract void start();
 void hiddenMaze() {
  System.out.println("進入隱藏迷宮");
 }
 Adventurer showReslt() {
  this.adventurer.setLevel(this.adventurer.getLevel() + 50 * this.difficulty);
  System.out.println("---" + this.adventurer.getType() + " 完成困難度 " + this.difficulty + " 迷宮");
  return this.adventurer;
 }
}

package com.ssc24.chap12.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class MazeTest {
 Adventurer sabar = new Sabar();
 Adventurer justice = new GundamJustice();
 MazeTemplate easyMaze = new EazyMaze();
 MazeTemplate hardMaze = new DifficultMaze();
 @Test
 public void test() {
  System.out.println("===樣版模式測試===");
  System.out.println("===困難迷宮===");
  sabar = hardMaze.adventurer(sabar);
  System.out.println("===簡單迷宮練功===");
  sabar = easyMaze.adventurer(sabar);
  System.out.println();
  System.out.println("===困難迷宮測試====");
  sabar = hardMaze.adventurer(sabar);
  justice = hardMaze.adventurer(justice);
 }
}

/**
===樣版模式測試===
===困難迷宮===
冒險者等級不足,請提升等級至 50 後開放迷宮
===簡單迷宮練功===
---Saber 開始進行困難度 1 的迷宮
準備100*100的迷宮
安排10隻小怪物
安排等級10的Boss
拔草整理場地
簡易迷宮準備完成
冒險者開始進行簡單迷宮的冒險
---Saber 完成困難度 1 迷宮

===困難迷宮測試====
---Saber 開始進行困難度 50 的迷宮
準備1000*1000的迷宮(包括隱藏迷宮)
安排打不完的小怪物
安排等級 50  的中BOSS,100隻
安排等級 120 的超級BOSS,放隱藏迷宮的寶物
拔草整理場地,重新油漆牆壁
擺放各種陷阱,擺放假屍體
困難迷宮準備完成
冒險者開始進行困難迷宮的冒險
進入隱藏迷宮
---Saber 完成困難度 50 迷宮
---Gundam-Justice 開始進行困難度 50 的迷宮
準備1000*1000的迷宮(包括隱藏迷宮)
安排打不完的小怪物
安排等級 50  的中BOSS,100隻
安排等級 120 的超級BOSS,放隱藏迷宮的寶物
拔草整理場地,重新油漆牆壁
擺放各種陷阱,擺放假屍體
困難迷宮準備完成
冒險者開始進行困難迷宮的冒險
進入隱藏迷宮
---Gundam-Justice 完成困難度 50 迷宮
**/




chap13.
合成模式 Composite
目的:處理樹狀結構資料

package com.ssc24.chap13.demo01;
public abstract class AbstractAssociation {
 protected String name;
 public AbstractAssociation(String name) {
  this.name = name;
 }
 public abstract void add(AbstractAssociation a);
 public abstract void remove(AbstractAssociation a);
 public abstract void display(int depth);
 public abstract void lineOfDute();
}

package com.ssc24.chap13.demo01;
import java.util.ArrayList;
import java.util.List;
public class Association extends AbstractAssociation {
 private List branchs = new ArrayList();
 public Association(String name) {
  super(name);
 }
 @Override
 public void add(AbstractAssociation a) {
  branchs.add(a);
 }
 @Override
 public void remove(AbstractAssociation a) {
  branchs.remove(a);
 }
 @Override
 public void display(int depth) {
  for (int i =0 ; i < depth ; i++) {
   System.out.print("-");
  }
  System.out.println(name);
  for (AbstractAssociation a : branchs) {
   a.display(depth + 1);
  }
  //System.out.println("|");
 }
 @Override
 public void lineOfDute() {
  for (AbstractAssociation a : branchs) {
   a.lineOfDute();
  }
 }
}

package com.ssc24.chap13.demo01;
public abstract class Department extends AbstractAssociation {
 public Department(String name) {
  super(name);
 }
 @Override
 public void add(AbstractAssociation a) {
  System.out.println("Leaf無法增加子節點");
 }
 @Override
 public void remove(AbstractAssociation a) {
  System.out.println("Leaf無子節點可以移除");
 }
 @Override
 public void display(int depth) {
  for (int i =0 ; i < depth ; i++) {
   System.out.print("-");
  }
  //System.out.println("*");
  System.out.println(name);
 }
 @Override
 public abstract void lineOfDute();
}


package com.ssc24.chap13.demo01;
public class HumanResouce extends Department {
 public HumanResouce(String name) {
  super(name);
 }
 @Override
 public void lineOfDute() {
  System.out.println(name + " :想辦法拐騙冒險者來完成任務");
 }
}

package com.ssc24.chap13.demo01;
public class ServiceDepartment extends Department {
 public ServiceDepartment(String name) {
  super(name);
 }
 @Override
 public void lineOfDute() {
  System.out.println(name + " :處理客訴,告訴客戶,這肯定是冒險者的錯,不是協會的錯");
 }
}

package com.ssc24.chap13.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class BranchOrganizationTest {
 @Test
 public void test() {
  System.out.println("===合成模式測試===");
  AbstractAssociation root = new Association("冒險者總會");
  root.add(new HumanResouce("總會-人力資源單位"));
  root.add(new ServiceDepartment("總會-客服單位"));
  AbstractAssociation mars = new Association("火星分會");
  mars.add(new HumanResouce("火星分會-人力資源單位"));
  mars.add(new ServiceDepartment("火星分會-客服單位"));
  root.add(mars);
  AbstractAssociation saturn = new Association("土星分會");
  saturn.add(new HumanResouce("土星分會-人力資源單位"));
  saturn.add(new ServiceDepartment("土星分會-客服單位"));
  root.add(saturn);
  AbstractAssociation m1 = new Association("土衛1號辦事處");
  m1.add(new HumanResouce("土衛1號辦事處-人力資源單位"));
  m1.add(new ServiceDepartment("土衛1號辦事處-客服單位"));
  saturn.add(m1);
  AbstractAssociation m2 = new Association("土衛2號辦事處");
  m2.add(new HumanResouce("土衛2號辦事處-人力資源單位"));
  saturn.add(m2);
  System.out.println("結構圖:");
  root.display(1);
  System.out.println();
  System.out.println("職責表");
  root.lineOfDute();
  System.out.println();
  AbstractAssociation root2 = new HumanResouce("測試1");
  root2.remove(m2);
 }
}

/**
===合成模式測試===
結構圖:
-冒險者總會
--總會-人力資源單位
--總會-客服單位
--火星分會
---火星分會-人力資源單位
---火星分會-客服單位
--土星分會
---土星分會-人力資源單位
---土星分會-客服單位
---土衛1號辦事處
----土衛1號辦事處-人力資源單位
----土衛1號辦事處-客服單位
---土衛2號辦事處
----土衛2號辦事處-人力資源單位

職責表
總會-人力資源單位 :想辦法拐騙冒險者來完成任務
總會-客服單位 :處理客訴,告訴客戶,這肯定是冒險者的錯,不是協會的錯
火星分會-人力資源單位 :想辦法拐騙冒險者來完成任務
火星分會-客服單位 :處理客訴,告訴客戶,這肯定是冒險者的錯,不是協會的錯
土星分會-人力資源單位 :想辦法拐騙冒險者來完成任務
土星分會-客服單位 :處理客訴,告訴客戶,這肯定是冒險者的錯,不是協會的錯
土衛1號辦事處-人力資源單位 :想辦法拐騙冒險者來完成任務
土衛1號辦事處-客服單位 :處理客訴,告訴客戶,這肯定是冒險者的錯,不是協會的錯
土衛2號辦事處-人力資源單位 :想辦法拐騙冒險者來完成任務

Leaf無子節點可以移除
**/


chap14.
狀態模式 State
目的:將物件的狀態封裝成類別,讓此物件隨著狀態改變時能有不同的能力
缺點:狀態變動太大時,物件會瘋狂生成。

package com.ssc24.chap14.demo01;
public interface State {
 void move(Warrior warrior);
}

package com.ssc24.chap14.demo01;
public class DesperateState implements State {
 public DesperateState() {
  System.out.println(">>狀態改變,背水一戰");
 }
 @Override
 public void move(Warrior warrior) {
  int hp = warrior.getHp();
  if (hp == 0) {
   warrior.setState(new UnableState());
   warrior.move();
  } else if (hp > 30) {
   warrior.setState(new FuryState());
   warrior.move();
  } else {
   System.out.println("HP=" + warrior.getHp() + " ,背水一戰 傷害增加50%, 防禦增加50%");
  }
 }
}

package com.ssc24.chap14.demo01;
public class FuryState implements State {
 public FuryState() {
  System.out.println(">>狀態改變,狂怒狀態");
 }
 @Override
 public void move(Warrior warrior) {
  int hp = warrior.getHp();
  if (hp > 70) {
   warrior.setState(new NormalState());
   warrior.move();
  } else if (hp <= 30) {
   warrior.setState(new DesperateState());
   warrior.move();
  } else {
   System.out.println("HP=" + warrior.getHp() + " 狂怒狀態 傷害增加30%");
  }
 }
}

package com.ssc24.chap14.demo01;
public class NormalState implements State {
 public NormalState() {
  System.out.println(">>狀態改變,一般狀態");
 }
 @Override
 public void move(Warrior warrior) {
  if (warrior.getHp() > 70) {
   System.out.println("HP=" + warrior.getHp() + " ,一般狀態");
  } else {
   warrior.setState(new FuryState());
   warrior.move();
  }
 }
}

package com.ssc24.chap14.demo01;
public class UnableState implements State {
 public UnableState() {
  System.out.println(">>狀態改變,無法戰鬥");
 }
 @Override
 public void move(Warrior warrior) {
  System.out.println("HP=" + warrior.getHp() + " ,無法戰鬥");
 }
}

package com.ssc24.chap14.demo01;
public class Warrior {
 private int hp;
 private State state;
 public Warrior() {
  this.hp = 100;
  state = new NormalState();
  this.move();
 }
 public void heal(int heal) {
  System.out.println("治療:" + heal);
  this.hp += heal;
  if (this.hp > 100) {
   this.hp = 100;
  }
  this.move();
 }
 public void getDamage(int damage) {
  System.out.println("受到攻擊:" + damage);
  this.hp -= damage;
  if (this.hp < 0) {
   this.hp = 0;
  }
  this.move();
 } 
 public int getHp() {
  return hp;
 }
 public void setState(State state) {
  this.state = state;
 }
 public void move() {
  state.move(this);
 }
}

package com.ssc24.chap14.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class WarriorTest {
 @Test
 public void test() {
  System.out.println("===狀態模式測試===");
  Warrior warrior = new Warrior();
  //warrior.move();
  warrior.getDamage(30);
  //warrior.move();
  warrior.getDamage(50);
  //warrior.move();
  warrior.heal(120);
  //warrior.move();
  warrior.getDamage(110);
  //warrior.move();
 }
}

/**
===狀態模式測試===
>>狀態改變,一般狀態
HP=100 ,一般狀態
受到攻擊:30
>>狀態改變,狂怒狀態
HP=70 狂怒狀態 傷害增加30%
受到攻擊:50
>>狀態改變,背水一戰
HP=20 ,背水一戰 傷害增加50%, 防禦增加50%
治療:120
>>狀態改變,狂怒狀態
>>狀態改變,一般狀態
HP=100 ,一般狀態
受到攻擊:110
>>狀態改變,狂怒狀態
>>狀態改變,背水一戰
>>狀態改變,無法戰鬥
HP=0 ,無法戰鬥
**/




chap15.
代理模式 Proxy
目的:為一個物件提供代理物件
虛擬代理(Virtual Proxy):用比較不消耗資源的代理物件來代替實際物件,實際物件只有在真正需要才會被創造。
遠程代理(Remote Proxy):在本地端提供一個代表物件來存取遠端網址的物件
保護代理(Protect Proxy):限制其他程式存取權限
智能代理(Smart Reference Proxy):為被代理的物件增加一些動作
心得:裝飾模式像是一種特化版的代理模式,代理模式只會包一層,裝飾模式會包多層。

package com.ssc24.chap15.demo01;
public interface GameDisplay {
 void display();
}

package com.ssc24.chap15.demo01;
public class ProxyGameDisplay implements GameDisplay {
 private RealGameDisplay realGameDisplay;
 public ProxyGameDisplay(RealGameDisplay realGameDisplay) {
  this.realGameDisplay = realGameDisplay;
 }
 public void display() {
  System.out.println("遊戲讀取中...");
  this.realGameDisplay.display();
 }
}

package com.ssc24.chap15.demo01;
public class RealGameDisplay implements GameDisplay {
 public void display() {
  System.out.println("顯示遊戲畫面");
 }
}

package com.ssc24.chap15.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class GameLoaderTest {
 @Test
 public void test() {
  System.out.println("===代理模式(動態代理)測試===");
  System.out.println("---沒有使用代理---");
  new RealGameDisplay().display();
  System.out.println();
  System.out.println("---使用代理---");
  new ProxyGameDisplay(new RealGameDisplay()).display();
 }
}

/**
===代理模式(動態代理)測試===
---沒有使用代理---
顯示遊戲畫面

---使用代理---
遊戲讀取中...
顯示遊戲畫面

**/



package com.ssc24.chap15.demo02;
public interface Person {
 void setLiteCount(int like);
 int getLikeCount();
 String getName();
 void setName(String name);
}

package com.ssc24.chap15.demo02;
public class PerSonBean implements Person {
 private String name;
 private int likeCount;
 @Override
 public void setLiteCount(int like) {
  this.likeCount = like;
 }
 @Override
 public int getLikeCount() {
  return this.likeCount;
 }
 @Override
 public String getName() {
  return this.name;
 }
 @Override
 public void setName(String name) {
  this.name = name;
 }
}

package com.ssc24.chap15.demo02;

public class ProxyPersonBean implements Person {
 PerSonBean person;
 private String name;
 private int likeCount;
 public ProxyPersonBean(PerSonBean person) {
  this.person = person;
 }
 @Override
 public void setLiteCount(int like) {
  System.out.println("無權限修改like數");
 }
 @Override
 public int getLikeCount() {
  return this.person.getLikeCount();
 }
 @Override
 public String getName() {
  return this.person.getName();
 }
 @Override
 public void setName(String name) {
  this.person.setName(name);
 }
}

package com.ssc24.chap15.demo02;
import static org.junit.Assert.*;
import org.junit.Test;
public class PersonTest {
 @Test
 public void test() {
  System.out.println("===代理模式(保護代理)測試");
  System.out.println("---沒使用代理---");
  Person realPerson = new PerSonBean();
  realPerson.setLiteCount(10);
  System.out.println("like " + realPerson.getLikeCount());
  System.out.println("---使用代理---");
  Person proxyPerson = new ProxyPersonBean(new PerSonBean());
  proxyPerson.setLiteCount(11);
  System.out.println("like " + proxyPerson.getLikeCount());
 }
}

/**
===代理模式(保護代理)測試
---沒使用代理---
like 10
---使用代理---
無權限修改like數
like 0
**/




package com.ssc24.chap15.demo03;
public class FightManager {
 public void doFight(String userName) {
  System.out.println(userName + "帶領冒險者們與無辜的怪物戰鬥");
  System.out.println("...以下省略戰鬥過程");
  System.out.println(userName + "帶領冒險者們洗劫了怪物的家,結束了一場慘無妖道的屠殺");
 }
} 

package com.ssc24.chap15.demo03;
import java.util.Date;
public class ProxyFightManager extends FightManager {
 private FightManager source;
 public ProxyFightManager(FightManager source) {
  this.source = source;
 }
 public void doFight(String userName) {
  System.out.println("> 開始時間:" + new Date().toLocaleString());
  this.source.doFight(userName);
 }
}

package com.ssc24.chap15.demo03;
import static org.junit.Assert.*;
import org.junit.Test;
public class AOPTest {
 @Test
 public void test() {
  System.out.println("===代理模式(AOP)測試===");
  System.out.println("---沒有使用代理---");
  FightManager fm = new FightManager();
  fm.doFight("煞氣A阿龐");
  System.out.println();
  System.out.println("---使用代理---");
  FightManager proxyFm = new ProxyFightManager(fm);
  proxyFm.doFight("煞氣A阿龐");
 }
}

/**
===代理模式(AOP)測試===
---沒有使用代理---
煞氣A阿龐帶領冒險者們與無辜的怪物戰鬥
...以下省略戰鬥過程
煞氣A阿龐帶領冒險者們洗劫了怪物的家,結束了一場慘無妖道的屠殺

---使用代理---
> 開始時間:2017/12/25 下午 03:44:26
煞氣A阿龐帶領冒險者們與無辜的怪物戰鬥
...以下省略戰鬥過程
煞氣A阿龐帶領冒險者們洗劫了怪物的家,結束了一場慘無妖道的屠殺

**/


chap16.
走訪器模式 Iterator
目的:提供方法走訪集合內的物件,走訪過程不需知道集合內部的結構

package com.ssc24.chap16.demo01;
public interface Iterator {
 boolean hasNext();
 E next();
}

package com.ssc24.chap16.demo01;
public class SimpleList {
 private int index = 0;
 private int size = 0;
 private String[] carList = new String[1000];
 public void add(String car) {
  carList[size] = car;
  size++;
 }
 public SimpleIterator getIterator() {
  return new SimpleIterator();
 }
 public class SimpleIterator implements Iterator {
  @Override
  public boolean hasNext() {
   if (index >= size) {
    return false;
   }
   return true;
  }
  public String next() {
   if (hasNext()) {
    return carList[index++];
   }
   throw new IndexOutOfBoundsException();
  }
 }
}

package com.ssc24.chap16.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class SimpleListTest {
 @Test
 public void test() {
  System.out.println("===走訪器模式 測試===");
  SimpleList list = new SimpleList();
  list.add("樂高車");
  list.add("超跑");
  list.add("露營車");
  list.add("連結車");
  list.add("九門轎車");
  list.add("F1賽車");
  Iterator it = list.getIterator();
  while (it.hasNext()) {
   System.out.println(it.next());
  }
  it.next();
 }
}

/**
===走訪器模式 測試===
樂高車
超跑
露營車
連結車
九門轎車
F1賽車
**/


chap17.
建造者模式 Builder
目的:將一個由各種組件組合的複雜產品建造過程封裝

package com.ssc24.chap17.demo01;
public class Form {
 private String formName;
 public Form(String formName) {
  this.formName = formName;
 }
 public String toString() {
  return this.formName;
 }
}

package com.ssc24.chap17.demo01;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Weapon {
 List list = new ArrayList();
 public Weapon(String[] weaponArray) {
  list.addAll(Arrays.asList(weaponArray));
 }
 public String toString() {
  return list.toString();
 }
}

package com.ssc24.chap17.demo01;
public abstract class IRobot {
 Form form;
 Power power;
 Weapon weapon;
 public void setForm(Form form) {
  this.form = form;
 }
 public void setPower(Power power) {
  this.power = power;
 }
 public void setWeapon(Weapon weapon) {
  this.weapon = weapon;
 }
 public void display() {
  System.out.println("機器人外型:" + form);
  System.out.println("機器人動力:" + power);
  System.out.println("機器人武器:" + weapon);
 }
}

package com.ssc24.chap17.demo01;
public class Gundam extends IRobot {
}

package com.ssc24.chap17.demo01;
public class Power {
 private String mainPower;
 private String subPower;
 private String battery;
 public Power(String mainPower,String subPower,String battery) {
  this.mainPower = mainPower;
  this.subPower = subPower;
  this.battery = battery;
 }
 public String toString() {
  return "{主動力:" + this.mainPower + " ,副動力:" + this.subPower + " ,電池:" + this.battery + "}";
 }
}

package com.ssc24.chap17.demo01;
public abstract class RobotBuilder {
 public abstract Form buildForm();
 public abstract Power buildPower();
 public abstract Weapon buildWeapon();
}


package com.ssc24.chap17.demo01;
public class GundamBuilder extends RobotBuilder {
 @Override
 public Form buildForm() {
  return new Form("鋼彈");
 }
 @Override
 public Power buildPower() {
  return new Power("亞哈反應爐", "Beta發電機", "氫電池");
 }
 @Override
 public Weapon buildWeapon() {
  return new Weapon(new String[]{
    "60nm 火神砲"
    ,"突擊長矛"
    ,"光束劍"
  });
 }
}

package com.ssc24.chap17.demo01;
public class Director {
 private RobotBuilder builder;
 public Director(RobotBuilder builder) {
  this.builder = builder;
 }
 public IRobot builderRobot() {
  IRobot robot = new Gundam();
  robot.setForm(builder.buildForm());
  robot.setPower(builder.buildPower());
  robot.setWeapon(builder.buildWeapon());
  return robot;
 }
}

package com.ssc24.chap17.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class RobotBuilderTest {
 @Test
 public void test() {
  System.out.println("===建構者模式測試===");
  Director director = new Director(new GundamBuilder());
  IRobot robot = director.builderRobot();
  robot.display();
 }
}

/**
===建構者模式測試===
機器人外型:鋼彈
機器人動力:{主動力:亞哈反應爐 ,副動力:Beta發電機 ,電池:氫電池}
機器人武器:[60nm 火神砲, 突擊長矛, 光束劍]
**/



chap18.
責任鍊模式 Chain Of Responsbility
目的:讓不同的物件有機會能處理同一個請求

package com.ssc24.chap18.demo01;
public abstract class Manager {
 protected String name;
 protected Manager superior;
 public Manager(String name) {
  this.name = name;
 }
 public void setSuperior(Manager superior) {
  this.superior = superior;
 }
 public abstract void apply(ApplyRequest request);
}

package com.ssc24.chap18.demo01;
public class CommonManager extends Manager {
 public CommonManager(String name) {
  super(name);
 }
 @Override
 public void apply(ApplyRequest request) {
  if ("請假".equals(request.getRequestType()) && request.getRequestCount() <= 2) {
   System.out.println(request.getRequestType() + ":" + request.getRequestContent() + " " + 
     request.getRequestCount()  + "天  被" + name + " 批准");
  } else {
   if (superior != null) {
    superior.apply(request);
   }
  }
 }
}

package com.ssc24.chap18.demo01;
public class GeneralManager extends Manager {
 public GeneralManager(String name) {
  super(name);
 }
 @Override
 public void apply(ApplyRequest request) {
  if ("請假".equals(request.getRequestType())) {
   System.out.println(request.getRequestType() + ":" + request.getRequestContent() + " " + 
     request.getRequestCount()  + "天  被" + name + " 批准");
  } else {
   if (request.getRequestCount() <= 1000) {
    System.out.println(request.getRequestType() + ":" + request.getRequestContent() + " " + 
      request.getRequestCount()  + "元  被" + name + " 批准");
   } else {
    System.out.println(request.getRequestType() + ":" + request.getRequestContent() + " " + 
      request.getRequestCount()  + "元  被" + name + " 駁回");
   }
  }
 }
}

package com.ssc24.chap18.demo01;
public class Majordomo extends Manager {
 public Majordomo(String name) {
  super(name);
 }
 @Override
 public void apply(ApplyRequest request) {
  if ("請假".equals(request.getRequestType()) && request.getRequestCount() <= 5) {
   System.out.println(request.getRequestType() + ":" + request.getRequestContent() + " " + 
     request.getRequestCount()  + "天  被" + name + " 批准");
  } else {
   if (superior != null) {
    superior.apply(request);
   }
  }
 }
}

package com.ssc24.chap18.demo01;
public class ApplyRequest {
 private String requestType;
 private String requestContent;
 private int requestCount;
 public String getRequestType() {
  return requestType;
 }
 public void setRequestType(String requestType) {
  this.requestType = requestType;
 }
 public String getRequestContent() {
  return requestContent;
 }
 public void setRequestContent(String requestContent) {
  this.requestContent = requestContent;
 }
 public int getRequestCount() {
  return requestCount;
 }
 public void setRequestCount(int requestCount) {
  this.requestCount = requestCount;
 }
}

package com.ssc24.chap18.demo01;
public class ManagerClient {
 public static void main(String[] args) {
  System.out.println("===責任鍊模式測試===");
  Manager pm = new CommonManager("PM經理");
  Manager gl = new Majordomo("總監");
  Manager gm = new GeneralManager("總經理");
  pm.setSuperior(gl);
  gl.setSuperior(gm);
  ApplyRequest request = new ApplyRequest();
  request.setRequestType("請假");
  request.setRequestContent("小菜請假");
  request.setRequestCount(2);
  pm.apply(request);
  request.setRequestCount(4);
  pm.apply(request);
  request.setRequestType("加薪");
  request.setRequestContent("小菜加薪");
  request.setRequestCount(2000);
  pm.apply(request);
  request.setRequestCount(900);
  pm.apply(request);
 }
}

/**
===責任鍊模式測試===
請假:小菜請假 2天  被PM經理 批准
請假:小菜請假 4天  被總監 批准
加薪:小菜加薪 2000元  被總經理 駁回
加薪:小菜加薪 900元  被總經理 批准
**/




chap19.
解譯器模式 Interpreter
目的:定義一個語言與其文法,使用一個解譯器來表示這個語言的敘述

package com.ssc24.chap19.demo01;
public class Context {
 private String text;
 public String getText() {
  return text;
 }
 public void setText(String text) {
  this.text = text;
 }
}

package com.ssc24.chap19.demo01;
public abstract class Expression {
 public void interprep(String str) {
  if (str.length() > 0) {
   String text = str.substring(1,str.length());
   Integer number = Integer.valueOf(text);
   excute(number);
  }
 }
 protected abstract void excute(Integer number);
}

package com.ssc24.chap19.demo01;
public class DownExpression extends Expression {
 @Override
 protected void excute(Integer number) {
  System.out.print(number / 2 + " ");
 }
}

package com.ssc24.chap19.demo01;
public class UpExpression extends Expression {
 @Override
 protected void excute(Integer number) {
  System.out.print(number * 2 + " ");
 }
}

package com.ssc24.chap19.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class InterpretTest {
 @Test
 public void test() {
  Expression ex ;
  Context context = new Context();
  context.setText("A4461 B1341 A676 B1787");
  System.out.println("===解譯器模式測試===");
  System.out.println("待解譯內容為:" + context.getText());
  System.out.println("---解譯結果---");
  for (String str : context.getText().split("\\s")) {
   if (str.charAt(0) == 'A') {
    ex = new UpExpression();
   } else {
    ex = new DownExpression();
   }
   ex.interprep(str);
  }
 }
}

/**
===解譯器模式測試===
待解譯內容為:A4461 B1341 A676 B1787
---解譯結果---
8922 670 1352 893 
**/



chap20.
中介者模式 Mediator
目的:當有多個物件之間有交互作用,使用一個中介物件來負責這些物件的交互以降低這些物件之間的耦合

package com.ssc24.chap20.demo01;
public abstract class Messager {
 private String name;
 private static Mediator mediator = new MessageMediator();
 public Messager(String name) {
  this.name = name;
 }
 public void sendToAll(String message) {
  mediator.sendToAll(name, message);
 }
 public void send(String message,Messager to) {
  mediator.send(message, this.name, to);
 }
 public String getName() {
  return this.name;
 }
}

package com.ssc24.chap20.demo01;
public class VIPUser extends Messager {
 public VIPUser(String name) {
  super(name);
 }
}

package com.ssc24.chap20.demo01;
public class CommonUser extends Messager {
 public CommonUser(String name) {
  super(name);
 }
 public void sendToAll(String message) {
  System.out.println("非VIP用戶不能使用廣播");
 }
}

package com.ssc24.chap20.demo01;
public interface Mediator {
 void send(String message,String from,Messager to);
 void sendToAll(String from,String message);
}

package com.ssc24.chap20.demo01;
import java.util.ArrayList;
import java.util.List;
public class MessageMediator implements Mediator {
 private static List vipList = new ArrayList();
 private static List userList = new ArrayList();
 public static void joinChat(Messager messager) {
  if ("VIPUser".equals(messager.getClass().getSimpleName())) {
   vipList.add((VIPUser)messager);
  } else {
   userList.add((CommonUser)messager);
  }
 }
 @Override
 public void send(String message, String from, Messager to) {
  for (Messager msg : vipList) {
   if (from.equals(msg.getName())) {
    System.out.println(from + " -> " + to.getName() + " :" + message);
   }
  }
  for (Messager msg : userList) {
   if (from.equals(msg.getName())) {
    System.out.println(from + " -> " + to.getName() + " :" + message);
   }
  }
 }
 @Override
 public void sendToAll(String from, String message) {
  for (Messager msg : vipList) {
   if (from.equals(msg.getName())) {
    System.out.println(from + " -> " + msg.getName() + " :" + message);
   }
  }
  for (Messager msg : userList) {
   if (from.equals(msg.getName())) {
    System.out.println(from + " -> " + msg.getName() + " :" + message);
   }
  }
 }
}

package com.ssc24.chap20.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class MediatorTest {
 @Test
 public void test() {
  System.out.println("===中介者模式===");
  Messager jacky = new VIPUser("jacky");
  Messager huant = new CommonUser("huant");
  Messager neil = new CommonUser("neil");
  MessageMediator.joinChat(jacky);
  MessageMediator.joinChat(huant);
  MessageMediator.joinChat(neil);
  System.out.println("---VIP會員直接送訊息給每個人---");
  jacky.sendToAll("hi, 你好");
  System.out.println("---私底下送訊息---");
  jacky.send("單挑阿!PK阿", huant);
  neil.send("收假了!!掰掰", jacky);
  System.out.println("---當VIP會員想送訊息給每個人---");
  neil.sendToAll("阿阿阿");
 }
}

/**
===中介者模式===
---VIP會員直接送訊息給每個人---
jacky -> jacky :hi, 你好
---私底下送訊息---
jacky -> huant :單挑阿!PK阿
neil -> jacky :收假了!!掰掰
---當VIP會員想送訊息給每個人---
非VIP用戶不能使用廣播
**/



chap21.
原型模式 Prototype
目的:複製一個物件而不是重新創建一個

package com.ssc24.chap21.demo01;
public class AdventurExperience implements Cloneable {
 private String date;
 private String location;
 protected Object clone() throws CloneNotSupportedException {
  return super.clone();
 }
 public String getDate() {
  return date;
 }
 public void setDate(String date) {
  this.date = date;
 }
 public String getLocation() {
  return location;
 }
 public void setLocation(String location) {
  this.location = location;
 }
}

package com.ssc24.chap21.demo01;
public class Resume implements Cloneable {
 private String name;
 private int level;
 private String profession;
 private AdventurExperience experience;
 public Resume(String name,String profession,int level) {
  this.name = name;
  this.profession = profession;
  this.level = level;
  this.experience = new AdventurExperience();
 }
 private Resume (AdventurExperience experience) throws CloneNotSupportedException {
  this.experience = (AdventurExperience) experience.clone();
 }
 public  Object clone() throws CloneNotSupportedException {
  Resume clone = new Resume(experience);
  clone.setName(this.name);
  clone.setLevel(this.level);
  clone.setProfession(this.profession);
  return clone;
 }
 public void display() {
  System.out.printf(" 冒險者:%s-%s 等級:%d \n",name,profession,level);
  System.out.printf(" 冒險經歷:%s %s \n",experience.getDate(),experience.getLocation());
  System.out.println();
 }
 public void setExperience(String date,String location) {
  experience.setDate(date);
  experience.setLocation(location);
 }
 public void setName(String name) {
  this.name = name;
 }
 public void setLevel(int level) {
  this.level = level;
 }
 public void setProfession(String profession) {
  this.profession = profession;
 }
 public void setExperience(AdventurExperience experience) {
  this.experience = experience;
 }
}
package com.ssc24.chap21.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class ResumeTest {
 @Test
 public void test() throws CloneNotSupportedException {
  System.out.println("===原型模式測試====");
  Resume resume = new Resume("傑克", "見習道士", 1);
  resume.setExperience("2011/01/01", "仙靈島");
  Resume resume2 = (Resume) resume.clone();
  resume2.setLevel(5);
  resume2.setExperience("20/12/03/31","隱龍窟");
  Resume resume3 = (Resume) resume2.clone();
  resume3.setProfession("殭屍道長");
  resume3.setExperience("2012/11/31", "赤鬼王血池");
  System.out.println("---第一份履歷---");
  resume.display();
  System.out.println("---第二份履歷---");
  resume2.display();
  System.out.println("---第三份履歷---");
  resume3.display();
 }
}

/**
===原型模式測試====
---第一份履歷---
 冒險者:傑克-見習道士 等級:1 
 冒險經歷:2011/01/01 仙靈島 

---第二份履歷---
 冒險者:傑克-見習道士 等級:5 
 冒險經歷:20/12/03/31 隱龍窟 

---第三份履歷---
 冒險者:傑克-殭屍道長 等級:5 
 冒險經歷:2012/11/31 赤鬼王血池 

**/



chap22.
橋接模式 Bridge
目的:將抽象介面與實作類別切開,使兩者可以各自變化而不影響彼此

package com.ssc24.chap22.demo01;
public abstract class Mail {
 abstract void registerState();
}

package com.ssc24.chap22.demo01;
public class RegisterMail extends Mail {
 @Override
 void registerState() {
  System.out.println("這是一封掛號信,收件人必須簽名");
 }
}

package com.ssc24.chap22.demo01;
public class NoRegisterMail extends Mail {
 @Override
 void registerState() {
  System.out.println("這不是掛號信,收件人不用簽名");
 }
}

package com.ssc24.chap22.demo01;
public abstract class MailSender {
 protected Mail mail;
 private MailSender(){
 }
 public MailSender(Mail mail) {
  this.mail = mail;
 }
 public abstract void send(); 
}


package com.ssc24.chap22.demo01;
public class NormalMail extends MailSender {
 public NormalMail(Mail mail) {
  super(mail);
 }
 @Override
 public void send() {
  System.out.println(">>信件寄出後3~5天內抵達");
  super.mail.registerState();
 }
}

package com.ssc24.chap22.demo01;
public class PromptMail extends MailSender {
 public PromptMail(Mail mail) {
  super(mail);
 }
 @Override
 public void send() {
  System.out.println(">>信件寄出後24hr內抵達");
  super.mail.registerState();
 }
}

package com.ssc24.chap22.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class RemoteTest {
 @Test
 public void test() {
  System.out.println("===橋接模式測試===");
  System.out.println("---一般信件測試---");
  MailSender mailSender = new NormalMail(new NoRegisterMail());
  mailSender.send();
  mailSender = new NormalMail(new RegisterMail());
  mailSender.send();
  
  System.out.println("---限時信件測試---");
  mailSender = new PromptMail(new NoRegisterMail());
  mailSender.send();
  mailSender = new PromptMail(new RegisterMail());
  mailSender.send();
 }
}

/**
===橋接模式測試===
---一般信件測試---
>>信件寄出後3~5天內抵達
這不是掛號信,收件人不用簽名
>>信件寄出後3~5天內抵達
這是一封掛號信,收件人必須簽名
---限時信件測試---
>>信件寄出後24hr內抵達
這不是掛號信,收件人不用簽名
>>信件寄出後24hr內抵達
這是一封掛號信,收件人必須簽名
**/





chap23.
備忘錄模式 Memento
目的:將一個物件的內部狀態儲存在另外一個備忘錄物件中,備忘錄物件可用來還原物件狀態

package com.ssc24.chap23.demo01;
public class GameRole {
 private int hp = 100;
 private int atk = 100;
 private int def = 100;
 private String name = "第六天魔王";
 public RoleStateMemo save() {
  return new RoleStateMemo(hp,atk,def);
 }
 public void fight() {
  hp = 30;
  System.out.println(name + "剩下 30% 血量,出大招把隊伍打的半死");
 }
 public void stateDisplay() {
  System.out.println(name + " 的狀態:");
  System.out.print("hp=" + hp);
  System.out.print(" ,atk=" + atk);
  System.out.print(" ,def=" + def);
 }
 public void load(RoleStateMemo memo) {
  this.hp = memo.getHp();
  this.atk = memo.getAtk();
  this.def = memo.getDef();
 }
 public int getHp() {
  return hp;
 }
 public void setHp(int hp) {
  this.hp = hp;
 }
 public int getAtk() {
  return atk;
 }
 public void setAtk(int atk) {
  this.atk = atk;
 }
 public int getDef() {
  return def;
 }
 public void setDef(int def) {
  this.def = def;
 }
}

package com.ssc24.chap23.demo01;
import java.util.ArrayList;
import java.util.List;
public class RoleStateCareTaker {
 public List saves = new ArrayList();
 public RoleStateMemo getSave() {
  return saves.get(0);
 }
 public void setSave(RoleStateMemo memo) {
  saves.add(0,memo);
 }
}

package com.ssc24.chap23.demo01;
public class RoleStateMemo {
 private int hp;
 private int atk;
 private int def;
 public RoleStateMemo(int hp,int atk,int def) {
  this.hp = hp;
  this.atk = atk;
  this.def = def;
 }
 public int getHp() {
  return hp;
 }
 public void setHp(int hp) {
  this.hp = hp;
 }
 public int getAtk() {
  return atk;
 }
 public void setAtk(int atk) {
  this.atk = atk;
 }
 public int getDef() {
  return def;
 }
 public void setDef(int def) {
  this.def = def;
 }
}

package com.ssc24.chap23.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class GameRoleTest {
 @Test
 public void test() {
  GameRole boss = new GameRole();
  boss.stateDisplay();
  System.out.println("使用複雜的神秘小技巧");
  boss.setAtk(60);
  RoleStateCareTaker rsc = new RoleStateCareTaker();
  rsc.setSave(boss.save());
  boss.stateDisplay();
  boss.fight();
  boss.stateDisplay();
  boss.load(rsc.getSave());
  System.out.println("不行不行,那個時間點該先回滿血,讀檔重打");
  boss.stateDisplay();
 }
}

/**
第六天魔王 的狀態:
hp=100 ,atk=100 ,def=100使用複雜的神秘小技巧
第六天魔王 的狀態:
hp=100 ,atk=60 ,def=100第六天魔王剩下 30% 血量,出大招把隊伍打的半死
第六天魔王 的狀態:
hp=30 ,atk=60 ,def=100不行不行,那個時間點該先回滿血,讀檔重打
第六天魔王 的狀態:
hp=100 ,atk=60 ,def=100
**/


chap24.
蠅量級(享元)模式 FlyWeight
目的:大量物件共享一些共同性質,降低系統的負荷

package com.ssc24.chap24.demo01;
public class Tree {
 private String type;
 private String owner;
 public Tree(String type) {
  this.type = type;
 }
 public void setOwner(String owner) {
  this.owner = owner;
 }
 public void display() {
  System.out.println(type + " ,擁有者" + owner);
 }
}

package com.ssc24.chap24.demo01;
import java.util.HashMap;
import java.util.Map;
public class TreeManager {
 private static Map treePool = new HashMap<>();
 public static Tree getTree(String type) {
  if (!treePool.containsKey(type)) {
   treePool.put(type,new Tree(type));
  }
  return treePool.get(type);
 }
}

package com.ssc24.chap24.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class TreeTest {
 @Test
 public void test() {
  System.out.println("===蠅量級模式測試===");
  Tree rose = TreeManager.getTree("玫瑰");
  rose.setOwner("Rose");
  rose.display();
  System.out.println("Jacky 來買一棵玫瑰花");
  Tree jRose = TreeManager.getTree("玫瑰");
  jRose.setOwner("Jacky");
  jRose.display();
  Tree hinoki = TreeManager.getTree("台灣紅檜");
  hinoki.setOwner("林務局");
  hinoki.display();
 }
}

/**
===蠅量級模式測試===
玫瑰 ,擁有者Rose
Jacky 來買一棵玫瑰花
玫瑰 ,擁有者Jacky
台灣紅檜 ,擁有者林務局
**/



chap25.
拜訪者模式 Visitor
目的:用不同的拜訪者使集合(Collection)中的元素行為與元素類別切離。

package com.ssc24.chap25.demo01;
public abstract class Chef {
 private String name;
 public Chef(String name) {
  this.name = name;
 }
 public String getName() {
  return name;
 }
 public abstract void acept(Visitor visitor); 
}

package com.ssc24.chap25.demo01;
public class DarkChef extends Chef {
 public DarkChef(String name) {
  super(name);
 }
 @Override
 public void acept(Visitor visitor) {
  visitor.cook(this);
 }
}

package com.ssc24.chap25.demo01;
public class SuperChef extends Chef {
 public SuperChef(String name) {
  super(name);
 }
 @Override
 public void acept(Visitor visitor) {
  visitor.cook(this);
 }
}

package com.ssc24.chap25.demo01;
public class SuperNoodleChef extends Chef {
 public SuperNoodleChef(String name) {
  super(name);
 }
 @Override
 public void acept(Visitor visitor) {
  visitor.cook(this);
 }
}

package com.ssc24.chap25.demo01;
public interface Visitor {
 void cook(DarkChef chef);
 void cook(SuperChef  chef);
 void cook(SuperNoodleChef chef);
}

package com.ssc24.chap25.demo01;
public class Visitor_saoMai implements Visitor {
 @Override
 public void cook(DarkChef chef) {
  System.out.println(chef.getName() + ":魔幻鴉片燒賣");
  
 }
 @Override
 public void cook(SuperChef chef) {
  System.out.println(chef.getName() + ":宇宙大燒賣");
  
 }
 @Override
 public void cook(SuperNoodleChef chef) {
  System.out.println(chef.getName() + ":鐵桿50人份燒賣");
 }
}

package com.ssc24.chap25.demo01;
public class Visitor_tofu implements Visitor {
 @Override
 public void cook(DarkChef chef) {
  System.out.println(chef.getName() + ":豆腐三重奏");
 }
 @Override
 public void cook(SuperChef chef) {
  System.out.println(chef.getName() + ":貓熊豆腐");
 }
 @Override
 public void cook(SuperNoodleChef chef) {
  System.out.println(chef.getName() + ":鐵桿臭豆腐");
 }
}

package com.ssc24.chap25.demo01;
import java.util.ArrayList;
import java.util.List;
public class ChefGroup {
 private List list = new ArrayList<>();
 public void join (Chef chef) {
  list.add(chef);
 }
 public void leave (Chef chef) {
  list.remove(chef);
 }
 public void topic (Visitor visitor) {
  for (Chef chef : list) {
   chef.acept(visitor);
  }
 }
}

package com.ssc24.chap25.demo01;
import static org.junit.Assert.*;
import org.junit.Test;
public class ChefTest {
 @Test
 public void test() {
  System.out.println("===拜訪者模式測試===");
  ChefGroup chefGroup = new ChefGroup();
  chefGroup.join(new SuperChef("小當家"));
  chefGroup.join(new DarkChef("紹安"));
  chefGroup.join(new SuperNoodleChef("解師傅"));
  System.out.println("第一回合:做燒賣");
  Visitor round1 = new Visitor_saoMai();
  chefGroup.topic(round1);
  System.out.println("第二回合:豆腐");
  Visitor round2 = new Visitor_tofu();
  chefGroup.topic(round2);
 }
}

/**
===拜訪者模式測試===
第一回合:做燒賣
小當家:宇宙大燒賣
紹安:魔幻鴉片燒賣
解師傅:鐵桿50人份燒賣
第二回合:豆腐
小當家:貓熊豆腐
紹安:豆腐三重奏
解師傅:鐵桿臭豆腐
**/