1.單例模式
public class God {
private volatile static God god;
private God(){}
public static God getInstance() {//廟是開放的不用排隊(duì)進(jìn)入
if (god == null) {//如果頭柱香未產(chǎn)生,這批搶香人進(jìn)入堂內(nèi)排隊(duì)。
synchronized(God.class){
if (god == null) {//只有頭香造了神,其他搶香的白排隊(duì)了
god = new God();
}
}
}
//此處頭柱香產(chǎn)生后不必再排隊(duì)
return god;
}
}
2.適配器模式
public interface TriplePin {
//參數(shù)分別為火線live,零線null,地線earth
public void electrify(int l, int n, int e);
}
public interface DualPin {
public void electrify(int l, int n);//這里沒有地線
}
public class TV implements DualPin {
@Override//既然是兩項(xiàng)插頭,當(dāng)然實(shí)現(xiàn)兩項(xiàng)插標(biāo)準(zhǔn)
public void electrify(int l, int n) {
System.out.println("火線通電:" + l);
System.out.println("零線通電:" + n);
}
}
3.策略模式
public interface Strategy { //算法標(biāo)準(zhǔn)
public int calculate(int a, int b); //操作數(shù),被操作數(shù)
}
public class Addition implements Strategy{ //實(shí)現(xiàn)算法接口
@Override
public int calculate(int a, int b) { //加數(shù)與被加數(shù)
return a + b; //這里我們做加法運(yùn)算
}
}
public class Subtraction implements Strategy{ //實(shí)現(xiàn)算法接口
@Override
public int calculate(int a, int b) { //減數(shù)與被減數(shù)
return a - b; //這里我們做減法運(yùn)算
}
}
public class Calculator { //計(jì)算器類
private Strategy strategy; //擁有某種算法策略
public void setStrategy(Strategy strategy) { //接入算法策略
this.strategy = strategy;
}
public int getResult(int a, int b) {
return this.strategy.calculate(a, b); //返回具體策略的結(jié)果
}
}
4.狀態(tài)模式
public interface State {
public void switchOn(Switcher switcher);//開
public void switchOff(Switcher switcher);//關(guān)
}
public class On implements State {
@Override
public void switchOn(Switcher switcher) {
System.out.println("WARN!!!通電狀態(tài)無需再開");
return;
}
@Override
public void switchOff(Switcher switcher) {
switcher.setState(new Off());
System.out.println("OK...燈滅");
}
}
public class Off implements State {
@Override
public void switchOn(Switcher switcher) {
switcher.setState(new On());
System.out.println("OK...燈亮");
}
@Override
public void switchOff(Switcher switcher) {
System.out.println("WARN!!!斷電狀態(tài)無需再關(guān)");
return;
}
}
public class Switcher {
//開關(guān)的初始狀態(tài)設(shè)置為“關(guān)”
private State state = new Off();
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void switchOn() {
//這里調(diào)用的是當(dāng)前狀態(tài)的開方法
state.switchOn(this);
}
public void switchOff(){
//這里調(diào)用的是當(dāng)前狀態(tài)的關(guān)方法
state.switchOff(this);
}
}
5.模板方法模式
public abstract class PM {
protected abstract void analyze(); //需求分析
protected abstract void design(); //設(shè)計(jì)
protected abstract void develop(); //開發(fā)
protected abstract boolean test(); //測試
protected abstract void release(); //發(fā)布
protected final void kickoff(){
analyze();
design();
do {
develop();
} while (!test());//如果測試失敗,則繼續(xù)開發(fā)改Bug。
release();
}
}
public class AutoTestPM extends PM {
@Override
protected void analyze() {
System.out.println("進(jìn)行業(yè)務(wù)溝通,需求分析");
}
//design();develop();test();release();實(shí)現(xiàn)省略
}
6.門面模式
public class VegVendor { //菜販子
public void sell() {
System.out.println("菜販子賣菜。。。");
}
}
public class GirlFriend { //女友
public void cook() {
System.out.println("女友烹飪。。。");
}
}
public class Me {
public void eat() {
System.out.println("我只會吃。。。");
}
public static void main(String[] args) {
//找菜販子買菜
VegVendor vv = new VegVendor();
vv.sell();
//找女友做飯
GirlFriend gf = new GirlFriend();
gf.cook();
//我只會吃
Me me = new Me();
me.eat();
//誰洗碗呢?一場戰(zhàn)場一觸即發(fā)……
}
}
public class Facade {
private VegVendor vv;
private Chef chef;
private Waiter waiter;
private Cleaner cleaner;
public Facade() {
this.vv = new VegVendor();
//開門前就找菜販子準(zhǔn)備好蔬菜
vv.sell();
//當(dāng)然還得雇傭好各類飯店服務(wù)人員
this.chef = new Chef();
this.waiter = new Waiter();
this.cleaner = new Cleaner();
}
public void provideService(){
//接待,入座,點(diǎn)菜
waiter.order();
//找廚師做飯
chef.cook();
//上菜
waiter.serve();
//收拾桌子,洗碗,以及其他工序……
cleaner.clean();
cleaner.wash();
}
}
7.裝飾器模式
public interface Showable {
public void show();// 定義展示行為
}
public class Girl implements Showable {
@Override
public void show() {
System.out.print("女孩的素顏");
}
}
public abstract class Decorator implements Showable {
protected Showable showable;
protected Decorator(Showable showable) {
this.showable = showable;
}
@Override
public void show() {
showable.show();// 直接調(diào)用不做加任何粉飾。
}
}
public class FoundationMakeup extends Decorator {
// 調(diào)用化妝品父類注入
public FoundationMakeup(Showable showable) {
super(showable);
}
@Override
public void show() {
System.out.print("打粉底(");
showable.show();
System.out.print(")");
}
}
public class Lipstick extends Decorator {
public Lipstick(Showable showable) {
super(showable);
}
@Override
public void show() {
System.out.print("涂口紅(");
showable.show();
System.out.print(")");
}
}
public class Demo
public static void main(String[] args) {
// 口紅包裹粉底,再包裹女友。
Showable madeupGirl = new Lipstick(new FoundationMakeup(new Girl()));
madeupGirl.show();
// 運(yùn)行結(jié)果:涂口紅(打粉底(女孩的臉龐))
}
}
8.中介模式
public class User {
private String name;// 名字
private ChatRoom chatRoom;// 聊天室引用
public User(String name) {
this.name = name;// 初始化必須起名字
}
public String getName() {
return this.name;
}
public void login(ChatRoom chatRoom) {// 用戶登陸
chatRoom.connect(this); // 調(diào)用聊天室連接方法
this.chatRoom = chatRoom; // 注入聊天室引用
}
public void talk(String msg) { // 用戶發(fā)言
chatRoom.sendMsg(this, msg); // 給聊天室發(fā)消息
}
public void listen(User fromWhom, String msg) { // 且聽風(fēng)吟
System.out.print("【" + this.name + "的對話框】");
System.out.println(fromWhom.getName() + " 說: " + msg);
}
}
import java.util.ArrayList;
import java.util.List;
public class ChatRoom {
private String name;// 聊天室命名
public ChatRoom(String name) {
this.name = name;// 初始化必須命名聊天室
}
List<User> users = new ArrayList<>();// 聊天室里的用戶們
public void connect(User user) {
this.users.add(user);// 用戶進(jìn)入聊天室加入列表。
System.out.print("歡迎【");
System.out.print(user.getName());
System.out.println("】加入聊天室【" + this.name + "】");
}
public void sendMsg(User fromWhom, String msg) {
// 循環(huán)所有用戶,只發(fā)消息給非發(fā)送方fromWhom。
users.stream().filter(user -> !user.equals(fromWhom))// 過濾掉發(fā)送方fromWhom
.forEach(toWhom -> toWhom.listen(fromWhom, msg));// 發(fā)送消息給剩下的所有人
}
}
9.組合模式
public abstract class Node {
protected String name; // 節(jié)點(diǎn)命名
public Node(String name) { // 構(gòu)造節(jié)點(diǎn),傳入節(jié)點(diǎn)名。
this.name = name;
}
// 增加后續(xù)子節(jié)點(diǎn)方法
protected abstract void add(Node child);
protected void ls(int space) {
for (int i = 0; i < space; i++) {
System.out.print(" ");// 先循環(huán)輸出n個空格;
}
System.out.println(name);// 然后再打印自己的名字。
}
}
public class File extends Node {
public File(String name) {
super(name);
}
@Override
protected void add(Node child) {
System.out.println("不能添加子節(jié)點(diǎn)。");
}
@Override
public void ls(int space) {
super.ls(space);
}
}
public class Folder extends Node {
// 文件夾可以包含子節(jié)點(diǎn)(文件夾或者文件)。
private List<Node> childrenNodes = new ArrayList<>();
public Folder(String name) {
super(name); // 調(diào)用父類“節(jié)點(diǎn)”的構(gòu)造方法命名。
}
@Override
protected void add(Node child) {
childrenNodes.add(child); // 可以添加子節(jié)點(diǎn)。
}
@Override
public void ls(int space) {
super.ls(space); // 調(diào)用父類共通的ls方法列出自己的名字。
space++; // 之后列出的子節(jié)點(diǎn)前,空格數(shù)要增加一個了。
for (Node node : childrenNodes) {
node.ls(space); // 調(diào)用子節(jié)點(diǎn)的ls方法。
}
}
}
10.迭代器模式
public interface Iterator<E> {
E next(); //返回下一個元素
boolean hasNext(); //是否還有下一個元素
}
public class DrivingRecorder {
private int index = -1; // 當(dāng)前記錄位置
private String[] records = new String[10]; // 假設(shè)只能記錄10條視頻
public void append(String record) {
if (index == 9) { // 循環(huán)覆蓋
index = 0;
} else {
index++;
}
records[index] = record;
}
public Iterator<String> iterator() {
return new Itr();
}
private class Itr implements Iterator<String> {
int cursor = index; // 迭代器游標(biāo),不染指原始游標(biāo)。
int loopCount = 0;
@Override
public boolean hasNext() {
return loopCount < 10;
}
@Override
public String next() {
int i = cursor; // 記錄即將返回的游標(biāo)位置
if (cursor == 0) {
cursor = 9;
} else {
cursor--;
}
loopCount++;
return records[i];
}
};
}
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) {
DrivingRecorder dr = new DrivingRecorder();
// 假設(shè)記錄了12條視頻
for (int i = 0; i < 12; i++) {
dr.append("視頻_" + i);
}
// 用戶要獲取交通事故視頻,定義事故列表。
List<String> accidents = new ArrayList<>();
// 用戶拿到迭代器
Iterator<String> it = dr.iterator();
while (it.hasNext()) {// 如果還有下一條則繼續(xù)迭代
String video = it.next();
System.out.println(video);
// 用戶翻看視頻發(fā)現(xiàn)10和8可作為證據(jù)。
if ("視頻_10".equals(video) || "視頻_8".equals(video)) {
accidents.add(video);
}
}
// 拿到兩個視頻集accidents交給交警查看。
System.out.println("事故證據(jù):" + accidents);
/*
* 視頻_11
* 視頻_10
* 視頻_9
* 視頻_8
* 視頻_7
* 視頻_6
* 視頻_5
* 視頻_4
* 視頻_3
* 視頻_2
* 事故證據(jù):[視頻_10, 視頻_8]
*/
}
}
11.備忘錄模式
public class Doc {
private String title; // 文章名字
private String body; // 文章內(nèi)容
public Doc(String title) { // 新建文檔先命名
this.title = title;
this.body = "";
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public History createHistory() {
return new History(body);// 創(chuàng)建歷史記錄
}
public void restoreHistory(History history) {
this.body = history.getBody();// 恢復(fù)歷史記錄
}
}
public class History {
private String body; // 用于備忘文章內(nèi)容
public History(String body) {
this.body = body;
}
public String getBody() {
return body;
}
}
import java.util.ArrayList;
import java.util.List;
public class Editor {
private Doc doc;
private List<History> historyRecords;// 歷史記錄列表
private int historyPosition = -1; // 歷史記錄當(dāng)前位置
public Editor(Doc doc) {
System.out.println("<<<打開文檔" + doc.getTitle());
this.doc = doc; // 注入文檔
historyRecords = new ArrayList<>(); // 初始化歷史記錄
backup(); // 保存一份歷史記錄
show(); // 顯示內(nèi)容
}
public void append(String txt) {
System.out.println("<<<插入操作");
doc.setBody(doc.getBody() + txt);
backup(); // 操作完成后保存歷史記錄
show();
}
public void save() {
System.out.println("<<<存盤操作");
}
public void delete() {
System.out.println("<<<刪除操作");
doc.setBody("");
backup(); // 操作完成后保存歷史記錄
show();
}
private void backup() {
historyRecords.add(doc.createHistory());
historyPosition++;
}
private void show() { // 顯示當(dāng)前文本內(nèi)容
System.out.println(doc.getBody());
System.out.println("文章結(jié)束>>>\n");
}
public void undo() { // 撤銷操作:如按下Ctr+Z,回到過去。
System.out.println(">>>撤銷操作");
if (historyPosition == 0) {
return; // 到頭了,不能再撤銷了。
}
historyPosition--; // 歷史記錄位置回滾一筆
History history = historyRecords.get(historyPosition);
doc.restoreHistory(history);// 取出歷史記錄并恢復(fù)至文檔
show();
}
// public void redo(); 省略實(shí)現(xiàn)代碼
}
public class Author {
public static void main(String[] args) {
Editor editor = new Editor(new Doc("《AI的覺醒》"));
/*
* <<<打開文檔《AI的覺醒》
* 文章結(jié)束>>>
*/
editor.append("第一章 混沌初開");
/*
* <<<插入操作 第一章 混沌初開 文章結(jié)束>>>
*/
editor.append("\n 正文2000字……");
/*
* <<<插入操作 第一章 混沌初開 正文2000字…… 文章結(jié)束>>>
*/
editor.append("\n 第二章 荒漠之花\n 正文3000字……");
/*
* <<<插入操作 第一章 混沌初開 正文2000字…… 第二章 荒漠之花 正文3000字…… 文章結(jié)束>>>
*/
editor.delete();
/*
* <<<刪除操作
* 文章結(jié)束>>>
*/
// 吃下后悔藥,我的世界又完整了。
editor.undo();
/*
* >>>撤銷操作 第一章 混沌初開 正文2000字…… 第二章 荒漠之花 正文3000字…… 文章結(jié)束>>>
*/
}
}
12.代理模式
public interface Internet { // 互聯(lián)網(wǎng)訪問接口
public void access(String url);
}
public interface Intranet { // 局域網(wǎng)訪問接口
public void fileAccess(String path);
}
public class Modem implements Internet {// 調(diào)制解調(diào)器
@Override
public void access(String url) {// 實(shí)現(xiàn)互聯(lián)網(wǎng)訪問接口
System.out.println("正在訪問:" + url);
}
}
public class Switch implements Intranet {
@Override
public void fileAccess(String path) {
System.out.println("訪問內(nèi)網(wǎng):" + path);
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
public class KeywordFilter implements InvocationHandler {
private List<String> blackList = Arrays.asList("電影", "游戲", "音樂", "小說");
// 被代理的真實(shí)對象,貓、交換機(jī)、或是別的什么都是。
private Object origin;
public KeywordFilter(Object origin) {
this.origin = origin;// 注入被代理對象
System.out.println("開啟關(guān)鍵字過濾模式...");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 要被切入方法面之前的業(yè)務(wù)邏輯
String arg = args[0].toString();
for (String keyword : blackList) {
if (arg.toString().contains(keyword)) {
System.out.println("禁止訪問:" + arg);
return null;
}
}
// 調(diào)用真實(shí)的被代理對象方法
return method.invoke(origin, arg);
}
}
import java.util.Arrays;
import java.util.List;
public class RouterProxy implements Internet { // 路由器代理類,互聯(lián)網(wǎng)訪問接口
private Internet modem; // 持有被代理類引用
private List<String> blackList = Arrays.asList("電影", "游戲", "音樂", "小說");
public RouterProxy() {
this.modem = new Modem(); // 實(shí)例化被代理類
System.out.println("撥號上網(wǎng)...連接成功!");
}
@Override
public void access(String url) { // 同樣實(shí)現(xiàn)互聯(lián)網(wǎng)訪問接口方法
for (String keyword : blackList) {// 循環(huán)黑名單
if (url.contains(keyword)) { // 是否包含黑名單字眼
System.out.println("禁止訪問:" + url);
return;
}
}
modem.access(url); // 正常訪問互聯(lián)網(wǎng)
}
}
import java.lang.reflect.Proxy;
public class Demo {
public static void main(String[] args) {
// 訪問外網(wǎng)(互聯(lián)網(wǎng)), 生成貓代理。
Internet internet = (Internet) Proxy.newProxyInstance(Modem.class.getClassLoader(),
Modem.class.getInterfaces(), new KeywordFilter(new Modem()));
internet.access("http://www.電影.com");
internet.access("http://www.游戲.com");
internet.access("http://www.學(xué)習(xí).com");
internet.access("http://www.工作.com");
// 訪問內(nèi)網(wǎng)(局域網(wǎng)), 生成交換機(jī)代理。
Intranet intranet = (Intranet) Proxy.newProxyInstance(Switch.class.getClassLoader(),
Switch.class.getInterfaces(), new KeywordFilter(new Switch()));
intranet.fileAccess("\\\\192.68.1.2\\共享\\電影\\IronHuman.mp4");
intranet.fileAccess("\\\\192.68.1.2\\共享\\游戲\\Hero.exe");
intranet.fileAccess("\\\\192.68.1.4\\shared\\Java學(xué)習(xí)資料.zip");
intranet.fileAccess("\\\\192.68.1.6\\Java知音\\設(shè)計(jì)模式是什么鬼.doc");
/*
開啟關(guān)鍵字過濾模式...
禁止訪問:http://www.電影.com
禁止訪問:http://www.游戲.com
正在訪問:http://www.學(xué)習(xí).com
正在訪問:http://www.工作.com
開啟關(guān)鍵字過濾模式...
禁止訪問:\\192.68.1.2\共享\電影\IronHuman.mp4
禁止訪問:\\192.68.1.2\共享\游戲\Hero.exe
訪問內(nèi)網(wǎng):\\192.68.1.4\shared\Java學(xué)習(xí)資料.zip
訪問內(nèi)網(wǎng):\\192.68.1.6\Java知音\設(shè)計(jì)模式是什么鬼.doc
*/
}
}
13.工廠方法模式
public abstract class Enemy {
// 敵人的坐標(biāo),會被子類繼承。
protected int x;
protected int y;
// 初始化坐標(biāo)
Enemy(int x, int y) {
this.x = x;
this.y = y;
}
// 抽象方法,在地圖上繪制。
public abstract void show();
}
public class Airplane extends Enemy {
public Airplane(int x, int y) {
super(x, y);// 調(diào)用父類構(gòu)造子初始化坐標(biāo)
}
@Override
public void show() {
System.out.println("飛機(jī)出現(xiàn)坐標(biāo):" + x + "," + y);
System.out.println("飛機(jī)向玩家發(fā)起攻擊……");
}
}
public class Tank extends Enemy {
public Tank(int x, int y) {
super(x, y);
}
@Override
public void show() {
System.out.println("坦克出現(xiàn)坐標(biāo):" + x + "," + y);
System.out.println("坦克向玩家發(fā)起攻擊……");
}
}
public class Boss extends Enemy {
public Boss(int x, int y) {
super(x, y);
}
@Override
public void show() {
System.out.println("Boss出現(xiàn)坐標(biāo):" + x + "," + y);
System.out.println("Boss向玩家發(fā)起攻擊……");
}
}
public interface Factory {
public Enemy create(int screenWidth);
}
import java.util.Random;
public class RandomFactory implements Factory {
private Random random = new Random();
@Override
public Enemy create(int screenWidth) {
Enemy enemy = null;
if (random.nextBoolean()) {
enemy = new Airplane(random.nextInt(screenWidth), 0); // 實(shí)例化飛機(jī)
} else {
enemy = new Tank(random.nextInt(screenWidth), 0); // 實(shí)例化坦克
}
return enemy;
}
}
public class BossFactory implements Factory {
@Override
public Enemy create(int screenWidth) {
// boss應(yīng)該出現(xiàn)在屏幕中央
return new Boss(screenWidth / 2, 0);
}
}
public class Demo {
public static void main(String[] args) {
int screenWidth = 100;
System.out.println("游戲開始");
Factory factory = new RandomFactory();
for (int i = 0; i < 10; i++) {
factory.create(screenWidth).show();
}
System.out.println("抵達(dá)關(guān)底");
factory = new BossFactory();
factory.create(screenWidth).show();
/*
游戲開始
飛機(jī)出現(xiàn)坐標(biāo):27,0
飛機(jī)向玩家發(fā)起攻擊……
坦克出現(xiàn)坐標(biāo):40,0
坦克向玩家發(fā)起攻擊……
飛機(jī)出現(xiàn)坐標(biāo):30,0
飛機(jī)向玩家發(fā)起攻擊……
坦克出現(xiàn)坐標(biāo):53,0
坦克向玩家發(fā)起攻擊……
坦克出現(xiàn)坐標(biāo):19,0
坦克向玩家發(fā)起攻擊……
飛機(jī)出現(xiàn)坐標(biāo):18,0
飛機(jī)向玩家發(fā)起攻擊……
坦克出現(xiàn)坐標(biāo):27,0
坦克向玩家發(fā)起攻擊……
飛機(jī)出現(xiàn)坐標(biāo):89,0
飛機(jī)向玩家發(fā)起攻擊……
飛機(jī)出現(xiàn)坐標(biāo):24,0
飛機(jī)向玩家發(fā)起攻擊……
飛機(jī)出現(xiàn)坐標(biāo):31,0
飛機(jī)向玩家發(fā)起攻擊……
抵達(dá)關(guān)底
Boss出現(xiàn)坐標(biāo):50,0
Boss向玩家發(fā)起攻擊……
*/
}
}
14.橋接模式
public interface Ruler {// 尺子
// 規(guī)則化筆觸走向
public void regularize();
}
public class CircleRuler implements Ruler {
@Override
public void regularize() { // 尺子模板畫出圓形
System.out.println("○");
}
}
public class SquareRuler implements Ruler {
@Override
public void regularize() { // 尺子模板畫出正方形
System.out.println("□");
}
}
public class TriangleRuler implements Ruler {
@Override
public void regularize() { // 尺子模板畫出三角形
System.out.println("△");
}
}
public abstract class Pen {// 畫筆
protected Ruler ruler;// 尺子的引用
public Pen(Ruler ruler) {
this.ruler = ruler;
}
public abstract void draw();// 抽象方法
}
public class BlackPen extends Pen {
public BlackPen(Ruler ruler) {
super(ruler);
}
@Override
public void draw() {
System.out.print("黑");
ruler.regularize();
}
}
public class WhitePen extends Pen {
public WhitePen(Ruler ruler) {
super(ruler);
}
@Override
public void draw() {
System.out.print("白");
ruler.regularize();
}
}
public class Demo {
public static void main(String args[]) {
// 白色畫筆對應(yīng)的所有形狀
new WhitePen(new CircleRuler()).draw();
new WhitePen(new SquareRuler()).draw();
new WhitePen(new TriangleRuler()).draw();
// 黑色畫筆對應(yīng)的所有形狀
new BlackPen(new CircleRuler()).draw();
new BlackPen(new SquareRuler()).draw();
new BlackPen(new TriangleRuler()).draw();
/*運(yùn)行結(jié)果:
白○
白□
白△
黑○
黑□
黑△
*/
}
}
15.建造者模式
public interface Builder { // 施工方接口
public void buildBasement();
public void buildWall();
public void buildRoof();
public Building getBuilding();
}
import java.util.ArrayList;
import java.util.List;
public class Building { // 建筑物
// 用來模擬房子組件的堆疊
private List<String> buildingComponents = new ArrayList<>();
// 地基
public void setBasement(String basement) {
this.buildingComponents.add(basement);
}
// 墻體
public void setWall(String wall) {
this.buildingComponents.add(wall);
}
// 房頂
public void setRoof(String roof) {
this.buildingComponents.add(roof);
}
@Override
public String toString() {
String buildingStr = "";
for (int i = buildingComponents.size() - 1; i >= 0; i--) {
buildingStr += buildingComponents.get(i);
}
return buildingStr;
}
}
public class ApartmentBuilder implements Builder {// 高層公寓樓施工方
private Building apartment;
public ApartmentBuilder() {
apartment = new Building();
}
@Override
public void buildBasement() {
System.out.println("深挖地基,修建地下車庫,部署管道、線纜、風(fēng)道。");
apartment.setBasement("╚═════════╝\n");
}
@Override
public void buildWall() {
System.out.println("搭建多層建筑框架,建造電梯井,鋼筋混凝土澆灌。");
for (int i = 0; i < 8; i++) {// 此處假設(shè)固定8層
apartment.setWall("║ □ □ □ □ ║\n");
}
}
@Override
public void buildRoof() {
System.out.println("封頂,部署通風(fēng)井,做防水層,保溫層。");
apartment.setRoof("╔═════════╗\n");
}
@Override
public Building getBuilding() {
return apartment;
}
}
public class HouseBuilder implements Builder { // 別墅施工方
private Building house;
public HouseBuilder() {
house = new Building();
}
@Override
public void buildBasement() {
System.out.println("挖地基,部署管道、線纜,水泥加固,搭建圍墻、花園。");
house.setBasement("╬╬╬╬╬╬╬╬\n");
}
@Override
public void buildWall() {
System.out.println("搭建木質(zhì)框架,石膏板封墻并粉飾內(nèi)外墻。");
house.setWall("|田|田 田|\n");
}
@Override
public void buildRoof() {
System.out.println("建造木質(zhì)屋頂、閣樓,安裝煙囪,做好防水。");
house.setRoof("╱◥███◣\n");
}
@Override
public Building getBuilding() {
return house;
}
}
public class Director {// 工程總監(jiān)
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void setBuilder(Builder builder) {
this.builder = builder;
}
public Building direct() {
System.out.println("=====工程項(xiàng)目啟動=====");
// 第一步,打好地基;
builder.buildBasement();
// 第二步,建造框架、墻體;
builder.buildWall();
// 第三步,封頂;
builder.buildRoof();
System.out.println("=====工程項(xiàng)目竣工=====");
return builder.getBuilding();
}
}
public class Demo {
public static void main(String[] args) {
// 招工,建別墅。
Builder builder = new HouseBuilder();
// 交給工程總監(jiān)
Director director = new Director(builder);
System.out.println(director.direct());
// 替換施工方,建公寓。
director.setBuilder(new ApartmentBuilder());
System.out.println(director.direct());
}
}
16.命令模式
public interface Switchable {// 電器接口
// 通電
public void on();
// 斷電
public void off();
}
public interface Device extends Switchable {
// 頻道+
public void channelUp();
// 頻道-
public void channelDown();
// 音量+
public void volumeUp();
// 音量-
public void volumeDown();
}
public class Radio implements Device {
@Override
public void on() {
System.out.println("收音機(jī)啟動");
}
@Override
public void off() {
System.out.println("收音機(jī)關(guān)閉");
}
@Override
public void channelUp() {
System.out.println("收音機(jī)調(diào)頻+");
}
@Override
public void channelDown() {
System.out.println("收音機(jī)調(diào)頻-");
}
@Override
public void volumeUp() {
System.out.println("收音機(jī)音量+");
}
@Override
public void volumeDown() {
System.out.println("收音機(jī)音量-");
}
}
public class TV implements Device {
@Override
public void on() {
System.out.println("電視機(jī)啟動");
}
@Override
public void off() {
System.out.println("電視機(jī)關(guān)閉");
}
@Override
public void channelUp() {
System.out.println("電視機(jī)頻道+");
}
@Override
public void channelDown() {
System.out.println("電視機(jī)頻道-");
}
@Override
public void volumeUp() {
System.out.println("電視機(jī)音量+");
}
@Override
public void volumeDown() {
System.out.println("電視機(jī)音量-");
}
}
public interface Command {
// 執(zhí)行命令操作
public void exe();
// 反執(zhí)行命令操作
public void unexe();
}
public class SwitchCommand implements Command {
private Device device;// 此處持有高級設(shè)備接口。
public SwitchCommand(Device device) {
this.device = device;
}
@Override
public void exe() {
device.on();// 執(zhí)行命令調(diào)用開機(jī)操作
}
@Override
public void unexe() {
device.off();// 反執(zhí)行命令調(diào)用關(guān)機(jī)操作
}
}
public class ChannelCommand implements Command {
private Device device;
public ChannelCommand(Device device) {
this.device = device;
}
@Override
public void exe() {
device.channelUp();
}
@Override
public void unexe() {
device.channelDown();
}
}
public class VolumeCommand implements Command {
private Device device;
public VolumeCommand(Device device) {
this.device = device;
}
@Override
public void exe() {
device.volumeUp();
}
@Override
public void unexe() {
device.volumeDown();
}
}
public class Controller {
private Command okCommand;
private Command verticalCommand;
private Command horizontalCommand;
// 綁定OK鍵命令
public void bindOKCommand(Command okCommand) {
this.okCommand = okCommand;
}
// 綁定上下方向鍵命令
public void bindVerticalCommand(Command verticalCommand) {
this.verticalCommand = verticalCommand;
}
// 綁定左右方向鍵命令
public void bindHorizontalCommand(Command horizontalCommand) {
this.horizontalCommand = horizontalCommand;
}
// 開始按鍵映射命令
public void buttonOKHold() {
System.out.print("長按OK按鍵……");
okCommand.exe();
}
public void buttonOKClick() {
System.out.print("單擊OK按鍵……");
okCommand.unexe();
}
public void buttonUpClick() {
System.out.print("單擊↑按鍵……");
verticalCommand.exe();
}
public void buttonDownClick() {
System.out.print("單擊↓按鍵……");
verticalCommand.unexe();
}
public void buttonLeftClick() {
System.out.print("單擊←按鍵……");
horizontalCommand.unexe();
}
public void buttonRightClick() {
System.out.print("單擊→按鍵……");
horizontalCommand.exe();
}
}
public class Demo {
public static void main(String[] args) {
System.out.println("===客戶端用【可編程式遙控器】操作電器===");
Device tv = new TV();
Device radio = new Radio();
Controller controller = new Controller();
//綁定【電視機(jī)】的【命令】到【控制器按鍵】
controller.bindOKCommand(new SwitchCommand(tv));
controller.bindVerticalCommand(new ChannelCommand(tv));//上下調(diào)臺
controller.bindHorizontalCommand(new VolumeCommand(tv));//左右調(diào)音
controller.buttonOKHold();
controller.buttonUpClick();
controller.buttonUpClick();
controller.buttonDownClick();
controller.buttonRightClick();
/*打印輸出:
===客戶端用【可編程式遙控器】操作電器===
長按OK按鍵……電視機(jī)啟動
單擊↑按鍵……電視機(jī)頻道+
單擊↑按鍵……電視機(jī)頻道+
單擊↓按鍵……電視機(jī)頻道-
單擊→按鍵……電視機(jī)音量+
*/
//綁定【收音機(jī)】的【命令】到【控制器按鍵】
controller.bindOKCommand(new SwitchCommand(radio));
controller.bindVerticalCommand(new VolumeCommand(radio)); //上下調(diào)音
controller.bindHorizontalCommand(new ChannelCommand(radio)); //左右調(diào)臺
controller.buttonOKHold();
controller.buttonUpClick();
controller.buttonUpClick();
controller.buttonRightClick();
controller.buttonDownClick();
/*打印輸出:
長按OK按鍵……收音機(jī)啟動
單擊↑按鍵……收音機(jī)音量+
單擊↑按鍵……收音機(jī)音量+
單擊→按鍵……收音機(jī)調(diào)頻+
單擊↓按鍵……收音機(jī)音量-
*/
}
}
17.訪問者模式
import java.time.LocalDate;
public abstract class Product {
protected String name; // 品名
protected LocalDate producedDate;// 生產(chǎn)日期
protected float price; // 價格
Product(String name, LocalDate producedDate, float price) {
this.name = name;
this.producedDate = producedDate;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDate getProducedDate() {
return producedDate;
}
public void setProducedDate(LocalDate producedDate) {
this.producedDate = producedDate;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
import java.time.LocalDate;
public class Candy extends Product implements Acceptable{ // 糖果類
public Candy(String name, LocalDate producedDate, float price) {
super(name, producedDate, price);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);// 把自己交給拜訪者。
}
}
import java.time.LocalDate;
public class Fruit extends Product implements Acceptable {// 水果
private float weight;
public Fruit(String name, LocalDate producedDate, float price, float weight) {
super(name, producedDate, price);
this.weight = weight;
}
public float getWeight() {
return weight;
}
public void setWeight(float weight) {
this.weight = weight;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);// 把自己交給拜訪者。
}
}
import java.time.LocalDate;
public class Wine extends Product implements Acceptable { // 酒類
public Wine(String name, LocalDate producedDate, float price) {
super(name, producedDate, price);
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);// 把自己交給拜訪者。
}
}
public interface Visitor { // 訪問者接口
public void visit(Candy candy);// 糖果重載方法
public void visit(Wine wine); // 酒類重載方法
public void visit(Fruit fruit);// 水果重載方法
}
import java.text.NumberFormat;
import java.time.LocalDate;
public class DiscountVisitor implements Visitor {
private LocalDate billDate;
public DiscountVisitor(LocalDate billDate) {
this.billDate = billDate;
System.out.println("結(jié)算日期:" + billDate);
}
@Override
public void visit(Candy candy) {
System.out.println("=====糖果【" + candy.getName() + "】打折后價格=====");
float rate = 0;
long days = billDate.toEpochDay() - candy.getProducedDate().toEpochDay();
if (days > 180) {
System.out.println("超過半年過期糖果,請勿食用!");
} else {
rate = 0.9f;
}
float discountPrice = candy.getPrice() * rate;
System.out.println(NumberFormat.getCurrencyInstance().format(discountPrice));
}
@Override
public void visit(Wine wine) {
System.out.println("=====酒品【" + wine.getName() + "】無折扣價格=====");
System.out.println(NumberFormat.getCurrencyInstance().format(wine.getPrice()));
}
@Override
public void visit(Fruit fruit) {
System.out.println("=====水果【" + fruit.getName() + "】打折后價格=====");
float rate = 0;
long days = billDate.toEpochDay() - fruit.getProducedDate().toEpochDay();
if (days > 7) {
System.out.println("¥0.00元(超過一周過期水果,請勿食用?。?);
} else if (days > 3) {
rate = 0.5f;
} else {
rate = 1;
}
float discountPrice = fruit.getPrice() * fruit.getWeight() * rate;
System.out.println(NumberFormat.getCurrencyInstance().format(discountPrice));
}
}
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
public class Demo {
public static void main(String[] args) {
// 三件商品加入購物車
List<Acceptable> products = Arrays.asList(
new Candy("小黑兔奶糖", LocalDate.of(2018, 10, 1), 20.00f),
new Wine("貓?zhí)┌拙?, LocalDate.of(2017, 1, 1), 1000.00f),
new Fruit("草莓", LocalDate.of(2018, 12, 26), 10.00f, 2.5f));
Visitor discountVisitor = new DiscountVisitor(LocalDate.of(2019, 1, 1));
// 迭代購物車輪流結(jié)算
for (Acceptable product : products) {
product.accept(discountVisitor);
}
/*
* 打印輸出: 結(jié)算日期:2019-01-01 =====糖果【小黑兔奶糖】打折后價格===== ¥18.00 =====酒品【貓?zhí)┌拙啤繜o折扣價格=====
* ¥1,000.00 =====水果【草莓】打折后價格===== ¥12.50
*/
}
}
18.解釋器模式
public interface Expression { // 表達(dá)式接口
public void interpret(); // 解釋方法
}
public class Delay implements Expression {
private int seconds;// 延時秒數(shù)
public Delay(int seconds) {
this.seconds = seconds;
}
public int getSeconds() {
return seconds;
}
public void interpret() {
System.out.println("系統(tǒng)延遲:" + seconds + "秒鐘");
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class LeftClick implements Expression {
private Expression leftDown;
private Expression leftUp;
public LeftClick() {
this.leftDown = new LeftDown();
this.leftUp = new LeftUp();
}
public void interpret() {
// 單擊=先按下再松開
leftDown.interpret();
leftUp.interpret();
}
}
public class LeftDown implements Expression {
public void interpret() {
System.out.println("按下鼠標(biāo):左鍵");
}
}
public class LeftUp implements Expression {
public void interpret() {
System.out.println("松開鼠標(biāo):左鍵");
}
}
public class LeftClick implements Expression {
private Expression leftDown;
private Expression leftUp;
public LeftClick() {
this.leftDown = new LeftDown();
this.leftUp = new LeftUp();
}
public void interpret() {
// 單擊=先按下再松開
leftDown.interpret();
leftUp.interpret();
}
}
public class Move implements Expression {
// 鼠標(biāo)位置坐標(biāo)
private int x, y;
public Move(int x, int y) {
this.x = x;
this.y = y;
}
public void interpret() {
System.out.println("移動鼠標(biāo):【" + x + "," + y + "】");
}
}
public class Repetition implements Expression {
private int loopCount; // 循環(huán)次數(shù)
private Expression expression;// 循環(huán)體表達(dá)式
public Repetition(Expression expression, int loopCount) {
this.expression = expression;
this.loopCount = loopCount;
}
public void interpret() {
while (loopCount > 0) {
expression.interpret();
loopCount--;
}
}
}
public class Sequence {
// 指令集序列
private List<Expression> expressions;
public Sequence(List<Expression> expressions) {
this.expressions = expressions;
}
public void interpret() {
// 循環(huán)挨個解析每條指令
expressions.forEach(exp -> exp.interpret());
}
}
import java.util.Arrays;
public class Demo {
public static void main(String[] args) {
/*
* BEGIN // 腳本開始
* MOVE 500,600; // 鼠標(biāo)移動到坐標(biāo)(500, 600)
* BEGIN LOOP 5 // 開始循環(huán)5次
* LEFT_CLICK; // 循環(huán)體內(nèi)單擊左鍵
* DELAY 1; // 每次延時1秒
* END; // 循環(huán)體結(jié)束
* RIGHT_DOWN; // 按下右鍵
* DELAY 7200; // 延時2小時
* END; // 腳本結(jié)束
*/
// 構(gòu)造指令集語義樹,實(shí)際情況會交給語法解析器(Evaluator or Parser)。
Expression sequence = new Sequence(Arrays.asList(
new Move(500, 600),
new Repetition(
new Sequence(
Arrays.asList(new LeftClick(),
new Delay(1))
),
5
),
new RightDown(),
new Delay(7200)
));
sequence.interpret();
/*打印輸出
移動鼠標(biāo):【500,600】
按下鼠標(biāo):左鍵
松開鼠標(biāo):左鍵
系統(tǒng)延遲:1秒鐘
按下鼠標(biāo):左鍵
松開鼠標(biāo):左鍵
系統(tǒng)延遲:1秒鐘
按下鼠標(biāo):左鍵
松開鼠標(biāo):左鍵
系統(tǒng)延遲:1秒鐘
按下鼠標(biāo):左鍵
松開鼠標(biāo):左鍵
系統(tǒng)延遲:1秒鐘
按下鼠標(biāo):左鍵
松開鼠標(biāo):左鍵
系統(tǒng)延遲:1秒鐘
按下鼠標(biāo):右鍵
系統(tǒng)延遲:7200秒鐘
*/
}
}
19.責(zé)任鏈模式
public abstract class Approver { // 審批人抽象類
protected String name; // 抽象出審批人的姓名。
protected Approver nextApprover; // 下一個審批人,更高級別領(lǐng)導(dǎo)。
public Approver(String name) {
this.name = name;
}
protected Approver setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
return this.nextApprover; // 返回下個審批人,鏈?zhǔn)骄幊獭? }
public abstract void approve(int amount); // 抽象審批方法由具體審批人子類實(shí)現(xiàn)
}
public class CEO extends Approver {
public CEO(String name) {
super(name);
}
@Override
public void approve(int amount) {
if (amount <= 10000) {
System.out.println("審批通過?!綜EO:" + name + "】");
} else {
System.out.println("駁回申請。【CEO:" + name + "】");
}
}
}
public class Manager extends Approver {
public Manager(String name) {
super(name);
}
@Override
public void approve(int amount) {
if (amount <= 5000) {
System.out.println("審批通過?!窘?jīng)理:" + name + "】");
} else {
System.out.println("無權(quán)審批,升級處理。【經(jīng)理:" + name + "】");
this.nextApprover.approve(amount);
}
}
}
public class Staff extends Approver {
public Staff(String name) {
super(name);
}
@Override
public void approve(int amount) {
if (amount <= 1000) {
System.out.println("審批通過?!締T工:" + name + "】");
} else {
System.out.println("無權(quán)審批,升級處理?!締T工:" + name + "】");
this.nextApprover.approve(amount);
}
}
}
public class Demo {
public static void main(String[] args) {
Approver flightJohn = new Staff("張飛");
flightJohn.setNextApprover(new Manager("關(guān)羽")).setNextApprover(new CEO("劉備"));
// 高層接觸不到也沒必要接觸,直接找員工張飛審批。
flightJohn.approve(1000);
/***********************
* 審批通過?!締T工:張飛】
***********************/
flightJohn.approve(4000);
/***********************
* 無權(quán)審批,升級處理。【員工:張飛】 審批通過。【經(jīng)理:關(guān)羽】
***********************/
flightJohn.approve(9000);
/***********************
* 無權(quán)審批,升級處理?!締T工:張飛】 無權(quán)審批,升級處理?!窘?jīng)理:關(guān)羽】 審批通過。【CEO:劉備】
***********************/
flightJohn.approve(88000);
/***********************
* 無權(quán)審批,升級處理?!締T工:張飛】 無權(quán)審批,升級處理?!窘?jīng)理:關(guān)羽】 駁回申請?!綜EO:劉備】
***********************/
}
}

責(zé)任鏈
20.觀察者模式
public abstract class Buyer {
protected String name;
protected Shop shop;
public Buyer(String name, Shop shop) {
this.name = name;
this.shop = shop;
}
public abstract void inform();
}
public class PhoneFans extends Buyer {
public PhoneFans(String name, Shop shop) {
super(name, shop);// 調(diào)用父類進(jìn)行構(gòu)造
}
@Override
public void inform() {
String product = shop.getProduct();
if (product.contains("水果手機(jī)")) {// 此買家只買水果牌手機(jī)
System.out.print(name);
System.out.println("購買:" + product);
}
}
}
public class HandChopper extends Buyer {
public HandChopper(String name, Shop shop) {
super(name, shop);
}
@Override
public void inform() {
System.out.print(name);
String product = shop.getProduct();
System.out.println("購買:" + product);
}
}
import java.util.ArrayList;
import java.util.List;
public class Shop {
private String product;
private List<Buyer> buyers; // 持有買家的引用
public Shop() {
this.product = "無商品";
this.buyers = new ArrayList<>();
}
// 為了主動通知買家,買家得來店里注冊。
public void register(Buyer buyer) {
this.buyers.add(buyer);
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product; // 到貨了
notifyBuyers(); // 到貨后通知買家
}
// 通知所有注冊買家
public void notifyBuyers() {
buyers.stream().forEach(b -> b.inform());
}
}
public class Demo {
public static void main(String[] args) {
Shop shop = new Shop();
Buyer tanSir = new PhoneFans("果粉唐僧", shop);
Buyer barJeet = new HandChopper("剁手族八戒", shop);
shop.register(tanSir);
shop.register(barJeet);
// 商店到貨
shop.setProduct("豬肉燉粉條");
shop.setProduct("水果手機(jī)【愛瘋叉】");
}
}
其它參考文檔:
23種設(shè)計(jì)模式及案例整理分享
代碼地址