设计模式-读书笔记

server/2024/12/20 19:22:20/

确认好:

模式名称

问题:在何时使用模式,包含设计中存在的问题以及问题存在的原因

解决方案:设计模式的组成部分,以及这些组成部分之间的相互关系,各自的职责和协作方式,用uml类图和核心代码描述

效果:模式优缺点,使用模式时应权衡的问题

创建型:描述如何创建对象。5个

结构型:如何实现类对象的组合。7个

行为型:类和对象怎么交互,以及怎么分配职责。11个

结合是处理类还是对象,如单例模式是对象创建型模式

类之间的关系:

1、关联。单向关联(顾客和地址),双向关联(顾客与产品,相互绑定),自关联(链表节点),多重性关联(界面上有多个按钮)

聚合(生命周期不同,汽车与轮胎),组合(生命周期相同,脸与鼻子)

菱形箭头,指向轮胎,另一边右箭头

2、依赖。驾驶员与汽车。----->指向汽车

3、泛化。继承,父类与子类。菱形箭头,指向父类,另一边无箭头。 在这基础上,改为虚线,就是接口实现,指向接口

面向对象设计原则:

1、单一职责:一个类只负责一个功能领域中的相应职责。

2、开闭原则。实体对扩展开放,对修改关闭。

3、里氏替换原则。所有引用基类对象的地方,能够透明地使用其子类的对象。

4、依赖倒转原则。抽象不应该依赖于细节,而是细节依赖于对象。

换言之,要针对接口编程,而不是针对实现编程。

一个具体类应当实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中加的新方法。

将具体类的对象通过依赖注入(DI)的方式注入到其他对象:构造注入,设值setter注入,接口注入

5、接口隔离原则。使用多个专门的接口,而不使用单一的总接口。

应当为客户端提供尽可能小的单独的几口,客户端不应该依赖那些它不需要的接口。因为实现一个接口就要实现该接口定义的所有方法。

6、合成复用原则。尽量使用对象组合,而不是继承来达到复用目的。

聚合/组合应优于继承,后者破坏了封装性,前者耦合性低。

7、迪米特原则。一个软件实体应当尽可能少地与其他实体发生相互作用。

通过引入一个合理的第三者来降低现有对象之间的耦合度

创建型模式

单例模式 对象创建型模型

问题:windows任务管理器点击多次,只弹出一个页面(!真的) 再比如负载均衡器的唯一性

demo1
private static A a = null; 静态变量
public static A getA(){if(a == null){  但是这里初始化需要一段时间,仍可能创建了多个loadBalancera = new A();}return a;
}

为了解决上面的问题,考虑到单例类的两个实现方式:饿汉式和懒汉式。

饿汉式,定义静态变量,直接初始化,见demo2,资源效率不好,可能初始化用不到该类,并且初始化加载时间长

private static A a = new A(); 静态变量
public static A getA(){return a;
}

懒汉式就是demo1,在demo1的基础上我们引入线程锁定

demo3
private static A a = null; 
public static A getA(){if(a == null){  synchronized(LazySingleton.class){a = new A();}   }return a;
}

仍有问题,假如两个线程同时判定了为空。引入双重检查锁定

demo4
private static A a = null; 
public static A getA(){if(a == null){synchronized(LazySingleton.class)if(a == null){  // 第2重判断a = new A();}}return a;
}

更好的方法 IoDH方法

增加一个静态内部类

demo5
private static Class B(){private final static A a = new A();
}
public static A getA(){return B.a;}

简单工厂模式 集中式 对象创建型 静态工厂

Chart类实现柱状图、饼状图等不同图表的实现

创建和使用不应耦合在一起

工厂类!!

//demo1
class Factory{public static Chart getChart(String type){  //静态工厂实现Chart chart = null;if(type.equalsIgnoreCase("h")){chart = new HChart();}else if 。。。。。。  }
}

工厂方法 多态 对象创建型 解决静态工厂无法引入新产品

工厂 多个具体的

//demo1
interface Logger{public void w();}  //抽象产品
class DLogger implements Logger{public void w(){.....}} //具体产品
interface Factory{public Logger getL();}  //抽象工厂
class DLoggerFactory{public Logger getL(){DLogger d = new DLogger();return d;}
}
//使用
Factory f;
Logger l;
f = new DLoggerFactory();
l = f.getL();
l.w();

可以用读取配置文件来获取类字符串,使用java的反射机制,根据类名字符串生成对象

如创建一个字符串类型的对象,通过类名生成实例对象并将其返回

Class c = Class.forName("String");
Object obj = c.newInstance();
return obj;

创建DOM对象

DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;

用xml文件配置

<?xml version = "1.0">
<config><className>FileLoggerFactory></className>
</cofig>
f = new DLoggerFactory();
//改为
f = (DLoggerFactory)XMLUtil.getBean();

缺点:类成对增加,开销大

抽象工厂模式 产品族 对象创建型 比如界面风格

//抽象工厂
interface Factory{public Button createButton();   //两个抽象产品public TextField createTextField();
}//具体工厂
class SummerFactory{public Button createButton(){return new SummerButton;};  public TextField createTextField(){。。。。。};
}

同样可以用xml配置文件反射得到java具体工厂

缺点:再增加新的抽象产品很麻烦

P86/396 12.4 22:01留

原型模式 对象的克隆 对象创建型

//demo1
class ConcretePrototype implements Prototype{private String attr;  // 成员变量public void setAttr(String attr){this.attr = attr;}public String getAttr(){return this.attr;}// 克隆方法public Prototype clone(){Prototype prototype = new Prototype();prototype.setAttr(this.attr);return prototype}
}

java中所有类都继承Object 类中的clone()方法,而这个方法来自接口Clonable

浅克隆

主要区别是是否支持引用类型(类、接口、数组)的成员变量的复制。当引用类型时,原型对象和克隆对象的成员变量指向相同的内存地址

深克隆 序列化实现:将对象写到流中,写到流中的对象,是原有对象的一个复制品

Serializable接口(两个类均要实现)附件类Attachment 是下面一个类的属性 周报类WeeklyLog(使用序列化实现深克隆)

//demo2
public WeeklyLog deepclone(){//将对象写入流中ByteArrayOutputStream bao = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bao);oos.writeObject(this);//将对象从流中读取ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (WeeklyLog)ois.readObject();
}

建造者模式 复杂对象的组装与创建 对象创建型

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

客户端只需实例化指挥者类,指挥者类针对抽象建造者编程,客户端根据需要传入具体的建造者类型

指挥者将指导具体建造者一步一步地构造一个完整的产品

//产品
class Product{private String partA;private String partB;
}
//抽象建造者类
abstract class Buider{protected Product product = new Product();public abstract void buildPartA();public abstract void buildPartB();//返回产品对象public Product getResult(){return product;}
}
//指挥者
class Director{private Builder builder;public Director(Builder builder){this.builder = builder;}//产品构建与组装方法public Product construct(){builder.buildPartA();builder.buildPartB();//决定次序}
}
//实现
Builder builder = new ConcreteBuilder(); //可通过配置文件实现
Director director = new Director(builder);
Product product = director.construct(); 

工厂方法:集中管理创建类型

关于指挥者:

1、省略Director,直接在具体建造者中construct构建

2、引入钩子方法,返回类型是Boolean,方法名一般是isXXX(),定义在抽象建造者类中,如是否光头 Bareheaded


http://www.ppmy.cn/server/151764.html

相关文章

【HarmonyOS】获取设备自定义名字

【HarmonyOS】获取设备自定义名字 一、问题背景 应用开发中我们经常需要拿到设备名称&#xff0c;非设备的品牌名称。例如&#xff0c;meta 60 Pro这种。而是用户自定义的设备名称。 但是鸿蒙针对用户信息的保护非常严格。想拿到设备名称&#xff0c;通过常规的DeviceInfo接…

uboot 打开log 的 方法

uboot 版本 commit f919c3a889f0ec7d63a48b5d0ed064386b0980bd (HEAD -> v2024.10, tag: v2024.10) Author: Tom Rini <trinikonsulko.com> Date: Mon Oct 7 08:54:35 2024 -0600 Prepare v2024.10 Signed-off-by: Tom Rini <trinikonsulko.com> 开启的选项…

Java爬虫️ 使用Jsoup库进行API请求有什么优势?

在Java的世界里&#xff0c;Jsoup库以其强大的HTML解析能力而闻名。它不仅仅是一个简单的解析器&#xff0c;更是一个功能齐全的工具箱&#xff0c;为开发者提供了从网页抓取到数据处理的一站式解决方案。本文将深入探讨使用Jsoup库进行API请求的优势&#xff0c;并提供代码示例…

零基础学安全--wireshark简介

目录 主要功能 捕获网络数据包 协议解析 数据包分析 数据包重组 过滤功能 统计与图表功能 官网 Wireshark是一个开源的网络协议分析工具 主要功能 捕获网络数据包 能够实时捕获网络中传输的数据包&#xff0c;用户选择要监听的网络接口&#xff08;如以太网、WiFi等…

基于DockerCompose搭建Redis主从哨兵模式

linux目录结构 内网配置 哨兵配置文件如下&#xff0c;创建3个哨兵配置文件 # sentinel26379.conf sentinel26380.conf sentinel26381.conf 内容如下 protected-mode no sentinel monitor mymaster redis-master 6379 2 sentinel down-after-milliseconds mymaster 60000 s…

Redis篇-15--数据结构篇7--Sorted Set内存模型(有序集合,跳跃表skip list,压缩列表ziplist)

1、概述 Redis的Sorted Set是一种有序集合&#xff0c;它不仅存储唯一的元素&#xff0c;还为每个元素关联一个分数&#xff08;score&#xff09;&#xff0c;用于对元素进行排序。为了在保证高效性能的同时节省内存&#xff0c;Redis对Sorted Set 的底层实现进行了多种优化。…

spring实例化对象的几种方式(使用XML配置文件)

前言 Spring框架作为一个轻量级的控制反转&#xff08;IoC&#xff09;容器&#xff0c;为开发者提供了多种对象实例化的策略。通过这些策略&#xff0c;开发者可以更加灵活地控制对象的生命周期和依赖关系。无论是通过XML配置、注解配置还是Java配置&#xff0c;Spring都能…

Swagger自动文档工具以及gin-swagger的使用

什么是 Swagger&#xff1f; Swagger 是一个开源的 API 设计和文档工具&#xff0c;旨在帮助开发者更高效地设计、构建、记录和测试 RESTful API。它基于 OpenAPI 规范&#xff08;前身为 Swagger 规范&#xff09;&#xff0c;通过自动化的方式生成交互式 API 文档、客户端 S…