Skip to content

Instantly share code, notes, and snippets.

@sezemiadmin
Last active March 23, 2020 04:09
Show Gist options
  • Save sezemiadmin/8289faa39330a0b6bc238749bee33108 to your computer and use it in GitHub Desktop.
Save sezemiadmin/8289faa39330a0b6bc238749bee33108 to your computer and use it in GitHub Desktop.
GoFSamples
import java.util.List;
import java.util.ArrayList;
// 抽象的な工場(食事のセット)の定義
abstract class MealFactory {
// 主食と汁物のセットを生成する
public abstract StapleFood createStapleFood();
public abstract Soup createSoup();
}
// 抽象的な製品1(主食)の定義
abstract class StapleFood {
public abstract void eat();
}
// 抽象的な製品2(汁物)の定義
abstract class Soup {
public abstract void drink();
}
// 具象的な工場1(和食)の実装
class JapaneseMealFactory extends MealFactory {
public StapleFood createStapleFood() {
return new Rice();
}
public Soup createSoup() {
return new MisoSoup();
}
}
// 具象的な製品1-1(ごはん)の実装
class Rice extends StapleFood {
public void eat() {
System.out.println("ごはん、ぱくぱく!");
}
}
// 具象的な製品1-2(味噌汁)の実装
class MisoSoup extends Soup {
public void drink() {
System.out.println("味噌汁、じゅるじゅる!");
}
}
// 具象的な工場2(洋食)の実装
class WesternMealFactory extends MealFactory {
public StapleFood createStapleFood() {
return new Bread();
}
public Soup createSoup() {
return new Potage();
}
}
// 具象的な製品2-1(パン)の実装
class Bread extends StapleFood {
public void eat() {
System.out.println("パン、モグモグ!");
}
}
// 具象的な製品1-2(ポタージュ)の実装
class Potage extends Soup {
public void drink() {
System.out.println("ポタージュ、スルスル!");
}
}
public class AbstractFactorySample {
public static void main(String[] args) {
// 和食、洋食、洋食、和食、洋食の順に注文された
List<MealFactory> mfList = new ArrayList<MealFactory>();
mfList.add(new JapaneseMealFactory());
mfList.add(new WesternMealFactory());
mfList.add(new WesternMealFactory());
mfList.add(new JapaneseMealFactory());
mfList.add(new WesternMealFactory());
// 主食と汁物のセットを適切な組合せで生成できる
for (MealFactory mf : mfList) {
System.out.println("--------------------");
mf.createStapleFood().eat();
mf.createSoup().drink();
System.out.println("--------------------");
}
}
}
// 一般社員を表すクラス
class Employee {
private int wage; // 時給
private int hour; // 時間
// 給与を返すメソッド
public int getSalary() {
return this.wage * this.hour;
}
// コンストラクタ
public Employee(int wage, int hour) {
this.wage = wage;
this.hour = hour;
}
}
// 社長を表すクラス
class President {
private int fixedSalary; // 固定給
// 固定給を返すメソッド
public int getFixedSalary() {
return this.fixedSalary;
}
// コンストラクタ
public President(int fixedSalary) {
this.fixedSalary = fixedSalary;
}
}
// PresidentをEmployeeにつなぐアダプタとなるクラス
class EmpAdapter extends Employee { // Employeeを継承する
private President pre; // Presidentを集約する
// コンストラクタ
public EmpAdapter(President pre) {
super(0, 0);
this.pre = pre;
}
// オーバーライド
public int getSalary() {
return pre.getFixedSalary();
}
}
// テスト用のメインクラス
public class AdapterSample {
public static int salarySum(Employee[] emp) {
int sum = 0;
for (int i = 0; i < emp.length; i++) {
sum += emp[i].getSalary();
}
return sum;
}
public static void main(String[] args) {
// Employeeの配列を作成する
Employee[] emp = new Employee[5];
// Employeeのインスタンスを生成して配列に格納する
emp[0] = new Employee(850, 200);
emp[1] = new Employee(900, 180);
emp[2] = new Employee(880, 190);
emp[3] = new Employee(950, 220);
// Presidentのインスタンスを生成し、
// アダプタをかぶせて配列に格納する
emp[4] = new EmpAdapter(new President(1000000));
// 給与の合計値を表示する
System.out.println(AdapterSample.salarySum(emp));
}
}
// methodA()を定義したクラス
abstract class ClassA {
public abstract void methodA();
}
// ClassAクラスを実装目的で継承するクラス
class ClassAEx extends ClassA {
public void methodA() {
System.out.println("ClassAExクラスのmethodA()の実装");
}
}
// 橋を架けるクラス
class ClassAB {
private ClassA bridge;
public ClassAB(ClassAEx aex) {
this.bridge = aex;
}
public void methodA() {
// 集約したClassAクラスを使ってmethodA()メソッドを呼び出す
this.bridge.methodA();
}
}
// ClassAクラスと同じ機能のClassABクラスを拡張目的で継承するクラス
class ClassB extends ClassAB {
public ClassB(ClassAEx aex) {
super(aex);
}
public void methodB() {
System.out.println("ClassBクラスのmethodB()の実装");
}
}
// メインクラス
public class BridgeSample {
public static void main(String[] args) {
// 実装目的で継承したクラスのインスタンスを使う
System.out.println("<< ClassAExを使う >>");
ClassAEx aex = new ClassAEx();
aex.methodA();
// 拡張目的で継承したクラスのインスタンスを使う
System.out.println("<< ClassBを使う >>");
ClassB b = new ClassB(aex);
b.methodA(); // ここで橋を渡っている
b.methodB();
}
}
// 料理人を表す抽象クラス(Builder)
abstract class MealBuilder {
public abstract void makeSalad(); // サラダを作る
public abstract void makeSoup(); // スープを作る
public abstract void makeMainDish(); // メインディッシュを作る
public abstract void makeDessert(); // デザートを作る
}
// フレンチの料理人の具象クラス(Builder)
class FrenchBuilder extends MealBuilder {
public void makeSalad() {
System.out.println("ニース風サラダ");
}
public void makeSoup() {
System.out.println("ポタージュスープ");
}
public void makeMainDish() {
System.out.println("鮭のムニエル");
}
public void makeDessert() {
System.out.println("イチゴのシャーベット");
}
}
// 和食の料理人の具象クラス(Builder)
class JapaneseBuilder extends MealBuilder {
public void makeSalad() {
System.out.println("菜の花のおひたし");
}
public void makeSoup() {
System.out.println("かきたま汁");
}
public void makeMainDish() {
System.out.println("お刺身5点盛り");
}
public void makeDessert() {
System.out.println("くずもち");
}
}
// レストランの監督の具象クラス(Director)
class RestaurantDirector {
// ビルダを集約する(料理作りを委譲するため)
private MealBuilder builder;
// コンストラクタ(お客さんに料理人を指定してもらう)
public RestaurantDirector(MealBuilder builder) {
this.builder = builder;
}
// ミニコースを依頼する
public void miniCourse() {
System.out.println("--------------------");
builder.makeSalad();
builder.makeMainDish();
System.out.println("--------------------");
}
// フルコースを依頼する
public void fullCourse() {
System.out.println("--------------------");
builder.makeSalad();
builder.makeSoup();
builder.makeMainDish();
builder.makeDessert();
System.out.println("--------------------");
}
}
// メインクラス(レストランのお客さん)
public class BuilderSample {
public static void main(String[] args) {
// 和食のミニコースとフルコースを頼む
RestaurantDirector rdJP = new RestaurantDirector(new JapaneseBuilder());
rdJP.miniCourse();
rdJP.fullCourse();
// フレンチのミニコースとフルコースを頼む
RestaurantDirector rdFR = new RestaurantDirector(new FrenchBuilder());
rdFR.miniCourse();
rdFR.fullCourse();
}
}
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
// Facadeパターンを実践したクラス
class MyTextFile {
// テキストファイルに書き込みを行うメソッド
public static int write(String fileName, String text) {
int retVal = 0;
try {
File f = new File(fileName);
FileWriter fw = new FileWriter(f);
fw.write(text);
fw.close();
}
catch (Exception e) {
retVal = -1;
}
return retVal;
}
// テキストファイルから読み出しを行うメソッド
public static String read(String fileName) {
int c;
String text;
try {
File f = new File(fileName);
FileReader fr = new FileReader(f);
text = "";
while ((c = fr.read()) != -1) {
text += (char)c;
}
fr.close();
}
catch (Exception e) {
text = null;
}
return text;
}
}
// メインクラス
public class FacadeSample {
public static void main(String[] args) {
// テキストファイルに書き込む
MyTextFile.write("sample.txt", "リンゴ\nミカン\nバナナ\n");
// テキストファイルから読み出す
String text = MyTextFile.read("sample.txt");
// 読み出した文字列を表示する
System.out.println(text);
}
}
import java.util.Map;
import java.util.HashMap;
// 単語帳を表すクラス
class WordBook {
// 「英単語」「日本語訳」のペアを格納するオブジェクトプール
private Map<String, String> pool;
// コンストラクタ
public WordBook() {
this.pool = new HashMap<String, String>();
}
// 単語帳に登録する
public void put(String engWord, String jpnWord) {
// 単語帳になければ登録する
if (this.pool.get(engWord) == null) {
this.pool.put(engWord, jpnWord);
}
}
// 単語帳から読み出す
public String get(String engWord) {
// 登録されていれば日本語訳を返す
String jpnWord = this.pool.get(engWord);
if (jpnWord == null) {
jpnWord = "登録されていません!";
}
return jpnWord;
}
// オブジェクトプール内にあるオブジェクト数を返す
public int getPoolSize() {
return this.pool.size();
}
}
public class FlyweightSample {
public static void main(String[] args) {
// 単語帳を生成する
WordBook wb = new WordBook();
// わざと同じ単語を何度も登録する
wb.put("apple", "リンゴ");
wb.put("orange", "ミカン");
wb.put("banana", "バナナ");
wb.put("apple", "リンゴ");
wb.put("orange", "ミカン");
wb.put("banana", "バナナ");
wb.put("apple", "リンゴ");
wb.put("orange", "ミカン");
wb.put("banana", "バナナ");
// 単語帳の登録数を表示する
System.out.println("オブジェクトプール内のオブジェクト数 = " + wb.getPoolSize());
// 単語帳を読み出す
System.out.println("banana→" + wb.get("banana"));
System.out.println("banana→" + wb.get("banana"));
System.out.println("orange→" + wb.get("orange"));
System.out.println("apple→" + wb.get("apple"));
System.out.println("orange→" + wb.get("orange"));
System.out.println("melon→" + wb.get("melon"));
}
}
import java.lang.Iterable;
import java.util.Iterator;
// IterableおよびIteratorインターフェイスを実装したMyIteratorクラス
class MyIterator implements Iterable<String>, Iterator<String> {
// 適当なデータを用意しておく
private String[] data = { "apple", "orange", "banana" };
// 次のデータの読み出し位置
private int index = 0;
// イテレータを返すメソッド
public Iterator<String> iterator() {
this.index = 0; // 毎回初期化するので何度でも読み出せる
return this;
}
// 次のデータがあればtrueを返すメソッド
public boolean hasNext() {
return this.index < data.length;
}
// 次のデータを返すメソッド
public String next() {
String s = data[index++];
return s;
}
// 最後に返した要素を削除するメソッド
public void remove() {
// 空実装
}
}
// テスト用のメインクラス
public class IteratorSample {
public static void main(String[] args) {
// MyIteratorクラスのインスタンスを生成する
MyIterator mi = new MyIterator();
// 拡張for文で先頭から末尾まで読み出す
System.out.println("<拡張for文>");
for (String s : mi) {
System.out.println(s);
}
// while文で先頭から末尾まで読み出すこともできる
System.out.println("<while文>");
Iterator<String> it = mi.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
// 図形の配列を保持するクラス
class FigArray implements Cloneable {
// 図形の配列
private char[] figs;
// 図形の配列の要素を変更する
public void setFig(int idx, char fig) {
this.figs[idx] = fig;
}
// 図形の配列を表示する
public void show() {
for (char f : figs) {
System.out.print(f);
}
System.out.println();
}
// コンストラクタ
public FigArray(char[] figs) {
this.figs = figs;
}
// clone()のオーバーライド
@Override
public FigArray clone() {
try {
// Objectクラスのclone()を呼び出してから
FigArray fa = (FigArray)super.clone();
// 参照元のclone()も呼び出すことで
fa.figs = this.figs.clone();
// deep copyを返せる
return fa;
}
catch (Exception e) {
return null;
}
}
}
public class PrototypeSample2 {
public static void main(String[] args) {
char[] figs = { '△', '〇', '□' };
FigArray fa1 = new FigArray(figs);
System.out.print("fa1 = ");
fa1.show();
FigArray fa2 = fa1.clone();
System.out.print("fa2 = ");
fa2.show();
fa1.setFig(1, '●');
System.out.print("fa1 = ");
fa1.show();
System.out.print("fa2 = ");
fa2.show();
}
}
// インスタンスを1個だけ生成して共有するクラス
class Information {
// インスタンスへの参照を保持するフィールド
private static Information ref = null;
// インスタンスを生成するメソッド
public static synchronized Information createInstance() {
if (Information.ref == null) {
// まだ生成されていないなら生成する
Information.ref = new Information();
// インスタンスが生成されたことを表示する
System.out.println("インスタンスが生成されました");
}
else {
System.out.println("生成済みのインスタンスを共有します");
}
return Information.ref;
}
// インスタンスが保持するお知らせ
private String info;
// お知らせを表示するメソッド
public void showInfo() {
System.out.println(this.info);
}
// コンストラクタをprivateにする
private Information() {
// 実際には、ここで、ファイルやデータベースを読み出す重い処理を行う
this.info = "お知らせ";
}
}
public class SingletonSample {
public static void main(String[] args) {
// Informationクラスのインスタンスを3つ生成する(そのつもり)
Information info1 = Information.createInstance();
Information info2 = Information.createInstance();
Information info3 = Information.createInstance();
// それぞれのインスタンスメソッドを呼び出す(そのつもり)
info1.showInfo();
info2.showInfo();
info3.showInfo();
}
}
import java.util.Scanner;
// 改造前のスーパークラス
abstract class QuizAlgo {
// 問題を表示する小さな抽象メソッド
public abstract void showQuestion();
// 答案を入力する小さな抽象メソッド
public abstract void inputAnswer();
// 判定を行う小さな抽象メソッド
public abstract boolean showJudgement();
// クイズの手順を示す大きな具象メソッド(テンプレートメソッド)
public void doQuiz() {
// 問題を表示する処理
this.showQuestion();
// 答案を入力する処理
this.inputAnswer();
// 判定結果を表示する処理
if (this.showJudgement()) {
System.out.println("<< 正解です! >>");
}
else {
System.out.println("<< 違います! >>");
}
}
}
// 選択問題のサブクラス
class SelectionQuiz extends QuizAlgo {
private String question; // 問題
private String[] choices; // 選択肢
private int correctNum; // 正解の番号
private int answerNum; // 答案の番号
// コンストラクタ
public SelectionQuiz(String question, String[] choices, int correctNum) {
this.question = question;
this.choices = choices;
this.correctNum = correctNum;
}
// 問題を表示する小さな抽象メソッドの実装
public void showQuestion() {
System.out.println("【問題】" + this.question);
System.out.println("【選択肢】");
for (int i = 0; i < this.choices.length; i++) {
System.out.println((i + 1) + ":" + this.choices[i]);
}
}
// 答案を入力する小さな抽象メソッドの実装
public void inputAnswer() {
Scanner scn = new Scanner(System.in);
System.out.print("答えを選んでください:");
this.answerNum = Integer.parseInt(scn.next());
}
// 判定を行う小さな抽象メソッドの実装
public boolean showJudgement() {
return this.answerNum == this.correctNum;
}
}
// 記述問題のサブクラス
class EssayQuiz extends QuizAlgo {
private String question; // 問題
private String correctAns; // 正解
private String answer; // 答案
// コンストラクタ
public EssayQuiz(String question, String correctAns) {
this.question = question;
this.correctAns = correctAns;
this.answer = answer;
}
// 問題を表示する小さな抽象メソッドの実装
public void showQuestion() {
System.out.println("【問題】" + this.question);
}
// 答案を入力する小さな抽象メソッドの実装
public void inputAnswer() {
Scanner scn = new Scanner(System.in);
System.out.print("答えを記述してください:");
this.answer = scn.next();
}
// 判定を行う小さな抽象メソッドの実装
public boolean showJudgement() {
return this.answer.equals(correctAns);
}
}
// メインメソッド
public class TemplateMethodSample1 {
public static void main(String[] args) {
// 選択問題を行う
String[] choices = { "利根川", "石狩川", "信濃川", "最上川" };
QuizAlgo q1 = new SelectionQuiz("日本で一番長い川は?", choices, 3);
q1.doQuiz();
// 記述問題を行う
System.out.println();
QuizAlgo q2 = new EssayQuiz("「川」を英語で何と言う?", "river");
q2.doQuiz();
}
}
<C:\GoFSamples\TemplateMethod1\TemplateMethodSample2.java>
import java.util.Scanner;
// 改造後のスーパークラス
abstract class QuizAlgo {
// 問題を表示する小さな抽象メソッド(変更なし!)
public abstract void showQuestion();
// 答案を入力する小さな抽象メソッド(変更なし!)
public abstract void inputAnswer();
// 判定を行う小さな抽象メソッド(変更なし!)
public abstract boolean showJudgement();
// クイズの手順を示す大きな具象メソッド(テンプレートメソッド)(ここだけ変更!)
public void doQuiz() {
// 判定結果
boolean judge;
// 答案を入力した回数
int ansCount = 0;
// 問題を表示する処理
this.showQuestion();
do {
// 答案を入力する処理
this.inputAnswer();
ansCount++;
// 判定結果を表示する処理
judge = this.showJudgement();
if (judge) {
System.out.println("<< 正解です! >>");
}
else {
System.out.println("<< 違います! >>");
}
} while (!judge && ansCount < 2);
}
}
// 選択問題のサブクラス(変更なし!)
class SelectionQuiz extends QuizAlgo {
private String question; // 問題
private String[] choices; // 選択肢
private int correctNum; // 正解の番号
private int answerNum; // 答案の番号
// コンストラクタ
public SelectionQuiz(String question, String[] choices, int correctNum) {
this.question = question;
this.choices = choices;
this.correctNum = correctNum;
}
// 問題を表示する小さな抽象メソッドの実装
public void showQuestion() {
System.out.println("【問題】" + this.question);
System.out.println("【選択肢】");
for (int i = 0; i < this.choices.length; i++) {
System.out.println((i + 1) + ":" + this.choices[i]);
}
}
// 答案を入力する小さな抽象メソッドの実装
public void inputAnswer() {
Scanner scn = new Scanner(System.in);
System.out.print("答えを選んでください:");
this.answerNum = Integer.parseInt(scn.next());
}
// 判定を行う小さな抽象メソッドの実装
public boolean showJudgement() {
return this.answerNum == this.correctNum;
}
}
// 記述問題のサブクラス(変更なし!)
class EssayQuiz extends QuizAlgo {
private String question; // 問題
private String correctAns; // 正解
private String answer; // 答案
// コンストラクタ
public EssayQuiz(String question, String correctAns) {
this.question = question;
this.correctAns = correctAns;
this.answer = answer;
}
// 問題を表示する小さな抽象メソッドの実装
public void showQuestion() {
System.out.println("【問題】" + this.question);
}
// 答案を入力する小さな抽象メソッドの実装
public void inputAnswer() {
Scanner scn = new Scanner(System.in);
System.out.print("答えを記述してください:");
this.answer = scn.next();
}
// 判定を行う小さな抽象メソッドの実装
public boolean showJudgement() {
return this.answer.equals(correctAns);
}
}
// メインメソッド(変更なし!)
public class TemplateMethodSample2 {
public static void main(String[] args) {
// 選択問題を行う
String[] choices = { "利根川", "石狩川", "信濃川", "最上川" };
QuizAlgo q1 = new SelectionQuiz("日本で一番長い川は?", choices, 3);
q1.doQuiz();
// 記述問題を行う
System.out.println();
QuizAlgo q2 = new EssayQuiz("「川」を英語で何と言う?", "river");
q2.doQuiz();
}
}
import java.util.Scanner;
// 手を表すスーパークラス
abstract class Hand {
protected String name; // 手の名前
public Hand(String name) { this.name = name; } // 初期化メソッド
public String toString() { return this.name; } // 文字列表現を返す
public abstract void vsGu(); // グーとの対戦結果を表示する
public abstract void vsChoki(); // チョキとの対戦結果を表示する
public abstract void vsPa(); // パーとの対戦結果を表示する
public abstract void judge(Hand obj); // 対戦相手objのvsXX()メソッドを呼び出す
}
// グーを表すクラス
class Gu extends Hand {
public Gu(String name) { super(name); }
public void vsGu() { System.out.println("あいこ"); }
public void vsChoki() { System.out.println(this.name + "の勝ち"); }
public void vsPa() { System.out.println(this.name + "の負け"); }
public void judge(Hand obj) { obj.vsGu(); }
}
// チョキを表すクラス
class Choki extends Hand {
public Choki(String name) { super(name); }
public void vsGu() { System.out.println(this.name + "の負け"); }
public void vsChoki() { System.out.println("あいこ"); }
public void vsPa() { System.out.println(this.name + "の勝ち"); }
public void judge(Hand obj) { obj.vsChoki(); }
}
// パーを表すクラス
class Pa extends Hand {
public Pa(String name) { super(name); }
public void vsGu() { System.out.println(this.name + "の勝ち"); }
public void vsChoki() { System.out.println(this.name + "の負け"); }
public void vsPa() { System.out.println("あいこ"); }
public void judge(Hand obj) { obj.vsPa(); }
}
// じゃんけんを行うクラス
public class VisitorSample {
public static void main(String[] args) {
Hand[] hand = { new Gu("グー"), new Choki("チョキ"), new Pa("パー") };
// ユーザーが手を選ぶ
System.out.print("手を入力してください(1 = グー、2 = チョキ、3 = パー): ");
Scanner scn = new Scanner(System.in);
Hand userHand = hand[scn.nextInt() - 1];
System.out.println("ユーザーの手:" + userHand);
// コンピュータが手を選ぶ
Hand computerHand = hand[(int)(Math.random() * 3)];
System.out.println("コンピュータの手:" + computerHand);
// 勝敗を判定する
userHand.judge(computerHand);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment