23种设计模式

  • 前言
    • 开闭原则
    • 隔离接口
    • 迪米特
    • 依赖倒置
    • 单一
    • 里式替换
  • 创建模式 (
    • 单例
      • 懒汉式
      • 饿汉式
    • 原型
      • 浅克隆
      • 深克隆
    • 建造者
    • 工厂
      • 简单工厂(Log)可以参考一下 LoggerFactory(SLF4J)
      • 抽象工厂
  • 结构模型
    • 适配器
    • 代理
      • 静态代理/装饰者
      • 动态代理
        • JDK动态代理
        • cgilb动态代理
    • 桥接
    • 外观模式
    • 组合模式
    • 享元模式
  • 行为模式
    • 模板模式
    • 策略模式
    • 状态模式
    • 中介者模式
    • 观察者模式
    • 访问者模式
    • 责任链模式

前言

脑图分享 脑图
理解设计模式对今后写业务和学习框架源代码有很大的作用,但是设计模式又非常的抽象和晦涩难懂 所以一般在第一次学习的时候可以有一个初步的印象大概知道是干什么的 然后 有哪些组成即,然后再工作一段时间后再回头过来学习 就会发现有新的理解 (回锅肉很好吃 哈哈),这些由前人总结出来的各种模式也都是遵循着设计模式的 7个准则 开闭原则 隔离接口 迪米特 依赖倒置 单一 里式替换 等 这个都是想让你的 更加健壮 就是在尽量不修改源代码的基础上增加功能 也就是所谓的 对修改关闭对扩展开放 而写java 的时候总是告诉你要面向接口开发也就是这个 原因 先抽象也就是先定义规则 然后再 按照规则 开发

开闭原则

意思:对修改关闭对扩展开放 。白话的意思是 比如你写了一个 功能模块但是突然在原来的基础上要加新的功能 一般像我 刚开始 开发的时候 都是在源代码上进行修改并进行测试,但是这样会带来一个问题就是目前的功能模块 已经是开发过的 并且经过 测试中心测试通过的 已经在线上运行的如果 在现在的功能里面进行修改那么 以前测试 通过的功能 又要 测试中心重新测试防止误操作产生新的bug 但是 测试中心的老师一般也不会情缘 因为这个工作会让他做重复性的工作 所这个时候 你需要在 将原功能 不动 的情况下 在新写一个新增的功能 然后 将他们 组合起来 这样 测试老师只需要测试你新的的功能就可以了 如果你的功能模块还没有上线 并且还在开发并且 业务逻辑也不复杂 那么就按照自己习惯简单易读 最好,如果你想练手可以 慢慢培养这种思维可以在自己的新业务代码种运用进去。

隔离接口

意思 : 不引用 用不到的接口这个 最好操作 平时我们也不会 去引用一个 什么都不干的接口。

迪米特

意思:最少知道原则 这个意思是不同功能的模块要分开 而不是耦合(耦合的意思就是手机数据线放到了裤兜里面拿出来的样子)在一个类中去写 。如果放到一个类中写 会出现一个问题就是 不管哪个功能变更 你都要去修改整个代码 因为你们写在了一起 只要修改就会创造bug 所以这么做的目的也是 让我们 尽可能少的变动代码

依赖倒置

意思: 比如 需要 将一个引用类型当做一个 参数传入 那么 就不要去放这个类 实现 类也就是子类 放入这个引用接口 为什么 呢 因为这么 做你可以很灵活的 去传参 只要是实现了这个接口 都可以当做这个参数 这样 就增加了 方法的健壮型 而不是 每次换一个类就得重写这个方法 传入 这也是面向接口的好处

单一

意思 就是一个类只干一个事情 ,比如你创建了一个 工具类 那么这类中 只放 平时大家一起用的工具 而不是将杂乱方法在里面 这样做一个是维护起来 省心 还有就是 自己在写业务的时候 也能减少重复造轮子。

里式替换

意思: 如果 你是一个子类 去继承了一个父类 去扩展 父类的方法 同时不要去重写的父类原有的方法 这就和上面说的开闭 说的就能联系上了 我们 扩展的目的不是去修改 原有的父类方法而是在其基础上去增强 所以 这个法则存

虽然说设计模式能解决 很多实际的问题 但是无形中也带来一定的困难 有些时候 会很不方便 如果业务不复杂还是以 易读为准吧 如果练手那就别出问题就行

(在使用设计模式的是有首先要有抽象层 这个很重要 也就是要有interface)

创建模式 (

会发现 这个些 都是帮你创建一个对象 也就是帮助你去new 一个类 只是功能侧重点不同 但是 同一的创建把他们规整到一个模式)

单例

(单例我就不说了 也不难理解 网上一大堆资料 也不抽象 )

懒汉式

饿汉式

原型

(JDK 原生支持 只要去实现 clone 接口就行)

浅克隆

(只复制本类)

深克隆

(如果说本类中参数中还有其他引用 Person类里面多了一个 User类 这个时候使用 深克隆 )

建造者

(如果你方法需要传入的参数过多 可以考虑这种方式 平时 我们 看后缀带xxxbuilder 方式 基本都是建造者模式 这个 理解起来也不费劲 就是一个传参 的过程 网上很多代码 平时的时候也可自己用在代码里面)
1.首先要抽象出来一个 建造者里面规定你要创建 的方法 也就是 你后续用到的参数 我这里抽象一个 手机builder

package Buider;public abstract class AbstracBuiderPhone {Phone phone;abstract AbstracBuiderPhone customCpu(String cpu);abstract AbstracBuiderPhone customMouse(String Mouse);
}

2.需要建造者 创建的物品手机

package Buider;class Phone {protected String name;protected String cpu;protected String Mouse;public String getName() {return name;}public String getCpu() {return cpu;}public String getMouse() {return Mouse;}@Overridepublic String toString() {return "Phone{"+ "name='"+ name+ '\''+ ", cpu='"+ cpu+ '\''+ ", Mouse='"+ Mouse+ '\''+ '}';}
}

3 实现一个建造者接口 就是你要创造出一个什么样的手机(比如小米手机)

package Buider;public class xiaomBuider extends AbstracBuiderPhone {/**** */public xiaomBuider() {phone = new Phone();}@OverrideAbstracBuiderPhone customCpu(String cpu) {phone.cpu = cpu;return this;}@OverrideAbstracBuiderPhone customMouse(String Mouse) {phone.Mouse = Mouse;return this;}Phone getPhone() {return phone;}
}

4 测试

package Buider;public class ttes {public static void main(String[] args) {//xiaomBuider x = new xiaomBuider();x.customCpu("i7 11000k").customMouse("xiaomni");Phone phone = x.getPhone();System.out.println(phone);}
}

使用这个是链式建造模式 使用这个方式 有什么好处呢 。显而易见就是 代码看着规整和方便 而不是在你创建对象new 一个类的时候里面需要传入 十几个参数 每次还都要去查看 哪个位置需要什么类型 这个就很方便 就是直接不停的点 方法名就会去 提示添加参数。在传入的参数超过5 个以上 可以 尝试使用一下

工厂

(我这里只说两个 方法 工厂方法可以尝试就用在现在 的业务代码中也许 已经在用了 只不过以前不知道 比如 创建的CommUtil 类 里面的静态方法 都是普通工具 类包,工厂类 可以将我们同一类型的类同一进行创建 并且是 在其内部创建好的 这么做有什么好处呢 比如 我们现在的业务代码种 存在很多方法 但是由于接手 或者历史遗留问题 代码 重复轮子不少 其实 可以将他们同一 归档 同一在一个工厂内部创建 这样 就像 咋杂乱无章的 贮存房间里面 放置了很多 架子 只需要将他们 按照不同类别规整 然后贴上标签 谁需要直接按照标签去找 而不是自己乱翻找)

简单工厂(Log)可以参考一下 LoggerFactory(SLF4J)

抽象工厂

将我们的工厂实体抽象 出去变成一个接口 这样的好处是工厂就可以扩展了 比如 就好像 将厂子变成了公司集团 有很多业务 之后可以 还用 抽象 的工厂去继承 集团总厂 这样就可以在名字上进行区分每个功能厂子比如造汽车 或者造手机 然后 可以在创建一个 抽象类 去实现这个 工厂接口 然后 对自己不要的 方法在抽象方法里面做一下处理 在真正的实体工厂类里面就可以不去重写 这个 抽象类工厂我们不需要的方法了 ,工厂创建完成了 这个时候需要 原材料组装 才能 生产 物品 ,所以将我们工厂要 生产的物品抽象(定义他是一个什么东西 比如phone) 实体类去实现这个物品抽象 接口 比如 我 是 华为手机 物品 有了但是华为不生产手机怎么办 他需要找代工 所以他们联系 实体工厂 吧自己 的设计好的产品送过过 这个时候 代工的工厂开始 工作在里面为我们 生产 一个个手机 (这里生产手机的时候 方法返回的是 手机实体还是抽象的手机呢?)
代码就不粘贴了 放一个图

图可能 不太符合规定当时 主要思想 能看明白就 结构模式

结构模型

适配器

适配器模式 把别人的功能拿过来增强自己的功能 比如 包装字符流 InputStreamReader 这里就是 将字节流 可以用字符流的方式读取 其中 private final StreamDecoder sd; 这个 就是 适配器方法。
大概的意思什么 呢 ;比如你要跟老外交流可以 英语水平只有2级 那么 你就偷偷买了 一个实时翻译的机器 放到兜里面 然后带上耳机 当老外跟你说话的时候 你通过 翻译器 翻译 听懂了 他说什么 然后 你说话通过翻译 器同时他有知道你在说什么 这样 你们 就可以 无障碍的交流而 代理/装饰者 与他本质的区别 就是你发现 老外是个美女 但是欧美人喜欢肌肉强壮的男人 怎么办你只能增强你自己 所以 在你 见美女之前 你要去健身房先去锻炼一身腱子肉 然后你再去 跟美女深入交流 发现了 吧 适配器 就如其名 要将两个功能 通过第三方 交流起来 而 代理/装饰者 而是增强你自身的类的功能。
1 抽象翻译器

package adapter;public interface Machine {void palys();
}

2 实体类英文翻译器

package adapter;public class Simultaneous implements Machine {private final Translator JpmMoviePlayerAdapter = new Zh_EnglishTranslator();private final YourSelf machine;public Simultaneous(YourSelf machine) {this.machine = machine;}@Overridepublic void palys() {String paly = machine.paly();String s = JpmMoviePlayerAdapter.TranslatorEnglish(paly);System.out.println(s);}
}

3 你本体

package adapter;class YourSelf {public String paly() {System.out.println("相遇 。。。。");System.out.println("你说。。。。");return "你好";}
}

4 翻译器功能抽象

package adapter;public interface Translator {String TranslatorEnglish(String str);
}

5 翻译器实体功能

package adapter;public class Zh_EnglishTranslator implements Translator {@Overridepublic String TranslatorEnglish(String str) {if ("你好".equals(str)) {return "hello";}return "";}
}

6 使用

package adapter;public class Simultaneous implements Machine {private final Translator JpmMoviePlayerAdapter = new Zh_EnglishTranslator();private final YourSelf machine;public Simultaneous(YourSelf machine) {this.machine = machine;}@Overridepublic void palys() {String paly = machine.paly();String s = JpmMoviePlayerAdapter.TranslatorEnglish(paly);System.out.println(s);}
}

7 测试

package adapter;import proxy.dynamic.JdkProxy;public class MainTest {public static void main(String[] args) {YourSelf yourSelf = new YourSelf();Machine ch = new Simultaneous(yourSelf);ch.palys();//}
}

8 结果

9 但是 你不甘心 你想发生点什么 你知道 欧美女人喜欢强壮的 但是你没有肌肉 你又不能 回炉重造 所以你 需要 增强 你自己 咋办 去健身房 增强你自己

代理

静态代理/装饰者

动态代理

JDK动态代理

10 增强自己的方式就在健身房

package proxy.dynamic;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class JdkProxy<T> implements InvocationHandler {private final T tagert;public JdkProxy(T t) {tagert = t;}public T getProxy() {Object o =Proxy.newProxyInstance(tagert.getClass().getClassLoader(),tagert.getClass().getInterfaces(),new JdkProxy<>(tagert));return (T) o;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("锻炼身体");Object invoke = method.invoke(tagert, args);System.out.println("同意深入交流");return invoke;}
}

11 增强完成

package adapter;import proxy.dynamic.JdkProxy;public class MainTest {public static void main(String[] args) {YourSelf yourSelf = new YourSelf();Machine ch = new Simultaneous(yourSelf);JdkProxy<Machine> jdkProxy = new JdkProxy(ch);Machine proxy = jdkProxy.getProxy();proxy.palys();//}
}

12 结果

13 身体被掏空 被抛弃 完~~~ 撒花

动态代理 静态代理还有装饰者主要的目的是强化本体 而 适配器主要是 将两个功能适配 一个对一个类 一个是对两个类 静态代理和装饰者 就是一个意思要不然 学的都蒙圈 就当成 正方形也是长方形 就是因为 特使 这么理解 把

cgilb动态代理

有时间可以自己区看下 因为jdk 代理必须要有有接口 如果你本类没有接口是代理不了的 所有 cglib 可以 再底层 人家帮你去 集成了你本类 在 你原来 类方法不动 的情况下增强你自己

桥接

意思 有点像 一整体你在思想上给他分开成不同的模块 然后 在 桥接点进行耦合 ,接口隔离 单一 很像 你这儿 功能里面有很多维度(维度 就是变化量 比如 时间维度 距离维度 )如果 你将这些多维度东西放到一起 最后实现起来耦合性很强 有些时候是牵一发而动全身 或者 相互关联 代码 重复度高 。 所以要站在一定的高度对业务的理解上 把他们抽象出去 然后再一 一 实现然后再 特定的地点 进行组合模式的耦合


好比上面的图 1 所有的功能模块都柔和一个类中 而图二 则是抽象出来需要哪个关联哪个 但是这个 东西再 创建功能之前 就需要构思号要不然容易 修改代码

1 抽象手机维度 可以

package bridge;
/** 耦合点  也就是桥节点* */
public abstract class AbstrcatPhone {String phoneName;/**获得手机属性** */abstract String getPhone();
}

2 实体手机 (创建对象可以练习用工厂的方式 创建 作为练习 怎么写都不为过)

package bridge;public class Huawei extends AbstrcatPhone {@OverrideString getPhone() {super.phoneName = "huawei";return phoneName;}
}

3 抽象 销售渠道

package bridge;
/** 桥接在此** */
public abstract class AbstractSale {String pirce;String Sale;public AbstractSale(String pirce, String sale) {this.pirce = pirce;Sale = sale;}
}

4 实体 销售渠道 线下

package bridge;public class Offline extends AbstractSale {public Offline(String pirce, String sale) {super(pirce, sale);}
}

5 线上

package bridge;public class Online extends AbstractSale {public Online(String pirce, String sale) {super(pirce, sale);}
}

6 抽象 耦合点

package bridge;public abstract class BridgePoint {AbstrcatPhone phone;AbstractSale sale;public BridgePoint(AbstrcatPhone phone, AbstractSale sale) {this.phone = phone;this.sale = sale;}String getPhone() {return phone.phoneName + sale.pirce + sale.Sale;}
}

7 实体耦合点

package bridge;public class newPoint extends BridgePoint {public newPoint(AbstrcatPhone phone, AbstractSale sale) {super(phone, sale);}
}

8 调用

package bridge;public class MaintExst {public static void main(String[] args) {//AbstrcatPhone phone = new Huawei();phone.phoneName = "huawei";AbstractSale sale = new Offline("线下", "123");AbstractSale saleO = new Online("线上", "321");BridgePoint b = new newPoint(phone, saleO);String phone1 = b.getPhone();System.out.println(phone1);}
}

每个功能之间相互不影响 需要就用不需要就不用 迪米特 隔离接口 基本特征分功能 引入你只要的

外观模式

组合模式

享元模式

连接池 应用他跟 原型模式区别 一个是个返回的本类 一个返回的 克隆类 克隆不是本类。主要 核心是抽象出来的 共享的元素 然后 非共享的元素可以放到实现类中取 然后 让简单工厂 取加工 返回 一个这个 元素的一个集合 。好比 一个 公司相当于 工厂类 ,需求经理过来 要找 程序员 开发新的功能 那么在这个公司内部的程序员 就是 属于一个 池化 一波人 如果 项目经理想开发这个功能就需要找一个程序员但是首先要判断 一下 他所找的 程序员是否有任务 如果 有 那么 就得 换一个 如果 都在摸鱼那么 就得反馈给公司工厂 在找一个 。

1 抽象公共 点

package flyweigth;public class AbstractFlyWeigth {Boolean isCanNotWork = true;String language;public void setCanNotWork(Boolean canNotWork) {isCanNotWork = canNotWork;}void Worke() {}public String getLanguage() {return language;}public void setLanguage(String language) {this.language = language;}
}

2 实体类 除了公共 还有不同点

package flyweigth;public class Dogs extends AbstractFlyWeigth {String name;public Dogs(String language, String name) {this.language = language;this.name = name;}public Dogs() {}@Overridepublic String toString() {return "Dogs{" + "language='" + language + '\'' + ", isCanNotWork=" + isCanNotWork + '}';}@Overridevoid Worke() {super.Worke();}
}

3 创造 简单工厂去创造 出来对象

package flyweigth;import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;public class _996Factory {public static Map<String, AbstractFlyWeigth> map = new HashMap<>();/** 目前 仅存存活的 员工* */static {Dogs dogsJava = new Dogs("java", "liergou");Dogs dogsJava1 = new Dogs("java", "zhangmeili");map.put("liergou", dogsJava);map.put("zhangmeili", dogsJava1);}public static void add(String tyep, String name) {Dogs dogsJava = new Dogs(tyep, name);map.put(tyep + name, dogsJava);}public static AbstractFlyWeigth get(@Nullable String type, String name) {/** 获取你想要的 员工* */AbstractFlyWeigth abstractFlyWeigth = map.get(name);if (abstractFlyWeigth != null) {if (abstractFlyWeigth.getLanguage().equals(type)) {return abstractFlyWeigth;}} /** 没有的话随机给你一个* */ else {for (AbstractFlyWeigth value : map.values()) {if (value.isCanNotWork) {value.setCanNotWork(false);System.out.println("ok");return value;} else {System.out.println("working .....");System.out.println("推荐下一个");}}}/** 都没有的话需要提加人了* */return null;}
}
4 测试 ```java
package flyweigth;public class MainTest {public static void main(String[] args) {////      需求1 要一个 javaAbstractFlyWeigth abstractFlyWeigth = _996Factory.get("", "java");System.out.println(abstractFlyWeigth);/*需求二也要一个java*/AbstractFlyWeigth abstractFlyWeigth1 = _996Factory.get("", "java");System.out.println(abstractFlyWeigth1);}
}

5 享元模式 + 策略 模式可以 使我们在判断 if if if 分别进入分支的时候有很好的支持 我们每次 获取 享元创建出来的池对象 然后分别执行我们业务代码 这样可以 将我们 if else 业务分离 并且 扩展 也不会 需要修改源代码。 就此 结构模式 完结

行为模式

模板模式

将在抽象类父类里面 实现 一些公共的方法 只是将 一些 需要 子类 实现的 功能去自定义实现
换句话说 就像 把大象放冰箱 总共分三步
抽象类 父类 实现 第一步和第二步 第三步 暴露一个 方法出去需要子类去 重写 覆盖 并完成 关键的 第四步
第一步 把冰箱门打开
第二部 把大象装冰箱 如何去装 自己 解决 。

第三步 把冰箱门关上

package template;public abstract class PutEle {public PutEle() {first();second();Three();}void first() {System.out.println("打开冰箱**");}void second() {}void Three() {System.out.println("冰箱门关闭");}
}
package template;public class PutIn extends PutEle {@Overridevoid second() {System.out.println("肢解。。。。。");}
}
package template;public class MainTest {public static void main(String[] args) {PutEle p = new PutIn();System.out.println(p);//}
}
打开冰箱**
肢解。。。。。
冰箱门关闭
template.PutIn@5a2e4553

策略模式

就是实现一个接口 的公共方法 无限的实现 都是相同的 类型 然后依赖倒置 在 组合模式到 一个 Context 方法中 set一个 策略接口。
与状态模式不同 因为不管谁来做 都得 第一 第二第三步都是重复且确定的行为

状态模式

1 你早中晚的状态

package state;public abstract class AbstracState {public abstract void paly();public abstract AbstracState next();
}

2 下午状态

package state;public class YourAfter extends AbstracState {@Overridepublic void paly() {System.out.println("困睡觉 状态不行 。。。。");}@Overridepublic AbstracState next() {return new YourNight();}
}

3 早上状态

package state;public class YourMorning extends AbstracState {@Overridepublic void paly() {System.out.println("早起状态不好 3 秒");}@Overridepublic AbstracState next() {return new YourAfter();}
}

4 晚上状态

package state;public class YourNight extends AbstracState {@Overridepublic void paly() {System.out.println("逃避 。。。。");}@Overridepublic AbstracState next() {return new YourMorning();}
}

5 测试】

package state;public class MainText {public static void main(String[] args) {//System.out.println("媳妇来了。。。。");AbstracState abstracState = new YourMorning();abstracState.paly();System.out.println("媳妇来了。。。。");abstracState = abstracState.next();abstracState.paly();System.out.println("媳妇来了。。。。");abstracState = abstracState.next();abstracState.paly();}
}
媳妇来了。。。。
早起状态不好 3 秒
媳妇来了。。。。
困睡觉 状态不行 。。。。
媳妇来了。。。。
逃避 。。。。

中介者模式

将 原来 网状 模式 转化 为星状模式
状态模式和策略模式很像 但是策略模式 是你本身想用哪个 就用哪个策略没有 流转 也就是规定好的 顺序 但是状态模式又 内部的规定 就是哪一步下一个执行的 是什么 都是定好的 流程框架 用一般来说这样会不乱。

不管 同事做什么事情 都要先请示一下领导 同意才能做 如果没有领导 的话每个人做事的时候都要先 去问问所有的同事 做过没有 标记下 然后在做 这样很混乱

1。 抽象领导 主要是 保存一个开关 就是 是否同意的锁 然后还有保存 这些同事 所要做的事情 是否 可以的业务方法

package mediator;public abstract class Wcleader {boolean flag = true;abstract void setFlag(AbastractWorker state);
}

2 具体领导 这里我把领导 单例 了 要不然 会出现 所有事物都会同意的事情 因为领导只有一个 如果 没有单例的话 会出现咨询不同领导 一件事情都同意 的 尴尬

package mediator;
/** 饿汉式单例 因为只能有一个领导** */
public class LeaderZhou extends Wcleader {private static final LeaderZhou leaderZhou = new LeaderZhou();private LeaderZhou() {}public static LeaderZhou getLeaderZhou() {return leaderZhou;}@Overridevoid setFlag(AbastractWorker state) {if ("leader".equals(state.state) && flag) {System.out.println("可以请假。。。。");flag = false;}else {System.out.println("不可以请假。。。。");}}
}

3 抽象同事 这里主要保存着个 状态 就是 他要做的事情 和 要做事情的具体步骤方法

package mediator;public abstract class AbastractWorker {String state;public abstract void getleave();
}

4 同事Li

package mediator;public class LiWorker extends AbastractWorker {public LiWorker(String state) {this.state = state;}@Overridepublic void getleave() {System.out.println("我想请假");}
}

5 同事Wang

package mediator;public class WangWorker extends AbastractWorker {public WangWorker(String state) {this.state = state;}@Overridepublic void getleave() {System.out.println("我想请假 。。。。");}
}

6 测试 同时去领导请假 但是 工作很忙 只会同意一个

package mediator;public class MainTest {public static void main(String[] args) {//LeaderZhou leaderZhou = LeaderZhou.getLeaderZhou();LiWorker liWorker = new LiWorker("leader");liWorker.getleave();leaderZhou.setFlag(liWorker);WangWorker wangWorker = new WangWorker("leader");wangWorker.getleave();leaderZhou.setFlag(wangWorker);}
}

7

我想请假
可以请假。。。。
我想请假 。。。。
不可以请假。。。。

观察者模式

这个 通俗一点说就是一个相互关联的组件 只要有一个变动就通知 所有 组件 核心是将左右 组件 放到 观察者的内部的一个list 中 每次变动的时候都去foreach 这个 list挨个通知 同样如果 双向观察也是 发现 就会变动
单相观察者就是 观察者有一个 接收 被观察着的方法 被观察者收集着 观察者的信息 一旦 变动 就是方法背调用 那么就遍历观察者列表 去 发送通知
我这里有一个 双向观察者的例子 单相 就一个 一个 发送 一个接收 双向 是两个发送两个接收

1 。抽象警察

package obsever;public interface Police {void addthief(Thief thief);/** 发送通知  观察者的关键* */void arrest(String msg);/** 接收通知* */void accpet(String msg);
}

2 实例化警察

package obsever;import java.util.ArrayList;
import java.util.List;public class WangPolicy implements Police {// 添加 小偷的信息也就是观察者private final List<Thief> ThiefList = new ArrayList<>();
//添加方法 @Overridepublic void addthief(Thief thief) {ThiefList.add(thief);}/** 无间道 小偷卧底  发送给小偷信息* */@Overridepublic void arrest(String msg) {for (Thief thief : ThiefList) {//System.out.println("卧底A");thief.accpet(msg);}}
//接收小偷信息@Overridepublic void accpet(String msg) {System.out.println(msg + "通知 卧底A");}
}

3 抽象小偷

package obsever;public interface Thief {void addPolice(Police police);/** 发送通知* */void flee(String msg);/** 接收通知* */void accpet(String msg);
}

4 实例化小偷 和警察一样

package obsever;import java.util.ArrayList;
import java.util.List;public class WangPolicy implements Police {//添加联系警察的信息private final List<Thief> ThiefList = new ArrayList<>();
/真正的添加方法@Overridepublic void addthief(Thief thief) {ThiefList.add(thief);}/** 无间道 发送给警察信息* */@Overridepublic void arrest(String msg) {for (Thief thief : ThiefList) {//System.out.println("卧底A");thief.accpet(msg);}}
// 接收警察信息@Overridepublic void accpet(String msg) {System.out.println(msg + "通知 卧底A");}
}

5 测试

package obsever;public class MainTest {public static void main(String[] args) {//Police police = new WangPolicy();Thief thief = new LiThief();police.addthief(thief);thief.addPolice(police);police.arrest("有内鬼活动终止");thief.flee("收到");}
}
卧底A
卧底 A有内鬼活动终止
收到我已暴露

访问者模式

访问者模式 抽象元素 实体元素 抽象访问者 实体访问者 还有对象构造
不用修改源代码 就能 改变 最主要的 因素是 只在 对象构造中 将 实体访问者 和 实体元素 耦合 通过组合的模式 把 实体元素 引入到 访问者内部 通过访问者的方法去修改 其 内部的属性 当 执行 耦合方法后 就会替换原来的 内容

核心 就是 要在第三方 也就是你这个 一堆元素组成的整体对象构造 内部 去修改
1 。抽象元素

package visitor;
/** 抽象元素* */
public abstract class AbastrictElement {/** 指令* */String Commands;/** 工作* */public AbastrictElement(String Commands) {this.Commands = Commands;}abstract void work();
}

2 实体CPU

package visitor;public class Cpu extends AbastrictElement {public Cpu(String Commands) {super(Commands);}@Overridevoid work() {System.out.println("Cpu 指令执行" + Commands);}
}

3 实体硬盘

package visitor;public class Disk extends AbastrictElement {public Disk(String Commands) {super(Commands);}@Overridevoid work() {System.out.println("磁盘落盘 " + Commands);}
}

4 抽象访问者

package visitor;public abstract class AbastrictVisitor {abstract void cpuUpDate(AbastrictElement abastrictElement);abstract void diskUpDate(AbastrictElement abastrictElement);
}

5 实体访问者

package visitor;public class Up extends AbastrictVisitor {@Overridevoid cpuUpDate(AbastrictElement abastrictElement) {abastrictElement.Commands = "aaa";}@Overridevoid diskUpDate(AbastrictElement abastrictElement) {abastrictElement.Commands = "bbb";}
}

6 构造对象 就是组合成你的 物品

package visitor;public class Pc {Cpu cpu = new Cpu("哒哒哒开机");Disk disk = new Disk("轰隆 粗存");public Pc() {}void getWork() {cpu.work();Qdisk.work();}void updatePc(AbastrictVisitor visitor) {visitor.diskUpDate(disk);visitor.cpuUpDate(cpu);}
}

7 测试

package visitor;public class MainTest {public static void main(String[] args) {Pc computer = new Pc();System.out.println("没有升级========");computer.getWork();AbastrictVisitor abastrictVisitor = new Up();System.out.println("升级后========");computer.updatePc(abastrictVisitor);computer.getWork();}
}
没有升级========
Cpu 指令执行哒哒哒开机
磁盘落盘 轰隆 粗存
升级后========
Cpu 指令执行aaa
磁盘落盘 bbb

主要的 思想是 通过第三方去修改 赋值而不是 在本类中

责任链模式

调用 警察的 arrest 方法其实内部是走的 小偷 相反依然。走小偷 的 flee 方法其实通知警察

ps : 菜鸟一个 有什么 理解不对的地方希望 大家指正 虚心学习 我这个也是学习中的一些 心得 目前还在学习中 一起努力

23种设计模式(白话篇章 )相关推荐

  1. Java开发中的23种设计模式详解(转)

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  2. 23 种设计模式实战 pdf(很全)

    今天分享一份学习资料:23 种设计模式实战教程.pdf,助你快速上手设计模式,写出各种高端代码,文末附下载地址. 设计模式一般分为三大类: 实战教程: 教程共 96 页PDF,太全了!纯粉丝福利,非广 ...

  3. 从追MM谈23种设计模式

    从追MM谈Java的23种设计模式 1.FACTORY-追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说&quo ...

  4. 【设计模式】Java 23种设计模式对比总结

    一.设计模式的分类 创建型模式,共五种(1-5):工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种(6-12):适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组 ...

  5. java 的23种设计模式 单例模式

    23种设计模式友情链接: 点击打开链接 单例模式: A.饿汉式单例模式 具体步骤: 1.声明一个私有的静态的最终的本类类型的对象并实例化 private static final Person ins ...

  6. 23种设计模式C++实现UML+源码汇总

    设计模式-汇总 代码开源仓库地址 23种设计模式C++实现 C++中的开闭原则使用C++多态功能实现附源码 C++基于多态实现依赖颠倒原则附源码 C++ 的静态成员变量为什么一定要在类外定义 23种设 ...

  7. 23种设计模式C++源码与UML实现--外观模式

    外观模式 facade模式也叫外观模式,是由GoF提出的23种设计模式中的一种,facade模式为一组具有类似功能的类群,比如类库,子系统等等,提供一个一致的简单界面.这个一致的简单的界面被称为fac ...

  8. 23种设计模式C++源码与UML实现--建造者模式

    建造者模式 代码仓库地址:建造者模式 Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23种设计模式中的一种.Builder模式是一种对象创建模式之一,用来隐藏复合对象的创建过程.他把 ...

  9. 【java】java开发中的23种设计模式详解

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

最新文章

  1. 快速搭建第一个Mybatis程序
  2. jquery radio取值,checkbox取值,select取值,radio选中,checkbox选中,select选中
  3. Atheros无线网卡芯片全介绍
  4. 华为FusionCloud 云计算解决方案及相关资料下载
  5. (转) Unity3D 使用Texturepacker打包工具制作NGUI(Atlas)图集
  6. java 并发编程第七章:取消和关闭
  7. 算法高级(10)-如何实现浏览器的前进、后退功能
  8. linux 路由添加
  9. Python 读取MODIS叶绿素-a浓度.nc文件
  10. maven配置tomcat版本
  11. 单片机定时器TMOD与TCON详解!
  12. Mac下解压.bin文件
  13. 后台传给小程序的时间对象如何转为“YYYY/MM/DD“格式渲染
  14. 使用Clonezilla复制硬盘
  15. 谷歌浏览器如何给长网页截图?
  16. 长度最小的子数组(力扣209)
  17. python爬虫完整代码下载页
  18. [小程序模板] 化妆品商城小程序模板 商城APP模板 化妆品商城小程序前端源码+免费分享
  19. 安卓系统管理软件_BlackBerry为部署车载安卓系统保驾护航
  20. 2021年起重机司机(限桥式起重机)考试题及起重机司机(限桥式起重机)考试试卷

热门文章

  1. RedisTemplate与jedis
  2. 应届毕业生找Python工作遇到的难题,刚毕业没有工作经验该怎么办?
  3. 干货!毫米波雷达超强解读
  4. 数据库第四单元mooc题
  5. RPA流程自动化有什么优点?如何使用RPA机器人自动化养号?​
  6. 软件需求分析——需求的理论基础
  7. 2021年焊工(技师)考试试卷及焊工(技师)多少钱
  8. 如何切换笔记本键盘的功能键?
  9. 【转】七大查找算法总结
  10. macOS Monterey(版本12.6.3)使用iTunes