Java设计模式总结(四)

本文深入讲解了备忘录模式、状态模式、访问者模式、中介者模式和解释器模式,探讨了它们在软件设计中的应用,包括如何实现对象状态的备份与恢复、根据不同状态调整行为、为现有类动态添加新功能、降低类间耦合度以及开发编译器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章参考自:https://blog.youkuaiyun.com/zhangerqing/article/details/8245537

其实每个设计模式都是很重要的一种思想,看上去很熟,其实是因为我们在学到的东西中都有涉及,尽管有时我们并不知道,其实在Java本身的设计之中处处都有体现,像AWT、JDBC、集合类、IO管道或者是Web框架,里面设计模式无处不在。因为我们篇幅有限,很难讲每一个设计模式都讲的很详细,不过我会尽我所能,尽量在有限的空间和篇幅内,把意思写清楚了,更好让大家明白。本章不出意外的话,应该是设计模式最后一讲了,首先还是上一下上篇开头的那个图:

本章讲讲第三类和第四类。

19、备忘录模式(Memento)

主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象,个人觉得叫备份模式更形象些,通俗的讲下:假设有原始类A,A中有各种属性,A可以决定需要备份的属性,备忘录类B是用来存储A的一些内部状态,类C呢,就是一个用来存储备忘录的,且只能存储,不能修改等操作。做个图来分析一下:

Original类是原始类,里面有需要保存的属性value及创建一个备忘录类,用来保存value值。Memento类是备忘录类,Storage类是存储备忘录的类,持有Memento类的实例,该模式很好理解。直接看源码:


 
  1. public class Original {
  2. private String value;
  3. public String getValue() {
  4. return value;
  5. }
  6. public void setValue(String value) {
  7. this.value = value;
  8. }
  9. public Original(String value) {
  10. this.value = value;
  11. }
  12. public Memento createMemento(){
  13. return new Memento(value);
  14. }
  15. public void restoreMemento(Memento memento){
  16. this.value = memento.getValue();
  17. }
  18. }

 
  1. public class Memento {
  2. private String value;
  3. public Memento(String value) {
  4. this.value = value;
  5. }
  6. public String getValue() {
  7. return value;
  8. }
  9. public void setValue(String value) {
  10. this.value = value;
  11. }
  12. }

 
  1. public class Storage {
  2. private Memento memento;
  3. public Storage(Memento memento) {
  4. this.memento = memento;
  5. }
  6. public Memento getMemento() {
  7. return memento;
  8. }
  9. public void setMemento(Memento memento) {
  10. this.memento = memento;
  11. }
  12. }

测试类:


 
  1. public class Test {
  2. public static void main(String[] args) {
  3. // 创建原始类
  4. Original origi = new Original( "egg");
  5. // 创建备忘录
  6. Storage storage = new Storage(origi.createMemento());
  7. // 修改原始类的状态
  8. System.out.println( "初始化状态为:" + origi.getValue());
  9. origi.setValue( "niu");
  10. System.out.println( "修改后的状态为:" + origi.getValue());
  11. // 回复原始类的状态
  12. origi.restoreMemento(storage.getMemento());
  13. System.out.println( "恢复后的状态为:" + origi.getValue());
  14. }
  15. }

输出:

初始化状态为:egg
修改后的状态为:niu
恢复后的状态为:egg

简单描述下:新建原始类时,value被初始化为egg,后经过修改,将value的值置为niu,最后倒数第二行进行恢复状态,结果成功恢复了。其实我觉得这个模式叫“备份-恢复”模式最形象。

20、状态模式(State)

核心思想就是:当对象的状态改变时,同时改变其行为,很好理解!就拿QQ来说,有几种状态,在线、隐身、忙碌等,每个状态对应不同的操作,而且你的好友也能看到你的状态,所以,状态模式就两点:1、可以通过改变状态来获得不同的行为。2、你的好友能同时看到你的变化。看图:


State类是个状态类,Context类可以实现切换,我们来看看代码:


 
  1. package com.xtfggef.dp.state;
  2. /
  3. * 状态类的核心类
  4. * 2012-12-1
  5. * @author erqing
  6. /
  7. public class State {
  8. private String value;
  9. public String getValue() {
  10. return value;
  11. }
  12. public void setValue(String value) {
  13. this.value = value;
  14. }
  15. public void method1(){
  16. System.out.println( "execute the first opt!");
  17. }
  18. public void method2(){
  19. System.out.println( "execute the second opt!");
  20. }
  21. }

 
  1. package com.xtfggef.dp.state;
  2. /
  3. * 状态模式的切换类 2012-12-1
  4. * @author erqing
  5. *
  6. */
  7. public class Context {
  8. private State state;
  9. public Context(State state) {
  10. this.state = state;
  11. }
  12. public State getState() {
  13. return state;
  14. }
  15. public void setState(State state) {
  16. this.state = state;
  17. }
  18. public void method() {
  19. if (state.getValue().equals( "state1")) {
  20. state.method1();
  21. } else if (state.getValue().equals( "state2")) {
  22. state.method2();
  23. }
  24. }
  25. }
测试类:


 
  1. public class Test {
  2. public static void main(String[] args) {
  3. State state = new State();
  4. Context context = new Context(state);
  5. //设置第一种状态
  6. state.setValue( "state1");
  7. context.method();
  8. //设置第二种状态
  9. state.setValue( "state2");
  10. context.method();
  11. }
  12. }
输出:

execute the first opt!
execute the second opt!

根据这个特性,状态模式在日常开发中用的挺多的,尤其是做网站的时候,我们有时希望根据对象的某一属性,区别开他们的一些功能,比如说简单的权限控制等。
21、访问者模式(Visitor)

访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。访问者模式适用于数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增加新的数据结构很困难。—— From 百科

简单来说,访问者模式就是一种分离对象数据结构与行为的方法,通过这种分离,可达到为一个被访问者动态添加新的操作而无需做其它的修改的效果。简单关系图:


来看看原码:一个Visitor类,存放要访问的对象,


 
  1. public interface Visitor {
  2. public void visit(Subject sub);
  3. }

 
  1. public class MyVisitor implements Visitor {
  2. @Override
  3. public void visit(Subject sub) {
  4. System.out.println( "visit the subject:"+sub.getSubject());
  5. }
  6. }
Subject类,accept方法,接受将要访问它的对象,getSubject()获取将要被访问的属性,

 
  1. public interface Subject {
  2. public void accept(Visitor visitor);
  3. public String getSubject();
  4. }

 
  1. public class MySubject implements Subject {
  2. @Override
  3. public void accept(Visitor visitor) {
  4. visitor.visit( this);
  5. }
  6. @Override
  7. public String getSubject() {
  8. return "love";
  9. }
  10. }
测试:


 
  1. public class Test {
  2. public static void main(String[] args) {
  3. Visitor visitor = new MyVisitor();
  4. Subject sub = new MySubject();
  5. sub.accept(visitor);
  6. }
  7. }
输出:visit the subject:love

该模式适用场景:如果我们想为一个现有的类增加新功能,不得不考虑几个事情:1、新功能会不会与现有功能出现兼容性问题?2、以后会不会再需要添加?3、如果类不允许修改代码怎么办?面对这些问题,最好的解决方法就是使用访问者模式,访问者模式适用于数据结构相对稳定的系统,把数据结构和算法解耦,
22、中介者模式(Mediator)

中介者模式也是用来降低类类之间的耦合的,因为如果类类之间有依赖关系的话,不利于功能的拓展和维护,因为只要修改一个对象,其它关联的对象都得进行修改。如果使用中介者模式,只需关心和Mediator类的关系,具体类类之间的关系及调度交给Mediator就行,这有点像spring容器的作用。先看看图:


User类统一接口,User1和User2分别是不同的对象,二者之间有关联,如果不采用中介者模式,则需要二者相互持有引用,这样二者的耦合度很高,为了解耦,引入了Mediator类,提供统一接口,MyMediator为其实现类,里面持有User1和User2的实例,用来实现对User1和User2的控制。这样User1和User2两个对象相互独立,他们只需要保持好和Mediator之间的关系就行,剩下的全由MyMediator类来维护!基本实现:


 
  1. public interface Mediator {
  2. public void createMediator();
  3. public void workAll();
  4. }

 
  1. public class MyMediator implements Mediator {
  2. private User user1;
  3. private User user2;
  4. public User getUser1() {
  5. return user1;
  6. }
  7. public User getUser2() {
  8. return user2;
  9. }
  10. @Override
  11. public void createMediator() {
  12. user1 = new User1( this);
  13. user2 = new User2( this);
  14. }
  15. @Override
  16. public void workAll() {
  17. user1.work();
  18. user2.work();
  19. }
  20. }

 
  1. public abstract class User {
  2. private Mediator mediator;
  3. public Mediator getMediator(){
  4. return mediator;
  5. }
  6. public User(Mediator mediator) {
  7. this.mediator = mediator;
  8. }
  9. public abstract void work();
  10. }

 
  1. public class User1 extends User {
  2. public User1(Mediator mediator){
  3. super(mediator);
  4. }
  5. @Override
  6. public void work() {
  7. System.out.println( "user1 exe!");
  8. }
  9. }

 
  1. public class User2 extends User {
  2. public User2(Mediator mediator){
  3. super(mediator);
  4. }
  5. @Override
  6. public void work() {
  7. System.out.println( "user2 exe!");
  8. }
  9. }
测试类:


 
  1. public class Test {
  2. public static void main(String[] args) {
  3. Mediator mediator = new MyMediator();
  4. mediator.createMediator();
  5. mediator.workAll();
  6. }
  7. }
输出:

user1 exe!
user2 exe!
23、解释器模式(Interpreter)
解释器模式是我们暂时的最后一讲,一般主要应用在OOP开发中的编译器的开发中,所以适用面比较窄。


Context类是一个上下文环境类,Plus和Minus分别是用来计算的实现,代码如下:


 
  1. public interface Expression {
  2. public int interpret(Context context);
  3. }

 
  1. public class Plus implements Expression {
  2. @Override
  3. public int interpret(Context context) {
  4. return context.getNum1()+context.getNum2();
  5. }
  6. }

 
  1. public class Minus implements Expression {
  2. @Override
  3. public int interpret(Context context) {
  4. return context.getNum1()-context.getNum2();
  5. }
  6. }

 
  1. public class Context {
  2. private int num1;
  3. private int num2;
  4. public Context(int num1, int num2) {
  5. this.num1 = num1;
  6. this.num2 = num2;
  7. }
  8. public int getNum1() {
  9. return num1;
  10. }
  11. public void setNum1(int num1) {
  12. this.num1 = num1;
  13. }
  14. public int getNum2() {
  15. return num2;
  16. }
  17. public void setNum2(int num2) {
  18. this.num2 = num2;
  19. }
  20. }

 
  1. public class Test {
  2. public static void main(String[] args) {
  3. // 计算9+2-8的值
  4. int result = new Minus().interpret(( new Context( new Plus()
  5. .interpret( new Context( 9, 2)), 8)));
  6. System.out.println(result);
  7. }
  8. }
最后输出正确的结果:3。

基本就这样,解释器模式用来做各种各样的解释器,如正则表达式等的解释器等等!

内容概要:该论文研究了激光照射下生物组织内的非傅里叶导热现象,采用双相位滞后生物传热模型(DPL模型)进行分析,并与Pennes模型、热波模型进行了比较。研究表明,当热流延迟时间和温度延迟时间较小时,DPL模型接近传统傅里叶热传导;当热流延迟时间增加时,表现出更多的热波效应。通过数值模拟分析了不同参数下组织的温度分布,结果表明DPL模型能更准确地描述激光与生物组织的热相互作用,对激光临床治疗具有理论指导意义。论文还通过代码实现了DPL模型的数值求解,并比较了三种模型的温度响应差异,分析了不同延迟时间对温度分布的影响,提出了模型选择指导和临床应用建议。 适合人群:具备一定物理学、生物学和编程基础的科研人员、医学工程技术人员以及对激光生物效应感兴趣的学者。 使用场景及目标:①用于研究激光辐照生物组织的热效应;②为激光临床治疗提供理论支持和技术参考;③帮助研究人员理解不同传热模型的特点及其适用场景;④为精确的激光手术规划提供模型选择依据。 其他说明:论文不仅提供了详细的理论分析,还给出了完整的Python代码实现,便于读者复现研究结果。此外,论文还讨论了不同延迟时间对温度分布的具体影响,为激光治疗参数优化提供了理论依据。未来研究方向包括多参数耦合条件下的DPL模型优化、不同组织类型的参数数据库建立等。
《DPD_sim_DPD_数字预失真_DPDmatlab_matlab_预失真_源码.zip》这个压缩包文件包含的是关于数字预失真(Digital Predistortion, DPD)技术的MATLAB源码。DPD是通信系统中一个重要的信号处理技术,主要应用于射频功率放大器(RF Power Amplifier, PA)中,以提高放大器的效率和线性度。本文将详细介绍DPD的基本原理、应用以及MATLAB在实现DPD算法中的关键步骤。 1. 数字预失真技术简介: 数字预失真是一种非线性补偿技术,其基本思想是在信号进入功率放大器之前,通过预设的非线性函数对信号进行逆操作,以抵消放大器在高功率输出时产生的非线性失真。这样可以确保放大后的信号尽可能接近原始输入信号,从而提高系统的线性度和频谱效率。 2. DPD工作原理: DPD的核心是建立一个模型来描述PA的非线性特性,通常采用多项式模型或记忆效应模型。模型参数通过实际PA的测量数据来确定,这一步称为系统校准。一旦模型建立,就可以用该模型对输入信号进行预失真处理。 3. MATLAB在DPD实现中的作用: MATLAB是一种强大的数学计算和数据分析工具,广泛用于信号处理和通信领域的仿真。在DPD中,MATLAB可以用来: - 建立和优化DPD模型:使用MATLAB的曲线拟合工具或自定义算法来拟合PA的非线性特性。 - 实现预失真算法:编程实现预失真器,根据模型对输入信号进行预失真处理。 - 仿真验证:通过仿真比较预失真后的信号与未处理信号,评估DPD的效果。 - 实时系统集成:MATLAB代码可以转换为C/C++,方便嵌入到硬件系统中。 4. DPD的实现步骤: - 数据采集:测量PA在不同输入功率下的输出,获取非线性特性数据。 - 模型选择与参数估计:根据数据选择合适的模型(如多项式模型、LUT模型等),并估计模型参数。 - 预失真器设计:编写MATLAB代码实现预失真算法,通常包括输入信号的预处理、模型运算和输出信号的后处理。 - 仿真与优化:通过MATLAB进行系统仿真,调整模型参数和预失真算法,以达到最佳性能。 - 硬件集成:将MATLAB代码转换为可执行的嵌入式代码,集成到实际的通信系统中。 5. MATLAB源码解析: 由于未提供具体的源码细节,无法深入解析。但一般来说,源码可能包括以下几个部分: - 数据处理模块:读取PA的测量数据,进行预处理。 - 模型建立模块:实现模型选择和参数估计。 - 预失真运算模块:根据模型进行预失真计算。 - 仿真与结果显示模块:展示预失真效果,并可能包括性能指标的计算。 DPD_sim_DPD_数字预失真_DPDmatlab_matlab_预失真_源码.zip这个压缩包文件包含了实现数字预失真技术的MATLAB源码,对于理解和研究DPD技术,以及在实际通信系统中应用DPD具有很高的价值。通过深入学习和分析这些源码,我们可以更深入地理解DPD的工作机制,并将其应用到实际项目中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值