设计模式
一.简介
1.概念
设计模式是一套被反复使用,多数人知道,经过分类,设计的代码模板。使用设计模式,为了代码的重用性更高,
让代码更容易理解。
2.设计原则
面向对象的基本原则
-
高内聚
模块内部要高度内聚,紧密结合,每一个模块都完成独立的功能
-
低耦合
模块之间依赖性低
手动挡的汽车 刹车 离合 油门 ---- 高耦合
设计模式的六大原则
- 单一职责原则
一个类只负责一个职责 - 开闭原则
对扩展开放,对修改关闭
在程序需要进行扩展的时候,不能去修改原有的代码,实现一个热插拔的效果(需要使用接口和抽象类) - 里氏替换原则
所有引用基类(父类)的地方必须能透明的使用其子类的对象
任何基类出现的地方,都可以换成子类,程序还可以正常执行 - 依赖倒置原则
细节应当依赖于抽象,抽象不应该依赖于细节,也就是“面向接口编程” 或 “面向抽象类编程” - 接口隔离原则
使用多个隔离的接口,而不使用单一的总接口
每个接口应该承担一个相对独立的角色,不干不该干的事 - 迪米特法则,也称为最少知道原则
一个类对自己依赖的类知道的越少越好
3.23种设计模式
分为三大类
- 创建型模式:工厂模式,抽象工厂模式,单例模式,建造者模式,原型模式。
- 结构型模式:适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。
- 行为型模式:策略模式、模板模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
二.单例模式
1.简介
确保某个类只有一个实例,在本类自行实例化,向整个系统提供这个实例
2.实现方法
两种方法
-
饿汉式
在类加载的时候创建实例,不管后面用不用都会创建 ----- 线程安全的
-
懒汉式
在需要的时候才创建,延迟加载 ----- 线程不安全的
代码步骤:
- 构造方法私有化
- 创建本类的一个唯一实例,使用 private static 修饰
- 提供一个用于获取实例的方法, 使用 public static 修饰
三.三层架构
1.简介
三层结构是一种程序设计的结构,使用分成结构将整个程序代码分为三层
- 视图层(View)
- 业务逻辑层(service)
- 数据访问层(dao)
特点: 实现高内聚,低耦合
- 每一层分工明确,任意一层修改都不影响其他层
- 每一层都不应该出现其他层的技术
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xX3rUAWP-1610940122046)(img/三层结构.png)]
2.三层
2.1View
-
用于实现系统与用户的数据交互
接收用户的数据:Scanner 网页 导入文件
向用户展示数据:控制台,网页 导出文件
-
类的命名: XxxView
2.2Service
-
用于实现具体的业务逻辑
-
类和接口的命名: XxxService XxxServiceImpl
-
方法的命名:add remove modify find findAll findById findByName
使用具体的业务名称: register login
2.3 dao
- (Data Access Object) 用于实现对数据的增删改查,数据的持久化操作
- 类和接口的名: XxxDao XxxDaoImpl
- 方法的命名: insert delete update select selectAll …
3.三层结构简单实现
功能: 从集合(数据库)中查询一个学生
步骤:
1.分包开发
view:输入输出
service:逻辑判断 service.impl
dao:数据访问 dao.impl
util:工具包
entity/pojo: 实体类 简单的java对象 (属性 get set 构造 没有赋值逻辑代码)
exception:自定义异常类
dao层与数据库关联
serivce调用dao
view调用service
四.模板模式
1.简介
Template 定义一个抽象类,将部分逻辑以具体的方法实现,然后声明一些抽象的方法,迫使子类实现剩余的部分逻辑代码
不同子类可以实现不同的逻辑
如: 盖房子, 定义一个模板: 有地基, 有窗户,有门,有墙。具体使用什么样的门,交给子类完成
先定义一个逻辑框架,将具体的细节交个子类实现
2.实现方式
五.工厂模式
1.简介
Factory 定义一个工厂类
2.实现
1.配置属性文件
key=value: 自定义名字=完整类名
2.在工厂类 读取属性文件中的数据,放入map集合中 (key值是自定义的名字,value值是通过完整类名获取的一个当前类对象)
3.写一个工厂方法,返回需要的对象 ,通过key获取value值
//map集合用来保存读取的数据
static HashMap<String, Object> map = new HashMap<String, Object>();
//将属性文件中的内容读取到 hashmap中,需要自己 读取后将key和value放到map集合中
static{
try(
//文件文件是放在src写的
InputStream is = ObjectFatory.class.getClassLoader().getResourceAsStream("objs.properties");
BufferedReader r = new BufferedReader( new InputStreamReader(is));
){
String str = null;
while((str=r.readLine())!=null){
String[] arr = str.split("=");
// map中的value应该放的是new的对象
// 通过类名 获取该类的一个对象 Class.forName("完整类名").newInstance
map.put(arr[0], Class.forName(arr[1]).newInstance());
}
}catch (Exception e) {
e.printStackTrace();
}
}
六.代理模式
1.简介
proxy为其他对象提供一种代理,以控制对这个对象的访问,起到中介的作用
被代理的对象 — 目标对象 代替目标对象的对象为— 代理对象
作用:可以扩展目标对象的功能,增加额外的操作,同时不侵入源代码
代理的三要素:
- 目标对象
- 代理对象
- 共同接口
2.实现方法
两种:静态代理 动态代理
2.1静态代理
代理类由程序员自己创建,需要实现与目标对象相同接口
缺点: 如果共同的接口中增加了方法,需要去维护目标类和代理类
步骤
- 定义一个类,实现与目标对象相同接口
- 原有功能不变(逻辑代码不变)-- 调用原来的方法
- 对方法进行增强(扩展)
UserService service = new UserServiceImpl();
@Override
public void login(String name, String password) {
service.login(name, password);//调用原有的代码,保持与原有功能一致
//对方法进行扩展
System.out.println("登录时间:"+new Date());
}
@Override
public String logout() {
//对方法增强
System.out.println("在线时长5个小时");
return service.logout();
}
2.2动态代理
代理类会自动生成---- 通过反射生成的