java知音--设计模式系列阅读笔记

182 阅读6分钟

笔记参考公众号:java知音

总结的编码之道

  1. 单一职责原则(高内聚,低耦合)
  2. 接口隔离原则(最小接口原则)
  3. 依赖倒置
  4. 里氏替换(父类出现的地方子类就能替换,可以检验设计是否合理)
  5. (迪米特原则:调用方只需了解最少的知识)最小知识原则
  6. 开闭原则

特点:分开容易组合 高层的泛化是底层多态的保证
面向对象 对现实的模拟 封装 继承 多态

设计模式

  1. 原型模式
    类必须实现cloneable接口。重写Object的clone方法。如果要实现深拷贝,即类中有其他引用类型的成员变量, 其他类也要实现相应接口。重写对象方法!在clone中调用其他clone 优势:直接复制内存中的数据流。不需要类加载,实例化、初始化。节约了内存和cpu

  2. 单例模式
    构造器私有 唯一实例 private static final eager load 在类中第一行直接new 优先 lazy load 注意并发问题 在方法体内加多线程并发控制

  3. 适配器模式
    不同对象直接通过接口互动,适配器解决配置兼容性问题 eg:Triplepin =new Adapter(new DoublePinImp()); 适配器实现了三插接口,在三插接口重写方法中调用二插接口的实现方法。实现了二插接口的实现类使用三插接口 构造器能接受任意二插接口实现类

    b:类适配器 。适配器直接继承TV类和实现三插接口 。 只适用于TV类了 优势:避免了修改原始类或者接口,符合开闭原则;

  4. 策略模式 一个策略接口。不同算法策略实现类。 在一个执行类中注入不同实现类。 优势:组装

  5. 状态模式 抽离状态 多个状态类实现同一个状态接口 ,抽象方法的参数是宿主类对象 宿主类(当前状态,更改状态的方法) 状态类中可以切换给宿主类对象到其他状态,this.state.switchON/OFF(this) shwitcher.setState(new 状态类)

  6. 装饰模式 对目标类的逻辑增强 实现相同的接口,实现方法中装饰类对传入目标类对象增强。构造器接受同一接口的实现类(目标类)。 应用举例:IO流处理的嵌套

  7. 门面模式
    对多个目标类再做一层封装,对调用方暴露一个对外接口

  8. 模板方法模式 抽象类 final固定的不可修改方法,对流程固定 do(develop()) while(tesy())

  9. 代理模式 对目标类加以控制

  • a:静态代理 :代理类和目标类实现同一接口 在代理内构造函数直接初始化目标类作为成员变量
  • b:动态代理 (不需要专门针对某个接口去写这么一个代理类,而是根据接口动态生成) : 将控制逻辑单独处理(实现invocationHander接口的逻辑bean invoke方法,构造器参数注入目标类对象) 在具体调用处 //访问内网(局域网),生成交换机代理。
15        Intranet intranet = (Intranet) Proxy.newProxyInstance(
16                Switch.class.getClassLoader(),
17                Switch.class.getInterfaces(), 
18                new KeywordFilter(new Switch()));  

兼容了不同的接口,把处理逻辑解耦。

应用举例:AOP Spring的面向切面AOP,我们只需要定义好一个切面类@Aspect,声明其切入点@Pointcut(被代理的哪些对象的哪些方法,也就是这里的猫和交换机的access以及accessFile),以及被切入的代码块(要增加上去的逻辑,比如这里的过滤功能代码,可分为前置执行@Before,后置执行@After,以及异常处理@AfterThrowing等),于是框架自动帮我们生成代理并切入目标执行。 更经典的事务控制的例子,在所有业务代码之前先切入“事务开始”,执行过后再切入“事务提交”,如果抛异常被捕获则执行“事务回滚”,

  1. 中介模式 对象之间显式的互相引用很多,需要一个中介类解耦

以聊天室举例:其他类持有中介类对象的引用,进行登录(加入到某个聊天室,加入到集合列表中),发送消息(调用聊天室方法:其他用户都接收到消息)。 登录和发送都要调用中介类对象的方法。接收方法在聊天室发送方法调用 应用:eureka server

  1. 组合模式 整体与部分的结构是类似的 数学上的分形概念

举例:文件系统 node(文件名,抽象方法添加节点,抽象方法列举ls,重载无参实例方法ls(){this.ls(0)}) file folder(有添加节点的功能,ls递归列出所有文件名)

  1. 迭代器模式 内部实现类实现了iterator接口。外部能遍历并获取数据(不直接将数据公开,不安全)迭代器私有

  2. 备忘录模式 用一个列表记录不同的版本 eg:记事本的编辑,撤销,撤销 通过集合存储不同版本的数据

  3. 责任链模型 在类中持有上一级对象的引用。结构相似。

  4. 享元模式 利用缓存(map)共享对象,节约内存(相比原型模式),加快速度(不用重复加载资源)

抛弃了利用new关键字肆意妄为地制造对象,而是改用这个图件工厂去帮我们把元构建并共享起来

  1. 桥接模式 在抽象类中植入接口 笛卡尔集

  2. 工厂方法模式 简单工厂:一个类中方法根据传入字符返回匹配bean。将创建过程封装。 工厂模式:工厂类抽象。横向划分。 泛化

  3. 抽象工厂模式: 纵向划分 泛化 多个抽象方法

  4. 建造者模式 将工序和工艺分开 以工艺的多态来实现复杂对象的构建过程 同样的构造工序可以展现出不同的产品对象 eg:同一个类实例化成不同的角色

举例:stringbuilder

  1. 命令模式 在策略模式的基础将命令抽出来,实现解耦,自由组合。

  2. 访问者模式 访问者实现了多个重载方法(业务逻辑需要),在接待者接口中实现一个方法,调用访问者,传入本身。 解决功能泛化导致的编译问题

// 三件商品加入购物车
 4        List<Acceptable> products = Arrays.asList(
 5            new Candy("小黑兔奶糖", LocalDate.of(2018, 10, 1), 20.00f),
 6            new Wine("猫泰白酒", LocalDate.of(2017, 1, 1), 1000.00f),
 7            new Fruit("草莓", LocalDate.of(2018, 12, 26), 10.00f, 2.5f)
 8        );
 9
10        Visitor discountVisitor = new DiscountVisitor(LocalDate.of(2019, 1, 1));
11        // 迭代购物车轮流结算
12        for (Acceptable product : products) {
13            product.accept(discountVisitor);
14        }

泛化导致参数重载方法不能识别。

  1. 解释器模式 interpret 与组合模式相比,更强调行为的相似性。 实现同一接口,不同的成员变量,不同的行为逻辑,组合在一起形成整体

  2. 观察者模式

类似于中介者模式。商家(聊天室)一接受到到货通知买家【观察者】(其他用户)

public void setProduct(String product) {
21        this.product = product;// 到货了
22        notifyBuyers();// 到货后通知买家
23    }