設(shè)計(jì)模式整理收集(純代碼)

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ì)模式及案例整理分享
代碼地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容