结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。
由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。
结构型模式分为以下 7 种:
-
代理模式
-
适配器模式
-
装饰者模式
-
桥接模式
-
外观模式
-
组合模式
-
享元模式
===============================================================================
- 问题:在JavaEE分层开发开发中,那个层次对于我们来讲最重要?
DAO —> Service --> Controller
JavaEE分层开发中,最为重要的是Service层
1、定义业务层接口
public interface EmpService {
/**
-
分页
-
@return 当前页的员工
*/
public List selectEmpByPage(int pageNumber);
/**
-
总的页数
-
@return 数据库有多少条员工数据
*/
public int selectTotalPage();
/**
-
添加员工
-
@param emp
*/
public void addEmp(Emp emp);
/**
-
根据id删除员工
-
@param id
*/
public void dropEmp(Integer id);
/**
-
根据id修改员工信息
-
@param emp
*/
public void update(Emp emp);
/**
-
批量删除员工
-
@param ids
*/
public void plDeleteEmp(List ids);
/**
-
更具id查询员工,用于数据回显
-
@param id
-
@return
*/
public Emp queryEmp(Integer id);
}
2、实现业务接口
public class EmpServiceImpl implements EmpService {
@Override
public List selectEmpByPage(int pageNumber) {
EmpDao mapper = (EmpDao) MybatisUtil.getMapper(EmpDao.class);
//设置每页展示的页数
int rows = 3;
//设置第几页开始的起始条数
int begin = (pageNumber - 1) * rows;
List emps = mapper.selectEmpByPage(begin, rows);
MybatisUtil.close();
return emps;
}
@Override
public int selectTotalPage() {
EmpDao mapper = (EmpDao) MybatisUtil.getMapper(EmpDao.class);
int i = mapper.selectTotalCount();
int rows = 3;
int page = 0;
if (i % rows == 0) {
page = i / rows;
} else {
page = i / rows + 1;
}
MybatisUtil.close();
return page;
}
@Override
public void addEmp(Emp emp) {
EmpDao mapper = (EmpDao) MybatisUtil.getMapper(EmpDao.class);
mapper.insertEmp(emp);
MybatisUtil.commit();
}
@Override
public void dropEmp(Integer id) {
EmpDao mapper = (EmpDao) MybatisUtil.getMapper(EmpDao.class);
mapper.deleteEmp(id);
MybatisUtil.commit();
}
@Override
public void update(Emp emp) {
EmpDao mapper = (EmpDao) MybatisUtil.getMapper(EmpDao.class);
mapper.update(emp);
MybatisUtil.commit();
}
@Override
public void plDeleteEmp(List ids) {
EmpDao mapper = (EmpDao) MybatisUtil.getMapper(EmpDao.class);
mapper.plDeleteEmp(ids);
MybatisUtil.commit();
}
@Override
public Emp queryEmp(Integer id) {
EmpDao mapper = (EmpDao) MybatisUtil.getMapper(EmpDao.class);
Emp emp = mapper.queryEmp(id);
MybatisUtil.close();
return emp;
}
}
3、Service层中包含了哪些代码?
Service层中 = 核心功能(几十行 上百代码) + 额外功能(附加功能)
- 核心功能
业务运算
DAO调用
-
额外功能
-
不属于业务
-
可有可无
-
代码量很小
事务、日志、性能…
从下图中可以看出,现有业务层中
控制事务代码出现了大量的冗余
,如何解决现有业务层出现的冗余问题?
4、额外功能书写在Service层中好不好?
Service层的调用者的角度(Controller):需要在Service层书写额外功能。
软件设计者:Service层不需要额外功能
5、现实生活中的解决方式
-
住酒店不一定需要亲自到酒店去,还可以通过微信支付下的同程艺龙来订酒店。
-
我们可以通过中介去找房子,不用直接跟房东沟通(现实生活中,我们更希望直接跟房东沟通)
-
春运买票买不到,我们可以找黄牛替我们抢票
-
想访问国外的网站,可以使用代理服务器进行访问。
===========================================================================
单词 proxy [ˈprɑːksi] 代理
1、概述
由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
Java中的代理按照代理类生成时机不同 又分为静态代理和动态代理。
-
"静态代理"代理类在编译期就生成
-
"动态代理"代理类则是在Java运行时动态生成。动态代理又有JDK代理和CGLib代理两种。
2、结构
代理(Proxy)模式分为三种角色:
-
抽象主题(Subject)类: 通过接口或抽象类 声明真实主题和代理对象实现的业务方法。
-
真实主题(Real Subject)类: 实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
-
代理(Proxy)类 : 提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
1、什么是代理? 中介
代理是java中的一种设计模式:代理设计模式
2、为什么需要代理?
有没有代理都可以完成当前的功能,但是存在代理之后,更加专注于核心的业务功能,额外功能可以交给代理去做,实现功能的解耦合
- 生活案例:小红正在做饭,但是男朋友小李给他发消息,他如果边做饭边发消息,影响做饭的效率,他就可以口述给她的闺蜜让她闺蜜和男朋友聊天,自己认真做饭,闺蜜就是代理,"如花"就是一个接口
3、代理的好处?
保证核心功能完成的前提下,同时兼顾额外功能
4、怎么开发代理对象?
1、代理对象一定依赖于核心业务对象
2、代理对象和核心业务对象一定要实现相同的接口
=========================================================================
1、什么是静态代理
-
静态代理:手工为某个类开发一个代理类,一个类对应一个代理类
-
通过代理类,为原始类(目标)增加额外的功能
-
好处:利于原始类(目标)的维护
2、名词解释
- 目标类 原始类 被代理的对象
指的是 业务类 (核心功能 --> 业务运算 DAO调用)
- 目标方法,原始方法
目标类(原始类)中的方法 就是目标方法(原始方法)
- 额外功能 (附加功能)
日志,事务,性能,数据清洗
3、代理开发的核心要素
代理类 = 目标类(原始类) + 额外功能 + 原始类(目标类)实现相同的接口
房东 —> public interface UserService{
m1
m2
}
UserServiceImpl implements UserService{
m1 —> 业务运算 DAO调用
m2
}
UserServiceProxy implements UserService
m1
m2
4、编码(静态代理的开发)
开发代理的原则: 代理类和目标类功能一致且实现相同的接口,同时代理类中依赖于目标类对象
(1)UserService接口
public interface UserService {
void save(String name);
void delete(String id);
void update();
String findAll(String name);
String findOne(String id);
}
(2)开发静态代理类
/**
-
@author 王恒杰
-
@version 1.0
-
@date 2021/11/11 11:14
-
@email 1078993387@qq.com
-
@Address 天津
-
@Description:开发原则:代理类和目标类实现相同接口,依赖于真正的目标类
*/
public class UserServiceStaticProxy implements UserService{
/**
- 真正的目标类 (target 原始业务逻辑对象)
*/
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
public void save(String name) {
try {
System.out.println(“开启事务”);
userService.save(name);
System.out.println(“提交事务”);
}catch (Exception e){
System.out.println(“回滚事务”);
e.printStackTrace();
}
}
@Override
public void delete(String id) {
try {
System.out.println(“开启事务”);
userService.delete(id);
System.out.println(“提交事务”);
}catch (Exception e){
System.out.println(“回滚事务”);
e.printStackTrace();
}
}
@Override
public void update() {
try {
System.out.println(“开启事务”);
userService.update();
System.out.println(“提交事务”);
}catch (Exception e){
System.out.println(“回滚事务”);
e.printStackTrace();
}
}
@Override
public String findAll(String name) {
String all=null;
try {
System.out.println(“开启事务”);
all = userService.findAll(name);
System.out.println(“提交事务”);
}catch (Exception e){
System.out.println(“回滚事务”);
e.printStackTrace();
}
return all;
}
@Override
public String findOne(String id) {
String one=null;
try {
System.out.println(“开启事务”);
one= userService.findOne(id);
System.out.println(“提交事务”);
}catch (Exception e){
System.out.println(“回滚事务”);
e.printStackTrace();
}
return one;
}
}
(3)修改目标实现类
public class UserServiceImpl implements UserService {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
面试结束复盘查漏补缺
每次面试都是检验自己知识与技术实力的一次机会,面试结束后建议大家及时总结复盘,查漏补缺,然后有针对性地进行学习,既能提高下一场面试的成功概率,还能增加自己的技术知识栈储备,可谓是一举两得。
以下最新总结的阿里P6资深Java必考题范围和答案,包含最全MySQL、Redis、Java并发编程等等面试题和答案,用于参考~
重要的事说三遍,关注+关注+关注!
更多笔记分享
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
系化!**
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-W9AZJK0x-1712192233107)]
面试结束复盘查漏补缺
每次面试都是检验自己知识与技术实力的一次机会,面试结束后建议大家及时总结复盘,查漏补缺,然后有针对性地进行学习,既能提高下一场面试的成功概率,还能增加自己的技术知识栈储备,可谓是一举两得。
以下最新总结的阿里P6资深Java必考题范围和答案,包含最全MySQL、Redis、Java并发编程等等面试题和答案,用于参考~
重要的事说三遍,关注+关注+关注!
[外链图片转存中…(img-hUX2r3jO-1712192233108)]
[外链图片转存中…(img-lzNXYWOC-1712192233108)]
更多笔记分享
[外链图片转存中…(img-T5wPE65w-1712192233109)]
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算