Adapter(適配器模式)
登場角色
- Target(對象)
該角色負責定義所需的方法
- Client(請求者)
該角色負責使用 Target 角色所定義的方法進行具體處理。
- Adaptee(被適配)
該角色持有既定的方法。
- Adapter(適配)
該角色的作用是使用 Adaptee 角色的方法來滿足 Target 角色的需求。
類圖
- 類適配器模式的類圖(使用繼承)
- 對象適配器模式的類圖(使用委託)
示例代碼
public class Banner {
private String string;
public Banner(String string) {
this.string = string;
}
public void showWithParen() {
System.out.println("(" + string + ")");
}
public void showWithAster() {
System.out.println("*" + string + "*");
}
}
public interface Print {
public abstract void printWeak();
public abstract void printStrong();
}
public class PrintBanner extends Banner implements Print {
public PrintBanner(String string) {
super(string);
}
public void printWeak() {
showWithParen();
}
public void printStrong() {
showWithAster();
}
}
public class PrintBanner extends Print {
private Banner banner;
public PrintBanner(String string) {
this.banner = new Banner(string);
}
public void printWeak() {
banner.showWithParen();
}
public void printStrong() {
banner.showWithAster();
}
}
Template Method(模板方法模式)
登場角色
- AbstractClass(抽象類或接口)
該角色負責實現模板方法,同時負責聲明在模板方法中所使用到的抽象方法。
- ConcreteClass(具體類)
該角色負責具體實現 AbstractClass 角色中定義的抽象方法。
類圖
示例代碼
public abstract class AbstractDisplay {
public abstract void open();
public abstract void print();
public abstract void close();
public final void display() {
open();
for (int i = 0; i < 5; i++) {
print();
}
close();
}
}
public class CharDisplay extends AbstractDisplay {
private char ch;
public CharDisplay(char ch) {
this.ch = ch;
}
public void open() {
System.out.print("<<");
}
public void print() {
System.out.print(ch);
}
public void close() {
System.out.println(">>");
}
}
public class StringDisplay extends AbstractDisplay {
private String string;
private int width;
public StringDisplay(String string) {
this.string = string;
this.width = string.getBytes().length;
}
public void open() {
printLine();
}
public void print() {
System.out.println("|" + string + "|");
}
public void close() {
printLine();
}
private void printLine() {
System.out.print("+");
for (int i = 0; i < width; i++) {
System.out.print("-");
}
System.out.println("+");
}
}
Factory Method(工廠方法模式)
登場角色
- Product(產品)
該角色屬於框架一方,定義了模式中實例所持有的接口,但具體的處理則由子類 ConcreteProduct 角色決定。
- Creator(創建者)
該角色屬於框架一方,負責生成 Product 角色的抽象類,但具體的處理則由子類 ConcreteCreator 角色決定。
- ConcreteProduct(具體的產品)
該角色屬於具體加工一方,它決定了具體的產品。
- ConcreteCreator(具體的創建者)
該角色屬於具體加工一方,它負責生成具體的產品。
類圖
示例代碼
public abstract class Product {
public abstract void use();
}
public abstract class Factory {
public final Product create(String owner) {
Product p = createProduct(owner);
registerProduct(p);
return p;
}
protected abstract Product createProduct(String owner);
protected abstract void registerProduct(Product product);
}
public class IDCard extends Product {
private String owner;
IDCard(String owner) {
System.out.println("製作" + owner + "的ID卡。");
this.owner = owner;
}
public void use() {
System.out.println("使用" + owner + "的ID卡。");
}
public String getOwner() {
return owner;
}
}
public class IDCardFactory extends Factory {
private List owners = new ArrayList();
protected Product createProduct(String owner) {
return new IDCard(owner);
}
protected void registerProduct(Product product) {
owners.add(((IDCard)product).getOwner());
}
public List getOwners() {
return owners;
}
}
Singleton(單例模式)
登場角色
- Singleton
只有一個角色,它返回唯一示例的 static 方法,並總是返回同一個示例(在同一個 JVM 內)。
類圖
示例代碼
public class Singleton{
private static class SingletonHolder{
public static Singleton INSTANCE = new Singleton();
}
private Singleton() {}
public static Singleton newInstance(){
return SingletonHolder.INSTANCE;
}
}
Builder(建造者模式)
登場角色
- Builder(建造者)
該角色負責定義用於生成實例的接口。
- ConcreteBuilder(具體的建造者)
該角色是負責實現 Builder 角色的接口的類。
- Director(監工)
該角色負責使用 Builder 角色的接口來生成實例,同時它並不依賴於 ConcreteBuilder 角色。
類圖
示例代碼
public abstract class Builder {
public abstract void makeTitle(String title);
public abstract void makeString(String str);
public abstract void makeItems(String[] items);
public abstract void close();
}
public class HTMLBuilder extends Builder {
private String filename;
private PrintWriter writer;
public void makeTitle(String title) {
filename = title + ".html";
try {
writer = new PrintWriter(new FileWriter(filename));
} catch (IOException e) {
e.printStackTrace();
}
writer.println("<html><head><title>" + title + "</title></head><body>");
writer.println("<h1>" + title + "</h1>");
}
public void makeString(String str) {
writer.println("<p>" + str + "</p>");
}
public void makeItems(String[] items) {
writer.println("<ul>");
for (int i = 0; i < items.length; i++) {
writer.println("<li>" + items[i] + "</li>");
}
writer.println("</ul>");
}
public void close() {
writer.println("</body></html>");
writer.close();
}
public String getResult() {
return filename;
}
}
public class TextBuilder extends Builder {
private StringBuffer buffer = new StringBuffer();
public void makeTitle(String title) {
buffer.append("==============================\n");
buffer.append("『" + title + "』\n");
buffer.append("\n");
}
public void makeString(String str) {
buffer.append('■' + str + "\n");
buffer.append("\n");
}
public void makeItems(String[] items) {
for (int i = 0; i < items.length; i++) {
buffer.append(" ・" + items[i] + "\n");
}
buffer.append("\n");
}
public void close() {
buffer.append("==============================\n");
}
public String getResult() {
return buffer.toString();
}
}
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void construct() {
builder.makeTitle("Greeting");
builder.makeString("從早上至下午");
builder.makeItems(new String[]{
"早上好。",
"下午好。",
});
builder.makeString("晚上");
builder.makeItems(new String[]{
"晚上好。",
"晚安。",
"再見。",
});
builder.close();
}
}
Strategy(策略模式)
登場角色
- Strategy(策略)
該角色負責決定實現策略所必需的接口。
- ConcreteStrategy(具體的策略)
該角色負責實現Strategy角色的接口,即負責實現具體的策略(戰略、方向、方法和算法)。
- Context(上下文)
該角色負責使用 Strategy,保存了 ConcreteStrategy 的實例,並使用 ConcreteStrategy 去實現需求。
類圖
示例代碼
public class Hand {
public static final int HANDVALUE_GUU = 0;
public static final int HANDVALUE_CHO = 1;
public static final int HANDVALUE_PAA = 2;
public static final Hand[] hand = {
new Hand(HANDVALUE_GUU),
new Hand(HANDVALUE_CHO),
new Hand(HANDVALUE_PAA),
};
private static final String[] name = {
"石頭", "剪刀", "布",
};
private int handvalue;
private Hand(int handvalue) {
this.handvalue = handvalue;
}
public static Hand getHand(int handvalue) {
return hand[handvalue];
}
public boolean isStrongerThan(Hand h) {
return fight(h) == 1;
}
public boolean isWeakerThan(Hand h) {
return fight(h) == -1;
}
private int fight(Hand h) {
if (this == h) {
return 0;
} else if ((this.handvalue + 1) % 3 == h.handvalue) {
return 1;
} else {
return -1;
}
}
public String toString() {
return name[handvalue];
}
}
public interface Strategy {
public abstract Hand nextHand();
public abstract void study(boolean win);
}
public class WinningStrategy implements Strategy {
private Random random;
private boolean won = false;
private Hand prevHand;
public WinningStrategy(int seed) {
random = new Random(seed);
}
public Hand nextHand() {
if (!won) {
prevHand = Hand.getHand(random.nextInt(3));
}
return prevHand;
}
public void study(boolean win) {
won = win;
}
}
public class ProbStrategy implements Strategy {
private Random random;
private int prevHandValue = 0;
private int currentHandValue = 0;
private int[][] history = {
{ 1, 1, 1, },
{ 1, 1, 1, },
{ 1, 1, 1, },
};
public ProbStrategy(int seed) {
random = new Random(seed);
}
public Hand nextHand() {
int bet = random.nextInt(getSum(currentHandValue));
int handvalue = 0;
if (bet < history[currentHandValue][0]) {
handvalue = 0;
} else if (bet < history[currentHandValue][0] + history[currentHandValue][1]) {
handvalue = 1;
} else {
handvalue = 2;
}
prevHandValue = currentHandValue;
currentHandValue = handvalue;
return Hand.getHand(handvalue);
}
private int getSum(int hv) {
int sum = 0;
for (int i = 0; i < 3; i++) {
sum += history[hv][i];
}
return sum;
}
public void study(boolean win) {
if (win) {
history[prevHandValue][currentHandValue]++;
} else {
history[prevHandValue][(currentHandValue + 1) % 3]++;
history[prevHandValue][(currentHandValue + 2) % 3]++;
}
}
}
public class Player {
private String name;
private Strategy strategy;
private int wincount;
private int losecount;
private int gamecount;
public Player(String name, Strategy strategy) {
this.name = name;
this.strategy = strategy;
}
public Hand nextHand() {
return strategy.nextHand();
}
public void win() {
strategy.study(true);
wincount++;
gamecount++;
}
public void lose() {
strategy.study(false);
losecount++;
gamecount++;
}
public void even() {
gamecount++;
}
public String toString() {
return "[" + name + ":" + gamecount + " games, " + wincount + " win, " + losecount + " lose" + "]";
}
}
Proxy(代理模式)
登場角色
- Subject(主體)
該角色定義了使 Proxy 和 RealSubject 之間具有一致性的接口。
- Proxy(代理人)
該角色會盡量處理來自 Client 的請求。只有當自己不能處理時,它纔會將工作交給 RealSubject。
- RealSubject(實際的主體)
該角色會在 Proxy 無法勝任工作時出場。
- Client(請求者)
使用 Proxy 模式的角色。
類圖
示例代碼
public interface Printable {
public abstract void setPrinterName(String name);
public abstract String getPrinterName();
public abstract void print(String string);
}
public class Printer implements Printable {
private String name;
public Printer() {
heavyJob("正在生成Printer的實例");
}
public Printer(String name) {
this.name = name;
heavyJob("正在生成Printer的實例(" + name + ")");
}
public void setPrinterName(String name) {
this.name = name;
}
public String getPrinterName() {
return name;
}
public void print(String string) {
System.out.println("=== " + name + " ===");
System.out.println(string);
}
private void heavyJob(String msg) {
System.out.print(msg);
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.print(".");
}
System.out.println("結束。");
}
}
public class PrinterProxy implements Printable {
private String name;
private Printer real;
public PrinterProxy() {
}
public PrinterProxy(String name) {
this.name = name;
}
public synchronized void setPrinterName(String name) {
if (real != null) {
real.setPrinterName(name);
}
this.name = name;
}
public String getPrinterName() {
return name;
}
public void print(String string) {
realize();
real.print(string);
}
private synchronized void realize() {
if (real == null) {
real = new Printer(name);
}
}
}