软件详细设计总复习(二)【太原理工大学】

news2024/11/26 2:47:15

文章目录

    • 二、结构型模式
      • 1. 适配器模式
      • 2. 桥接模式
      • 3. 组合模式
      • 4. 装饰模式
      • 5. 外观模式
      • 6. 代理模式

二、结构型模式

1. 适配器模式

适配器是用来将两个原本并不兼容的接口能够在一起工作。就像我们的充电线可以让手机接口和插座接口相互适应,完成工作。
课本上的案例是让机器人模仿其他动物叫,其实就是想让机器人能够适配不同动物的叫声,那么中间必定需要一个桥梁去完成这件事情,这个桥梁就叫做适配器,机器人叫做被适配者。
适配原理很简单,适配器类要实现机器人接口,然后重写机器人类中的叫方法,何为模仿?就是说你咋叫我就咋叫,那么重写机器人的叫方法里面是不是应该写那些动物的叫声呢?当然我们肯定不可能直接打印输出,那就没意义了,而是在这里面调用其它动物的叫方法,没有动物对象是不能调用其方法的,所以在适配器类中,我们还需 new 动物对象,然后在方法里面调用其方法。
以上例子是单方面地适配也就是单向适配,而我们的实验中又提到了一种双向适配。就是说猫可以学狗的一些行为,狗也可以学习猫的一些行为,它们之间是互相学习的,两个抽象类互为抽象目标和抽象适配者。在适配器类中new一个小猫对象和一个小狗对象,并重写它们的所有抽象方法,互相学习的过程就是互相调用对方方法的过程。
适配器模式将现有的接口需要转化为客户类期望的接口,使接口不兼容的那些接口可以一起工作,保证了对现有类的重用。

整体结构:
① 一个适配器类,双向适配要实现互相适配的两个接口;
② 两个抽象类,即互相学习的猫和狗;
③ 两个具体适配者兼目标类,重写抽象类中的所有方法。

//适配器类
package com.zxetest1;

public class Adapter implements Cat, Dog {
    private Cat cat = new ConcreteCat();
    private Dog dog = new ConcreteDog();
    @Override
    public void cry() {
        System.out.print("小猫学");
        dog.wang();
    }
    @Override
    public void catchMouse() {
        cat.catchMouse();
    }
    @Override
    public void wang() {
        dog.wang();
    }
    @Override
    public void action() {
        System.out.print("小狗学");
        cat.catchMouse();
    }
}
//抽象类
public interface Cat {
    public void cry();
    public void catchMouse();
}

public interface Dog {
    public void wang();
    public void action();
}
//具体适配者兼目标类
public class ConcreteCat implements Cat {
    @Override
    public void cry() {
        System.out.println("小猫喵喵喵~");
    }
    @Override
    public void catchMouse() {
        System.out.println("小猫捉老鼠啦!");
    }
}

public class ConcreteDog implements Dog {
    @Override
    public void wang() {
        System.out.println("小狗汪汪汪~");
    }
    @Override
    public void action() {
        System.out.println("小狗吃骨头!");
    }
}

2. 桥接模式

上课的时候,老师拿毛笔和蜡笔来举例的,题目大概是这样的:
现需要提供大中小 3 种型号的画笔,能够绘制 5 种不同的颜色。如果使用蜡笔,我们需要准备 15 支蜡笔,也就是说必须准备 15 个具体的蜡笔类。而如果使用毛笔的话,只需要 3 种型号的毛笔,外加 5 个颜料盒,用 8 个类就可以实现 15 支蜡笔的功能。

如果系统中某个类存在两个独立变化的维度,通过桥接模式可以将这两个维度分离出来,使得两者可以独立扩展。桥接模式用一种巧妙的方式处理多层继承存在的问题,用抽象关联取代了传统的多重继承,将类之间的静态继承关系转换为动态的对象组合关系,使得系统更加灵活,并易于扩展,同时有效地控制了系统中类的个数。

整体结构:
① 一个抽象类,引入实现类并提供 add 方法;
② 数个抽象类的子类,完成对实现类中 beAdd 方法的调用;
③ 一个实现类接口 ,内置 beAdd 方法;
④ 数个具体的实现类,重写 beAdd 方法。

public abstract class Food {
    //水果
    Fruit fruit;
    
    public void setFruit(Fruit fruit) {
        this.fruit = fruit;
    }
    //制作时添加
    public abstract void add();
}
public class Cake extends Food {
 
    @Override
    public void add() {
        fruit.beAdd("蛋糕");
    }
}

public class Milk extends Food {
    @Override
    public void add() {
        fruit.beAdd("牛奶");
    }
}
public interface Fruit {
    //被添加
    public void beAdd(String food);
}
public class Banana implements Fruit {
    @Override
    public void beAdd(String food) {
        System.out.println("香蕉" + food);
    }
}

public class Mango implements Fruit {
    @Override
    public void beAdd(String food) {
        System.out.println("芒果" + food);
    }
}

3. 组合模式

组合模式就像课本上的盘子和水果的关系,又或实验里的文件夹和文件的关系,一个文件夹里可以有很多文件,也可以有更多的文件夹。
访问的时候自然就用到递归进行遍历,俗称套娃模式,一层一层地执行,到最后剩下的就是文件不能再分解,而文件就是我们最终想要的结果,这里一个文件夹里面的所有内容我们是用集合来接收的,以便后续遍历。
组合模式通过一种巧妙的设计方案使得用户可以一致性地处理整个树形结构或者树形结构的一部分,它描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无需对它们进行区分,可以一致性地对待容器对象和叶子对象。

在这里插入图片描述

整体结构:
① 一个抽象文件类,既包括文件也包括文件夹,内部提供一个展示方法;
② 数个具体文件类,继承抽象文件类,最终的展示结果;
③ 一个具体文件夹类,继承抽象文件类,用 List 集合来存放文件夹下的东西,当调用展示方法的时候,内部使用遍历的方式去调用集合中每一个元素的展示方法,如果该元素是一个文件,那么它会直接输出,如果该元素是一个文件夹,那么又回到了文件夹的操作上,一层一层展开,直至最后仅剩下文件,输出结果。

public abstract class AbstractFile {
    public abstract void display();
}
public class VideoFile extends AbstractFile {
    @Override
    public void display() {
        System.out.println("这是一个视频文件!");
    }
}
public class TextFile extends AbstractFile {
    @Override
    public void display() {
        System.out.println("这是一个文本文件!");
    }
}
public class Folder extends AbstractFile {
    private ArrayList<AbstractFile> arrayList = new ArrayList<>();
    public void add(AbstractFile file) {
        arrayList.add(file);
    }
    public void remove(AbstractFile file) {
        arrayList.remove(file);
    }
    @Override
    public void display() {
        for (AbstractFile a : arrayList) {
            a.display();
        }
    }
}

4. 装饰模式

我们生活中的装饰就是在不改变原有模样的基础上,去为它装扮一些新的东西。
在设计模式中,装饰模式出现的动机是,可以在不改变一个对象本身功能的基础上给对象增加额外的新行为。它是一种用于替代继承的技术,它通过一种无须定义子类的方式给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系,引入了装饰类,在装饰类中既可以调用待装饰的原有类的方法,还可以增加新的方法,以扩展原有类的功能。

整体结构:
① 一个抽象构建类,内置基本操作方法;
② 数个具体构建类,重写抽象构建内中的方法;
③ 一个抽象装饰类,继承抽象构建类,使用带参构造的方法传入一个具体构建,然后实现原有方法;
④ 数个具体装饰类,新增业务方法,重写父类方法,并在重写方法中调用原有业务方法及新增业务方法。

public abstract class Component {
 public abstract void operation();
}
public class ConcreteComponent extends Component {
 public void operation() {
 //实现基本功能 
 }
}
public class Decorator extends Component {
 private Component component; //维持一个对抽象构件对象的引用
 //注入一个抽象构件类型的对象
 public Decorator(Component component) {
 this.component=component;
 }
 public void operation() {
 component.operation(); //调用原有业务方法
 }
}
public class ConcreteDecorator extends Decorator {
 public ConcreteDecorator(Component component) {
 super(component); 
 }
 public void operation() {
 super.operation(); //调用原有业务方法
 addedBehavior(); //调用新增业务方法
 }
 //新增业务方法
 public void addedBehavior() {
 ……
 }
}

5. 外观模式

通俗一点地理解,它有点像我们电脑的开关机,当你按了开关机键之后,就可以统一控制电脑内部各程序的运行与结束。就是说我现在只用一个开关就可以控制全部软件及硬件的运行。
在外观模式中,我们也会设置一个这样的开关,客户端直接使用这个开关来控制所有的方法。

外观模式为复杂的子系统调用提供一个统一的入口,使子系统与客户端的耦合度降低,且客户端调用非常方便。

整体结构:
① 数个子系统类,即开关要管理的对象;
② 一个总开关类,在无参构造方法里面 new 子系统对象,因为我们要调用这些子系统的方法,提供一个总开关入口方法,在该方法里面调用各子系统的方法,实际上就是把对子系统的调用步骤从客户端转移到了总开关类中。

public class Memory {
    public void check() {
        System.out.println("你好主人,内存正在自检中,请稍等!");
    }
}

public class CPU {
    public void run() {
        System.out.println("你好主人,CPU 跑起来了!");
    }
}

public class HardDisk {
    public void read() {
        System.out.println("你好主人,硬盘正在努力读取中,请稍等!");
    }
}

public class OS {
    public void load() {
        System.out.println("你好主人,操作系统正在加载中,忙坏了!");
    }
}
public class Mainframe {
    private Memory memory;
    private CPU cpu;
    private OS os;
    private HardDisk hardDisk;

    public Mainframe() {
        memory = new Memory();
        cpu = new CPU();
        os = new OS();
        hardDisk = new HardDisk();
    }

    public void on() {
        memory.check();
        cpu.run();
        os.load();
        hardDisk.read();
    }

}

6. 代理模式

代理即代替别人来完成一些事情。
代理模式是常用的结构型设计模式之一,当直接访问某些对象存在问题时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。

通过引入一个新的对象来实现对真实对象的操作,戒者将新的对象作为真实对象的一个替身。

整体结构:
① 一个抽象主题类,一般为接口;
② 数个目标类,实现接口;
③ 数个代理类,实现上述接口,是对被代理角色的增强。

public interface Movie {
    void play();
}
public class RealMovie implements Movie {
    @Override
    public void play() {
        System.out.println("您正在观看电影 《肖申克的救赎》");
    }
}
public class Cinema implements Movie {

    RealMovie movie;
    public Cinema(RealMovie movie) {
        super();
        this.movie = movie;
    }

    @Override
    public void play() {
        guanggao(true);    // 代理类的增强处理
        movie.play();     // 代理类把具体业务委托给目标类,并没有直接实现
        guanggao(false);    // 代理类的增强处理
    }

    public void guanggao(boolean isStart){
        if ( isStart ) {
            System.out.println("电影马上开始了,爆米花、可乐、口香糖9.8折,快来买啊!");
        } else {
            System.out.println("电影马上结束了,爆米花、可乐、口香糖9.8折,买回家吃吧!");
        }
    }
}

Cinema 就是代理对象,它有一个 play() 方法。不过调用 play() 方法时,它进行了一些相关利益的处理,那就是广告。也就是说,代理类与目标类都可以播放电影,但是除此之外,代理类还对 “播放电影” 这个行为进行进一步增强,即增加了额外的处理,同时不影响目标类的实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/551909.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux防火墙iptables

文章目录 一.iptables概述二.netfilter/iptables 关系三.四表五链3.1作用3.2四表3.3五链3.4规则表的优先顺序3.5规则链的匹配顺序3.6iptables 命令行配置方法3.8常用管理选项3.9iptables安装 四、操作4.1 增加规则4.2删除规则4.3修改规则4.4查询规则 五、规则匹配5.1通用匹配5.…

IDEA快捷键总结

IDEA快捷键总结 KeyMap使用的是Eclipse 常用快捷键 Ctrl H 全局搜索Shift Shift 搜索源码Ctrl O 查看当前类或接口包含的方法&#xff0c;即自身结构。Ctrl Alt B 选中接口名&#xff0c;查看当前接口的实现类Ctrl Alt V 快速补全Ctrl Alt ↓ 复制当前行到下一行C…

广告让你不自觉地掏钱?消费者行为背后的心理学

一般来说&#xff0c;应该从广告的各个方面提升&#xff0c;比如与目标用户的需求匹配&#xff0c;产品定位&#xff0c;核心卖点&#xff0c;突出重点和价值&#xff0c;不断重复&#xff0c;等等的这些都说的很好&#xff0c;给用户提供了做这件事的足够的动机和理由。 但我…

【组合优化】基于CHHO的QoS感知的web服务组合优化【Matlab代码22#】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第7节&#xff1a;资源获取】1. Web服务2. QoS感知的Web服务组合3. 改进后的CHHO算法3.1 原始HHO算法3.2 CHHO算法 4. 优化目标5. 部分代码展示6. 仿真结果展示7. 资源获取 【可更换其他算法&#xff0c;获取资源请见文章…

rpc与grpc学习记录

文章目录 1、RPC2、gRPC多线程pythongrpc代码1、安装python需要的库&#xff1a;2、grpc编程步骤3、Demo13.1、编写 .proto文件&#xff0c;定义接口和数据类型3.2、编译 .proto文件生成存根文件3.3、编写服务器端代码&#xff1a;3.4、编写客户端代码&#xff1a;3.5、测试 1、…

docker操作2

docker操作2 文章目录 docker操作2启动新容器配置新的容器后要做的操作进入Docker容器可以显示图片的容器镜像pull 网络镜像 日志停止与删除停止删除删除image报错 在容器和宿主机之间拷贝数据创建命令别名查看docker运行容器的ipdocker image保存与导入保存image导入image 打标…

CMake的应用与实践

CMake 简介 CMake是什么&#xff1f; 全称 Cross Platform Make&#xff0c;起初为了跨平台需求&#xff0c;而后不断完善并广泛使用一款优秀的工程构建工具 特点和优势 开放源代码&#xff0c;具有BSD许可跨平台&#xff0c;支持Linux&#xff0c;Mac和Windows等不同操作系…

【C生万物】 字符串内存函数篇 (上)

欢迎来到 Claffic 的博客 &#x1f49e;&#x1f49e;&#x1f49e; &#x1f449; 专栏&#xff1a;《C生万物 | 先来学C》&#x1f448; 前言&#xff1a; 过了指针这个坎后&#xff0c;下一步就是C语言中关于字符的处理&#xff0c;这一期来讲…

chatgpt赋能Python-python5个一行

Python: 5行代码改变世界 Python是一种高级编程语言&#xff0c;以其简单易学的特性而闻名。Python的发明者Guido van Rossum在1980年代末和1990年代初创造了Python&#xff0c;旨在创建一种语言&#xff0c;既易于理解又易于使用。如今&#xff0c;Python已经成为了最受欢迎的…

【离散数学】陪集和拉格朗日定理编程题

1&#xff1a;编写一个程序能够计算有限群G的子群H的左陪集 输入一个n阶有限群G的二元运算表及相关的子群&#xff0c;输出其左陪集。 &#xff08;注意&#xff1a;按照表头元素顺序计算每个陪集&#xff0c;下图为G的二元运算表示例&#xff09; 样例1&#xff1a; 输入&…

干货 | 利用SPSS进行高级统计分析第三期

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ 在本期中&#xff0c;我们继续为大家介绍如何利用SPSS进行&#xff1a;单因素方差分析、多因素方差分析、重复测量方差分析等。 1. 单因素方差分析【组间实验单一因变量&#xff1b;进行差…

iptables防火墙中的SNAT和DNAT

SNAT的原理和应用 SNAT 应用环境∶局域网主机共享单个公网IP地址接入Internet &#xff08;私有IP不能在Internet中正常路由&#xff09; SNAT原理∶修改数据包的源地址。 SNAT转换前提条件∶ 局域网各主机已正确设置IP地址、子网掩码、默认网关地址Linux网关开启IP路由转发…

游资92科比到底牛在哪里?

昨天一天时间把92科比之前的一个帖子全部看完&#xff0c;从科比对情绪周期的把握来看那简直总结的已经是标准答案了&#xff0c;那么为何92科比公布了答案&#xff0c;还是有很多人“痛苦”的做不到&#xff1f; 这个问题我觉得跟退学炒股是一样的&#xff0c;退学先解决了小…

springcloud-alibaba (03)sentinel下载安装

Sentinel 一&#xff0c;下载安装&#x1f4a0;二&#xff0c;编写脚本&#x1f9ff;三&#xff0c;启动sentinel&#x1f48e;四&#xff0c;Win-访问控制台✨ 在Linux中下载安装Spring Cloud Alibaba Sentinel&#xff0c;可以按照以下步骤进行操作&#xff1a; 一&#xff0…

Python常见面试题. Python中的解包操作及其应用场景

这是个简单的知识点&#xff0c;但有的同学并不理解 unpacking解包 解&#xff0c;对应的是*或者**&#xff0c;也有自动解包之说 包对应的可迭代对象 Python助学大礼包点击跳转获取 目录 一、自动解包二、数据过多的解包*三、星号在函数中的使用四、两个星号的解包五、场…

Lesson13---人工神经网络(2)

13 人工神经网络&#xff08;2&#xff09; 多层神经网络-非线性分类问题多层神经网络的损失函数不是凸函数&#xff0c;很难计算解析解通常采用梯度下降法&#xff0c;得到数据解&#xff0c;梯度下降法可以用来求解函数极值问题 批量梯度下降随机梯度下降小批量梯度下降 1…

[Nacos] Nacos Client获取所有服务和定时更新Client端的注册表 (三)

文章目录 1.Nacos Client获取所有服务1.1 Client如何获取所有服务1.2 Client获取服务方法getServices()详解 2.Nacos定时更新Client端的注册表2.1 Nacos和Eureka定时更新Client端的注册表的区别2.2 Client定时更新本地服务过程2.3 updateServiceNow方法解析2.4 定时更新本地注册…

DrissionPage学习(一)

一、下载适合mac环境的chromedriver.exe 1.查找chrome浏览的版本 方法二&#xff1a;查看chrome版本信息 2.确定版本后在下载chrome对应的chromedriver.exe 下载地址&#xff1a;http://chromedriver.storage.googleapis.com/index.html 3.在文件夹中找到下载的文件chro…

MyBatis-Plus or() equls() 连用的格式为 a AND (b OR c)

正确示范&#xff1a; userInterfaceQueryWrapper.and(qw -> qw .eq("status", UserInterfaceInfoStatusEnum.OFFLINE) .or() .eq("status", UserInterfaceInfoStatusEnum.TRYOUT));错误示范&#xff1a; userInterfaceQueryWrapper.eq("status&…

分布式项目10.jsonp 使用js中script的属性src进行服务器之间的访问

一般使用ajax来访问不同服务器的数据&#xff0c;可行吗&#xff1f; 做个实验&#xff1a; 第一步&#xff1a;在本服务器中使用ajax技术访问本服务器数据 <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>测试JSON跨域…