设计模式整理收集(纯代码)

1.单例模式

public class God {
    private volatile static God god;
    private God(){} 
    public static God getInstance() {//庙是开放的不用排队进入
        if (god == null) {//如果头柱香未产生,这批抢香人进入堂内排队。
            synchronized(God.class){
                if (god == null) {//只有头香造了神,其他抢香的白排队了
                    god = new God();
                }
            }
        }
        //此处头柱香产生后不必再排队
        return god;
    }
}

2.适配器模式

public interface TriplePin {
    //参数分别为火线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//既然是两项插头,当然实现两项插标准
    public void electrify(int l, int n) {
        System.out.println("火线通电:" + l);
        System.out.println("零线通电:" + n);
    }
}

3.策略模式

public interface Strategy {                            //算法标准
    public int calculate(int a, int b);                //操作数,被操作数
}
public class Addition implements Strategy{ //实现算法接口
    @Override
    public int calculate(int a, int b) {  //加数与被加数
        return a + b;                            //这里我们做加法运算
    }
}
public class Subtraction implements Strategy{ //实现算法接口
    @Override
    public int calculate(int a, int b) {      //减数与被减数
        return a - b;   //这里我们做减法运算
    }
}
public class Calculator {          //计算器类
   private Strategy strategy;     //拥有某种算法策略
   public void setStrategy(Strategy strategy) {  //接入算法策略
        this.strategy = strategy;
    }
    public int getResult(int a, int b) {
        return this.strategy.calculate(a, b); //返回具体策略的结果
    }
}

4.状态模式

public interface State {
    public void switchOn(Switcher switcher);//开
    public void switchOff(Switcher switcher);//关
}
public class On implements State {
     @Override
     public void switchOn(Switcher switcher) {
         System.out.println("WARN!!!通电状态无需再开");
         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!!!断电状态无需再关");
        return;
    }
}
public class Switcher {
     //开关的初始状态设置为“关”
     private State state = new Off();
     public State getState() {
         return state;
     } 
     public void setState(State state) {
        this.state = state;
    }
    public void switchOn() {
        //这里调用的是当前状态的开方法
        state.switchOn(this);
    }
    public void switchOff(){
        //这里调用的是当前状态的关方法
        state.switchOff(this);
    }
}

5.模板方法模式

 public abstract class PM {
     protected abstract void analyze();  //需求分析
     protected abstract void design();   //设计
     protected abstract void develop(); //开发
     protected abstract boolean test();  //测试
     protected abstract void release();  //发布
     protected final void kickoff(){
        analyze();
        design();
        do {
            develop();
        } while (!test());//如果测试失败,则继续开发改Bug。
        release();
    }
}
public class AutoTestPM extends PM {
    @Override
    protected void analyze() {
        System.out.println("进行业务沟通,需求分析");     
    }
    //design();develop();test();release();实现省略
}

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();
        //谁洗碗呢?一场战场一触即发……
    }
}
public class Facade {
     private VegVendor vv;
     private Chef chef;
     private Waiter waiter;
     private Cleaner cleaner;

     public Facade() {
       this.vv = new VegVendor();
        //开门前就找菜贩子准备好蔬菜
        vv.sell();
        //当然还得雇佣好各类饭店服务人员
        this.chef = new Chef();
        this.waiter = new Waiter();
        this.cleaner = new Cleaner();
    }

    public void provideService(){
        //接待,入座,点菜
        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();// 直接调用不做加任何粉饰。
    }

}
public class FoundationMakeup extends Decorator {

    // 调用化妆品父类注入
    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();
        // 运行结果:涂口红(打粉底(女孩的脸庞))
    }
}

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); // 调用聊天室连接方法
        this.chatRoom = chatRoom; // 注入聊天室引用
    }

    public void talk(String msg) { // 用户发言
        chatRoom.sendMsg(this, msg); // 给聊天室发消息
    }

    public void listen(User fromWhom, String msg) { // 且听风吟
        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);// 用户进入聊天室加入列表。
        System.out.print("欢迎【");
        System.out.print(user.getName());
        System.out.println("】加入聊天室【" + this.name + "】");
    }

    public void sendMsg(User fromWhom, String msg) {
        // 循环所有用户,只发消息给非发送方fromWhom。
        users.stream().filter(user -> !user.equals(fromWhom))// 过滤掉发送方fromWhom
                .forEach(toWhom -> toWhom.listen(fromWhom, msg));// 发送消息给剩下的所有人
    }
}

9.组合模式

public abstract class Node {
    protected String name; // 节点命名

    public Node(String name) { // 构造节点,传入节点名。
        this.name = name;
    }

    // 增加后续子节点方法
    protected abstract void add(Node child);

    protected void ls(int space) {
        for (int i = 0; i < space; i++) {
            System.out.print(" ");// 先循环输出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("不能添加子节点。");
    }

    @Override
    public void ls(int space) {
        super.ls(space);
    }
}
public class Folder extends Node {
    // 文件夹可以包含子节点(文件夹或者文件)。
    private List<Node> childrenNodes = new ArrayList<>();

    public Folder(String name) {
        super(name);                    // 调用父类“节点”的构造方法命名。
    }

    @Override
    protected void add(Node child) {
        childrenNodes.add(child);       // 可以添加子节点。
    }

    @Override
    public void ls(int space) {
        super.ls(space);                        // 调用父类共通的ls方法列出自己的名字。
        space++;                                // 之后列出的子节点前,空格数要增加一个了。
        for (Node node : childrenNodes) {
            node.ls(space);                     // 调用子节点的ls方法。
        }
    }
}

10.迭代器模式

public interface Iterator<E> {
    E next();           //返回下一个元素
    boolean hasNext();  //是否还有下一个元素
}
public class DrivingRecorder {
    private int index = -1; // 当前记录位置
    private String[] records = new String[10]; // 假设只能记录10条视频

    public void append(String record) {
        if (index == 9) { // 循环覆盖
            index = 0;
        } else {
            index++;
        }
        records[index] = record;
    }

    public Iterator<String> iterator() {
        return new Itr();
    }

    private class Itr implements Iterator<String> {
        int cursor = index; // 迭代器游标,不染指原始游标。
        int loopCount = 0;

        @Override
        public boolean hasNext() {
            return loopCount < 10;
        }

        @Override
        public String next() {
            int i = cursor;     // 记录即将返回的游标位置
            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();
        // 假设记录了12条视频
        for (int i = 0; i < 12; i++) {
            dr.append("视频_" + i);
        }
        // 用户要获取交通事故视频,定义事故列表。
        List<String> accidents = new ArrayList<>();
        // 用户拿到迭代器
        Iterator<String> it = dr.iterator();
        while (it.hasNext()) {// 如果还有下一条则继续迭代
            String video = it.next();
            System.out.println(video);
            // 用户翻看视频发现10和8可作为证据。
            if ("视频_10".equals(video) || "视频_8".equals(video)) {
                accidents.add(video);
            }
        }
        // 拿到两个视频集accidents交给交警查看。
        System.out.println("事故证据:" + accidents);
        /*
         * 视频_11 
         * 视频_10 
         * 视频_9 
         * 视频_8 
         * 视频_7 
         * 视频_6 
         * 视频_5 
         * 视频_4 
         * 视频_3 
         * 视频_2 
         * 事故证据:[视频_10, 视频_8]
         */
    }
}

11.备忘录模式

public class Doc {
    private String title;       // 文章名字
    private String body;        // 文章内容

    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);// 创建历史记录
    }

    public void restoreHistory(History history) {
        this.body = history.getBody();// 恢复历史记录
    }
}
public class History {
    private String body; // 用于备忘文章内容

    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;    // 历史记录当前位置

    public Editor(Doc doc) {
        System.out.println("<<<打开文档" + doc.getTitle());
        this.doc = doc;                     // 注入文档
        historyRecords = new ArrayList<>(); // 初始化历史记录
        backup();                           // 保存一份历史记录
        show();                             // 显示内容
    }

    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() {           // 显示当前文本内容
        System.out.println(doc.getBody());
        System.out.println("文章结束>>>\n");
    }

    public void undo() {            // 撤销操作:如按下Ctr+Z,回到过去。
        System.out.println(">>>撤销操作");
        if (historyPosition == 0) {
            return;                 // 到头了,不能再撤销了。
        }
        historyPosition--;          // 历史记录位置回滚一笔
        History history = historyRecords.get(historyPosition);
        doc.restoreHistory(history);// 取出历史记录并恢复至文档
        show();
    }

    // public void redo(); 省略实现代码
}
public class Author {
    public static void main(String[] args) {
        Editor editor = new Editor(new Doc("《AI的觉醒》"));
        /*
         * <<<打开文档《AI的觉醒》
         * 文章结束>>>
         */
        editor.append("第一章 混沌初开");
        /*
         * <<<插入操作 第一章 混沌初开 文章结束>>>
         */
        editor.append("\n 正文2000字……");
        /*
         * <<<插入操作 第一章 混沌初开 正文2000字…… 文章结束>>>
         */
        editor.append("\n 第二章 荒漠之花\n 正文3000字……");
        /*
         * <<<插入操作 第一章 混沌初开 正文2000字…… 第二章 荒漠之花 正文3000字…… 文章结束>>>
         */
        editor.delete();
        /*
         * <<<删除操作
         * 文章结束>>>
         */
        // 吃下后悔药,我的世界又完整了。
        editor.undo();
        /*
         * >>>撤销操作 第一章 混沌初开 正文2000字…… 第二章 荒漠之花 正文3000字…… 文章结束>>>
         */
    }
}

12.代理模式

public interface Internet { // 互联网访问接口
    public void access(String url);
}
public interface Intranet {  // 局域网访问接口
    public void fileAccess(String path);
}
public class Modem implements Internet {// 调制解调器
    @Override
    public void access(String url) {// 实现互联网访问接口
        System.out.println("正在访问:" + url);
    }
}
public class Switch implements Intranet {
    @Override
    public void fileAccess(String path) {
        System.out.println("访问内网:" + 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("电影", "游戏", "音乐", "小说");

    // 被代理的真实对象,猫、交换机、或是别的什么都是。
    private Object origin;

    public KeywordFilter(Object origin) {
        this.origin = origin;// 注入被代理对象
        System.out.println("开启关键字过滤模式...");
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 要被切入方法面之前的业务逻辑
        String arg = args[0].toString();
        for (String keyword : blackList) {
            if (arg.toString().contains(keyword)) {
                System.out.println("禁止访问:" + arg);
                return null;
            }
        }
        // 调用真实的被代理对象方法
        return method.invoke(origin, arg);
    }

}
import java.util.Arrays;
import java.util.List;

public class RouterProxy implements Internet { // 路由器代理类,互联网访问接口

    private Internet modem; // 持有被代理类引用
    private List<String> blackList = Arrays.asList("电影", "游戏", "音乐", "小说");

    public RouterProxy() {
        this.modem = new Modem(); // 实例化被代理类
        System.out.println("拨号上网...连接成功!");
    }

    @Override
    public void access(String url) {      // 同样实现互联网访问接口方法
        for (String keyword : blackList) {// 循环黑名单
            if (url.contains(keyword)) {  // 是否包含黑名单字眼
                System.out.println("禁止访问:" + url);
                return;
            }
        }
        modem.access(url); // 正常访问互联网
    }
}
import java.lang.reflect.Proxy;

public class Demo {
        public static void main(String[] args) {
            // 访问外网(互联网), 生成猫代理。
            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.学习.com");
            internet.access("http://www.工作.com");

            // 访问内网(局域网), 生成交换机代理。
            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学习资料.zip");
            intranet.fileAccess("\\\\192.68.1.6\\Java知音\\设计模式是什么鬼.doc");
   
           /*
               开启关键字过滤模式...
               禁止访问:http://www.电影.com
               禁止访问:http://www.游戏.com
               正在访问:http://www.学习.com
               正在访问:http://www.工作.com
               开启关键字过滤模式...
               禁止访问:\\192.68.1.2\共享\电影\IronHuman.mp4
               禁止访问:\\192.68.1.2\共享\游戏\Hero.exe
               访问内网:\\192.68.1.4\shared\Java学习资料.zip
               访问内网:\\192.68.1.6\Java知音\设计模式是什么鬼.doc
   
           */
       }
}

13.工厂方法模式

public abstract class Enemy {
    // 敌人的坐标,会被子类继承。
    protected int x;
    protected int y;

    // 初始化坐标
    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);// 调用父类构造子初始化坐标
    }

    @Override
    public void show() {
        System.out.println("飞机出现坐标:" + x + "," + y);
        System.out.println("飞机向玩家发起攻击……");
    }

}
public class Tank extends Enemy {

    public Tank(int x, int y) {
        super(x, y);
    }

    @Override
    public void show() {
        System.out.println("坦克出现坐标:" + x + "," + y);
        System.out.println("坦克向玩家发起攻击……");
    }

}
public class Boss extends Enemy {

    public Boss(int x, int y) {
        super(x, y);
    }

    @Override
    public void show() {
        System.out.println("Boss出现坐标:" + x + "," + y);
        System.out.println("Boss向玩家发起攻击……");
    }

}
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);   // 实例化飞机
        } else {
            enemy = new Tank(random.nextInt(screenWidth), 0);       // 实例化坦克
        }
        return enemy;
    }
}
public class BossFactory implements Factory {

    @Override
    public Enemy create(int screenWidth) {
        // boss应该出现在屏幕中央
        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("抵达关底");
        factory = new BossFactory();
        factory.create(screenWidth).show();
        /*
          游戏开始
          飞机出现坐标:27,0
          飞机向玩家发起攻击……
          坦克出现坐标:40,0
          坦克向玩家发起攻击……
          飞机出现坐标:30,0
          飞机向玩家发起攻击……
          坦克出现坐标:53,0
          坦克向玩家发起攻击……
          坦克出现坐标:19,0
          坦克向玩家发起攻击……
          飞机出现坐标:18,0
          飞机向玩家发起攻击……
          坦克出现坐标:27,0
          坦克向玩家发起攻击……
          飞机出现坐标:89,0
          飞机向玩家发起攻击……
          飞机出现坐标:24,0
          飞机向玩家发起攻击……
          飞机出现坐标:31,0
          飞机向玩家发起攻击……
          抵达关底
          Boss出现坐标:50,0
          Boss向玩家发起攻击……
        */
          }
      }

14.桥接模式

public interface Ruler {// 尺子
    // 规则化笔触走向
    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[]) {
        // 白色画笔对应的所有形状
        new WhitePen(new CircleRuler()).draw();
        new WhitePen(new SquareRuler()).draw();
        new WhitePen(new TriangleRuler()).draw();
        // 黑色画笔对应的所有形状
        new BlackPen(new CircleRuler()).draw();
        new BlackPen(new SquareRuler()).draw();
        new BlackPen(new TriangleRuler()).draw();
        /*运行结果:
        白○
        白□
        白△
        黑○
        黑□
        黑△
        */
    }
}

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("深挖地基,修建地下车库,部署管道、线缆、风道。");
        apartment.setBasement("╚═════════╝\n");
    }

    @Override
    public void buildWall() {
        System.out.println("搭建多层建筑框架,建造电梯井,钢筋混凝土浇灌。");
        for (int i = 0; i < 8; i++) {// 此处假设固定8层
            apartment.setWall("║ □ □ □ □ ║\n");
        }
    }

    @Override
    public void buildRoof() {
        System.out.println("封顶,部署通风井,做防水层,保温层。");
        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("搭建木质框架,石膏板封墙并粉饰内外墙。");
        house.setWall("|田|田 田|\n");
    }

    @Override
    public void buildRoof() {
        System.out.println("建造木质屋顶、阁楼,安装烟囱,做好防水。");
        house.setRoof("╱◥███◣\n");
    }

    @Override
    public Building getBuilding() {
        return house;
    }
}
public class Director {// 工程总监

    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public void setBuilder(Builder builder) {
        this.builder = builder;
    }

    public Building direct() {
        System.out.println("=====工程项目启动=====");
        // 第一步,打好地基;
        builder.buildBasement();
        // 第二步,建造框架、墙体;
        builder.buildWall();
        // 第三步,封顶;
        builder.buildRoof();
        System.out.println("=====工程项目竣工=====");
        return builder.getBuilding();
    }
}
public class Demo {
    public static void main(String[] args) {
        // 招工,建别墅。
        Builder builder = new HouseBuilder();
        
       // 交给工程总监
        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("收音机启动");
    }

    @Override
    public void off() {
        System.out.println("收音机关闭");
    }

    @Override
    public void channelUp() {
        System.out.println("收音机调频+");
    }

    @Override
    public void channelDown() {
        System.out.println("收音机调频-");
    }

    @Override
    public void volumeUp() {
        System.out.println("收音机音量+");
    }

    @Override
    public void volumeDown() {
        System.out.println("收音机音量-");
    }
}

public class TV implements Device {

    @Override
    public void on() {
        System.out.println("电视机启动");
    }

    @Override
    public void off() {
        System.out.println("电视机关闭");
    }

    @Override
    public void channelUp() {
        System.out.println("电视机频道+");
    }

    @Override
    public void channelDown() {
        System.out.println("电视机频道-");
    }

    @Override
    public void volumeUp() {
        System.out.println("电视机音量+");
    }

    @Override
    public void volumeDown() {
        System.out.println("电视机音量-");
    }
}
public interface Command {
    // 执行命令操作
    public void exe();
    // 反执行命令操作
    public void unexe();
}
public class SwitchCommand implements Command {

    private Device device;// 此处持有高级设备接口。

    public SwitchCommand(Device device) {
        this.device = device;
    }

    @Override
    public void exe() {
        device.on();// 执行命令调用开机操作
    }

    @Override
    public void unexe() {
        device.off();// 反执行命令调用关机操作
    }

}

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();
        
                //绑定【电视机】的【命令】到【控制器按键】
               controller.bindOKCommand(new SwitchCommand(tv));
               controller.bindVerticalCommand(new ChannelCommand(tv));//上下调台
               controller.bindHorizontalCommand(new VolumeCommand(tv));//左右调音
       
               controller.buttonOKHold();
               controller.buttonUpClick();
               controller.buttonUpClick();
               controller.buttonDownClick();
               controller.buttonRightClick();
       
               /*打印输出:
                   ===客户端用【可编程式遥控器】操作电器===
                   长按OK按键……电视机启动
                   单击↑按键……电视机频道+
                   单击↑按键……电视机频道+
                   单击↓按键……电视机频道-
                   单击→按键……电视机音量+
               */
               //绑定【收音机】的【命令】到【控制器按键】
               controller.bindOKCommand(new SwitchCommand(radio));
               controller.bindVerticalCommand(new VolumeCommand(radio));    //上下调音
               controller.bindHorizontalCommand(new ChannelCommand(radio)); //左右调台
               controller.buttonOKHold();
               controller.buttonUpClick();
               controller.buttonUpClick();
               controller.buttonRightClick();
               controller.buttonDownClick();
               /*打印输出:
                   长按OK按键……收音机启动
                   单击↑按键……收音机音量+
                   单击↑按键……收音机音量+
                   单击→按键……收音机调频+
                   单击↓按键……收音机音量-
               */
    }
}

17.访问者模式

import java.time.LocalDate;
public abstract class Product {
    protected String name;           // 品名
    protected LocalDate producedDate;// 生产日期
    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("结算日期:" + 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("猫泰白酒", 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));
        // 迭代购物车轮流结算
        for (Acceptable product : products) {
            product.accept(discountVisitor);
        }
        /*
         * 打印输出: 结算日期:2019-01-01 =====糖果【小黑兔奶糖】打折后价格===== ¥18.00 =====酒品【猫泰白酒】无折扣价格=====
         * ¥1,000.00 =====水果【草莓】打折后价格===== ¥12.50
         */
    }
}

18.解释器模式

public interface Expression {  // 表达式接口
    public void interpret();   // 解释方法
}
public class Delay implements Expression {

    private int seconds;// 延时秒数

    public Delay(int seconds) {
        this.seconds = seconds;
    }

    public int getSeconds() {
        return seconds;
    }

    public void interpret() {
        System.out.println("系统延迟:" + 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("按下鼠标:左键");
    }

}
public class LeftUp implements Expression {

    public void interpret() {
        System.out.println("松开鼠标:左键");
    }

}
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 {
    // 鼠标位置坐标
    private int x, y;

    public Move(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void interpret() {
        System.out.println("移动鼠标:【" + x + "," + y + "】");
    }

}
public class Repetition implements Expression {

    private int loopCount;        // 循环次数
    private Expression expression;// 循环体表达式

    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() {
        // 循环挨个解析每条指令
        expressions.forEach(exp -> exp.interpret());
    }

}
import java.util.Arrays;
public class Demo {
    public static void main(String[] args) {
                /*
                 * BEGIN             // 脚本开始
                 * MOVE 500,600;     // 鼠标移动到坐标(500, 600)
                 *  BEGIN LOOP 5     // 开始循环5次
                 *      LEFT_CLICK;  // 循环体内单击左键
                 *      DELAY 1;     // 每次延时1秒
                 *  END;             // 循环体结束
                * RIGHT_DOWN;       // 按下右键
                * DELAY 7200;       // 延时2小时
                * END;              // 脚本结束
                */
                 // 构造指令集语义树,实际情况会交给语法解析器(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();
                 /*打印输出
                   移动鼠标:【500,600】
                   按下鼠标:左键
                   松开鼠标:左键
                   系统延迟:1秒钟
                   按下鼠标:左键
                   松开鼠标:左键
                   系统延迟:1秒钟
                   按下鼠标:左键
                   松开鼠标:左键
                   系统延迟:1秒钟
                   按下鼠标:左键
                   松开鼠标:左键
                   系统延迟:1秒钟
                   按下鼠标:左键
                   松开鼠标:左键
                   系统延迟:1秒钟
                   按下鼠标:右键
                   系统延迟:7200秒钟
                */
           }
}

19.责任链模式

public abstract class Approver {              // 审批人抽象类

    protected String name;                    // 抽象出审批人的姓名。
    protected Approver nextApprover;          // 下一个审批人,更高级别领导。

    public Approver(String name) {
        this.name = name;
    }

    protected Approver setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
        return this.nextApprover;              // 返回下个审批人,链式编程。
    }

    public abstract void approve(int amount);  // 抽象审批方法由具体审批人子类实现
}
public class CEO extends Approver {

    public CEO(String name) {
        super(name);
    }

    @Override
    public void approve(int amount) {
        if (amount <= 10000) {
            System.out.println("审批通过。【CEO:" + 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("审批通过。【经理:" + name + "】");
        } else {
            System.out.println("无权审批,升级处理。【经理:" + 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("审批通过。【员工:" + name + "】");
        } else {
            System.out.println("无权审批,升级处理。【员工:" + name + "】");
            this.nextApprover.approve(amount);
        }
    }
}
public class Demo {
    public static void main(String[] args) {
        Approver flightJohn = new Staff("张飞");
        flightJohn.setNextApprover(new Manager("关羽")).setNextApprover(new CEO("刘备"));

        // 高层接触不到也没必要接触,直接找员工张飞审批。
        flightJohn.approve(1000);
        /***********************
         * 审批通过。【员工:张飞】
         ***********************/
        flightJohn.approve(4000);
        /***********************
         * 无权审批,升级处理。【员工:张飞】 审批通过。【经理:关羽】
         ***********************/

        flightJohn.approve(9000);
        /***********************
         * 无权审批,升级处理。【员工:张飞】 无权审批,升级处理。【经理:关羽】 审批通过。【CEO:刘备】
         ***********************/

        flightJohn.approve(88000);
        /***********************
         * 无权审批,升级处理。【员工:张飞】 无权审批,升级处理。【经理:关羽】 驳回申请。【CEO:刘备】
         ***********************/
    }
}
责任链

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);// 调用父类进行构造
    }

    @Override
    public void inform() {
        String product = shop.getProduct();
        if (product.contains("水果手机")) {// 此买家只买水果牌手机
            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("水果手机【爱疯叉】");
    }
}

其它参考文档:
23种设计模式及案例整理分享
代码地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容