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

news2024/10/5 19:20:49

实验内容重点看,无需死记,它更是一种设计思想。要理解一种设计模式出现的意义是什么,它又是如何方便我们使用的?目的无非就是解耦、易扩充。题目问到优缺点,你只要知道该模式的设计思想就完全可以用自己的话概述,所以还是不用死记,全书围绕面向对象设计原则进行编程,也就是课本P26页的表格。
本来这门课不打算出博客了,现在又决定还是出一下吧,反正写博客的时候自己也就跟着顺便复习了,重要的章节我会放源码,不重要的只放核心思路,本篇内容是根据自己的理解写的,总结不易,进来的小伙伴希望能留个攒,感谢!

文章目录

    • 一、创建型模式
      • 1. 简单工厂模式
      • 2. 工厂方法模式
      • 3. 抽象工厂模式
      • 4. 建造者模式
      • 5. 原型模式
      • 6. 单例模式

一、创建型模式

1. 简单工厂模式

工厂是用来干什么的?在我们的生活中工厂当然是用来生产产品的,但在 Java 中,工厂是用来生产对象的,如何生产?内部原理其实还是 new 了一个具体的实现类。
为什么叫简单工厂模式呢?简单是因为它是静态的,何为静态?静态即关键字 static,工厂方法用 static 修饰后,测试类中就直接可以通过类名调用方法,而无需创建工厂对象。
我们明明可以直接在测试类中 new 一个对象,调用方法就可以了,为什么还要用到这工厂类呢?这里正是简单工厂模式出现的意义:

当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无需知道其创建细节,即在测试类中无需创建对象,只负责传入产品名称即可。

整体结构:
① 一个抽象产品类,里面有一个抽象方法;
② 数个具体产品类,重写抽象产品类中的抽象方法;
③ 一个工厂类,里面有一个静态方法,通过条件分支对传入的参数做不同的判断,并返回所对应的产品对象;
④ 一个测试类,通过工厂类调用其静态方法,并传入参数,返回的结果就是该参数所对应的产品对象,产品对象调用其内置方法,并输出结果。

这里有一个小的问题,当我们每次生产不同的产品都需要在测试类中传入不同的参数,这是不符合开闭原则的,就是说我测试类中的东西你不要随意地动,这时候就想,我们能不能把它做成死的以后就固定住了,所以在此我们引入一个工具类 XMLUtil,通过它可以从 XML 格式的配置文件中读取节点获取数据,如需修改产品名称,无需修改客户端代码,只需修改配置文件,通过配置文件可以极大地提高系统的扩展性,让软件实体更符合开闭原则。
此工具类我们会一直使用,后面再出现就不多做解释,但是放心考试是不会考工具类的。

//简单工厂类
public class PhoneFactory {
    public Phone makePhone(String phoneType){
        if(phoneType.equalsIgnoreCase("XM")){
            return new XmPhone();
        }
        else if(phoneType.equalsIgnoreCase("PG")){
            return new PgPhone();
        }
        return null;
    }
}

2. 工厂方法模式

在上述简单工厂模式中存在诸多的缺点,最明显的就是它把所有产品对象的创建过程都放在一个工厂类里面,万一我们其中一个地方出错呢?系统就全盘崩溃了,万一我要增加新的产品呢?你还要去修改工厂类中的条件分支语句,这有违开闭原则。
对此,工厂方法模式帮我们解决这些问题。解决办法就是使工厂类更加抽象,新增一个抽象工厂类,只提供一个公共的生产方法,而具体的创建工作交给子工厂类去做。

当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体产品对象以及一个具体工厂对象即可,原有对象不需要进行任何修改,也不需要修改客户端,即对外扩展开放,对内修改关闭。

整体结构:
① 一个抽象产品类;
② 数个具体产品类;
③ 一个抽象工厂类,内置公共生产方法;
④ 数个具体工厂类,每个具体工厂负责生产一种产品。

//抽象工厂类
public interface TVFactory {
	public TV createTV();
}
//具体工厂类
public class HaierFactory implements TVFactory {
	public TV createTV() {
		return new HaierTV();
	}
}

3. 抽象工厂模式

我觉得抽象工厂模式应该是工厂方法模式的升级版。
此话怎讲?上面的工厂方法模式,一个工厂里面只能生产一种产品,这能合理吗?工厂怎么可能只生产一种产品呢,不管你是海尔品牌还是 TCL 品牌,除了生产电视机,我是不是还可以生产冰箱、生产空调,这合情合理吧?
怎么做呢?你既然要增加新的产品,那么就多写几个产品抽象类,并实现。
抽象工厂类中也要新增生产方法,之前只生产电视,现在请增加几个其它产品的生产方法,至于增加几个?你有几种产品就增加几个呗,然后让具体工厂类实现该抽象工厂类,最终返回其所对应的产品对象。
具体产品在应用层的代码被隔离,无需关心创建的细节,将一系列的产品统一到一起去创建,如果需要增加新的工厂,直接继承抽象工厂类即可。但是缺点也很明显,如果需要增加新的产品就意味着要彻底修改所有的工厂类对象,扩展是很困难的,增加了系统的抽象性和理解难度。

整体结构:
① 数个抽象产品类;
② 数个具体产品类;
③ 一个抽象工厂类,内置数个公共生产方法;
④ 数个具体工厂类,每个具体工厂负责生产它自己旗下的数个产品。

在这里插入图片描述

//抽象产品类
public abstract class CPU {
    public abstract void isCPU();
}

public abstract class RAM {
    public abstract void isRAM();
}
//具体产品类
public class MacCPU extends CPU {
    @Override
    public void isCPU() {
        System.out.println("是Mac的CPU!");
    }
}

public class PcCPU extends CPU {
    @Override
    public void isCPU() {
        System.out.println("是Pc的CPU!");
    }
}

public class MacRAM extends RAM {
    @Override
    public void isRAM() {
        System.out.println("是Mac的RAM!");
    }
}

public class PcRAM extends RAM {
    @Override
    public void isRAM() {
        System.out.println("是Pc的RAM!");
    }
}
//抽象工厂类
public abstract class AbstractFactory {
    public abstract CPU produceCPU();
    public abstract RAM produceRAM();
}
//具体工厂类
public class PcFactory extends AbstractFactory {
    @Override
    public CPU produceCPU() {
        return new PcCPU();
    }
    public RAM produceRAM() {
        return new PcRAM();
    }
}

public class MacFactory extends AbstractFactory {
    @Override
    public CPU produceCPU() {
        return new MacCPU();
    }
    public RAM produceRAM() {
        return new MacRAM();
    }
}

4. 建造者模式

首先想一下建造者是干什么的?你说那还用问吗自然是建设与创造啊。以课本例子为例,当你去饭店吃饭的时候服务员会给你推荐几个套餐,不同套餐里的食物也会不一样,而每一份套餐我们都会有特定的人去生产,这些制作套餐的对象我们称之为建造者,建造者有很多,一个建造者对应一种套餐。
还要有一个服务员,由他来接收客户需求,并传达套餐需求给建造者。
套餐类用于将传入的套餐信息封装成一个完整的菜单,里面有两个方法,一个吃一个喝,以及各自的 get、set 方法,用于后续的传参取参操作。
在抽象建造者类中,第一步需要 new 一个套餐对象,因为建造的过程就是给套餐类传参的过程,接下来给出两个抽象方法,用于建造食物和饮品。我们要想在控制台输出套餐结果,就得先获取到套餐对象,在抽象建造者类里再提供一个方法用于返回 meal 对象。
具体建造者类依次继承抽象建造者类并实现其所有方法,其实就是调用套餐类的 set 方法进行传参,这些传入的参数就是套餐内容。
我们本来可以在测试类中直接调用建造者类中的 buildFood、buildDrink、getMeal 方法进行传参以及获取套餐对象,但如果把这些过程全都写在测试类中,这还像是设计模式的思想吗?对于客户端我们尽量是不要暴露太多内部操作的,所以这里我们又引入一个指挥者类。
首先,指挥者类中要给出一个 setMealBuilder 方法,测试类会通过调用该方法进行传参,此参正是套餐类型,同时再写一个 construct 方法,在该方法里面我们要进行对 buildFood 和 buildDrink 的调用,最后返回抽象建造者类中的 getMeal 方法,即返回一个 meal 对象,调用 meal 的 get 方法将套餐内容输出在控制台。

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

整体结构:
① 一个复杂产品类,数个成员属性以及各自的 get、set 方法;
② 一个抽象建造者类;
③ 数个具体建造者类,调用产品类的 set 方法并传参;
④ 一个指挥者类,将客户端的调用请求都封装在了一个类中,保证了客户端对外的封闭性。

//产品类
public class Meal {
	private String food;
	private String drink;
	public String getFood() {
        return food;
	}
    public void setFood(String food) {
	    this.food = food;
	}
	public String getDrink() {
	    return drink;
	}
	public void setDrink(String drink) {
	    this.drink = drink;
	}
}
//抽象建造者类
public abstract class MealBuilder {
    Meal meal = new Meal();
    public abstract void buildFood();    
    public abstract void buildDrink();   
    public Meal getMeal(){
        return meal;
}
//具体建造者类
public class MealA extends MealBuilder{
    public void buildDrink() {
        meal.setDrink("汉堡");
    }
    public void buildFood() {
        meal.setFood("果汁");
    }
}
//指挥者类
public class KFCWaiter {
    private MealBuilder mealBuilder;   
    public KFCWaiter(MealBuilder mealBuilder) {
        this.mealBuilder = mealBuilder;
    }
    public Meal construct(){
        mealBuilder.buildFood();
        mealBuilder.buildDrink();
        return mealBuilder.getMeal();
    }
}

5. 原型模式

原型即原始的模型,那么它出现的场合是啥呢?
当需要创建大量相同或者相似的对象时,可以通过对一个已有对象的复制获取更多对象。也就是说我们只需要创建一个原型对象,然后通过在类中定义的克隆方法来复制自己,当创建新对象的成本较大时,原型模式可以极大地提高创建新实例对象的效率。

整体结构:
① 一个抽象原型类,内置抽象克隆方法;
② 一个具体原型类。

浅克隆可以使用Java自带的克隆方法,需实现 Cloneable 接口,浅克隆只复制值类型的变量,不复制引用类型,所以克隆前后的 WeeklyLog 是两个完全不同的对象,但其内部的成员对象Attachment是同一个对象。

//具体原型类,浅克隆
public class WeeklyLog implements Cloneable{
    //getter,setter方法省略
    private Attachment attachment;
    private String name;
    private String date;
    
    //浅克隆核心代码
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

深克隆可以通过实现序列化接口,将对象写入流中,再从流中进行读取的方法实现,需实现 Serializable 接口,深克隆对于值类型变量和引用类型变量都会复制,所以克隆前后的 WeeklyLog 和 Attachment 都已不是同一个对象。

//具体原型类,深克隆
public class WeeklyLog implements Serializable {

    public WeeklyLog deepClone() throws IOException, ClassNotFoundException {
        //getter,setter方法省略
        private Attachment attachment;
        private String name;
        private String date;
       
        //深克隆核心代码
        //将对象写入到流中
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(baos);
        oos.writeObject(this);
		
	    //将对象从流中取出
        ByteArrayInputStream  bis=new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bis);
        return (WeeklyLog)ois.readObject();
        }
}    

6. 单例模式

顾名思义,单例指的是单个的实例,它是,所有设计模式中结构最为简单的模式。
单例模式要确保一个类中只有一个实例,且自行实例化,这个类称为单例类,它提供全局访问的方法。

注意:
① 单例类的构造函数为私有,阻止外部通过构造函数创建对象;
② 提供一个自身的静态私有成员变量,为什么是静态的?因为该成员变量可以说是一个标识,我们想用它来判断一个对象是否已经存在,就必须把它设为 static,保证每次操作之后的变量值不会恢复,内部条件判断语句判断该变量值是否为空,如果为空就代表对象不存在,接下来 new 一个对象并为其设置参数,这个时候的成员变量值已经不是空了,当下次在客户端再调用该方法时,由于成员变量值不为空,将走 else 路线告诉客户端对象已经存在不允许重复创建;
③ 提供一个公有的静态工厂方法,共有的静态方法是为了客户端可以直接通过类名调用方法,而无需再创建类对象。

既然知道了单例模式,那多例模式你能想到吗?没错,以下正是我们实验里面的内容,我们能不能想办法保证一个类只能创建固定数量的对象呢,单例模式通过是否为空来控制,同样道理,多例模式我们完全可以用数字来控制。
就是说在一个类中只允许存在有限个实例对象,在判断的时候让创建对象的次数小于某个值就可以,小于就创建新对象,如果超出设定个数就不会再创建。同时给出私有的无参构造方法,使外部不能通过new来实例化对象,即只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。

public class Multiton {
    private static Multiton array;
    private static int i = 1;

    private Multiton() {

    }

    public static Multiton getInstance() {
        int count = random();
        if (count <= 3) {
            array = new Multiton();
            System.out.println("第" + count + "个对象!");
        } else {
            System.out.println("只允许创建三个对象!");
        }
        return array;
    }

    public static int random() {
        return i++;
    }
}
public class Client {
    public static void main(String[] args) {
        Multiton m1 = Multiton.getInstance();
        Multiton m2 = Multiton.getInstance();
        Multiton m3 = Multiton.getInstance();
        Multiton m4 = Multiton.getInstance();
    }
}

在这里插入图片描述

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

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

相关文章

chatgpt赋能Python-python3绘制图形

Python3绘制图形 – 让数据更加生动 作为一种可视化数据的工具&#xff0c;图形在数据分析和展示中扮演着重要的角色。Python3作为一种高效的编程语言&#xff0c;在图形方面也有自己的实现方式&#xff0c;让我们一起来了解Python3的图形绘制。 什么是Python3图形绘制&#…

chatgpt赋能Python-python3_取余

Python3 取余 在Python3中&#xff0c;取余运算是使用%符号进行实现的。它可以用于整数和浮点数&#xff0c;并返回一个余数。Python3是一种开放源码、高级编程语言。它是一种解释型语言&#xff0c;由于其简洁的语法和易于阅读的特性而受到广泛的欢迎。 取余基础 取余运算就…

ContOS7单机安装Hadoop

安装Hadoop 1&#xff0c;准备环节 因为Hadoop是由java编写的&#xff0c;所以需要Java的环境支持&#xff0c;作为开发者我们需要安装jdk。 安装jdk的教程http://t.csdn.cn/6qJKg 下载Hadoop的安装包 Hadoop官网&#xff1a;http://hadoop.apache.org/ Hadoop版本下载地…

【连续介质力学】张量的偏微分、球张量和偏张量

张量的偏微分 张量的一阶微分&#xff0c;定义&#xff1a; ∂ A ∂ A A , A ∂ A i j ∂ A k l ( e ^ i ⨂ e ^ j ⨂ e ^ k ⨂ e ^ l ) δ i k δ j l ( e ^ i ⨂ e ^ j ⨂ e ^ k ⨂ e ^ l ) I \frac{\partial A}{\partial A} A_{,A}\frac{\partial A_{ij}}{\partial A…

C++ map用法总结(整理)

1&#xff0c;map简介 map是STL的一个关联容器&#xff0c;它提供一对一的hash。 第一个可以称为关键字(key)&#xff0c;每个关键字只能在map中出现一次&#xff1b;第二个可能称为该关键字的值(value)&#xff1b; map以模板(泛型)方式实现&#xff0c;可以存储任意类型的…

算法26:暴力递归

目录 题目1&#xff1a;给你一个字符串&#xff0c;要求打印打印出这个字符串的全部子序列&#xff08;子序列不能重复&#xff09; 题目2&#xff1a;打印一个字符串的全部排列。 题目3&#xff1a;针对题目2&#xff0c;要求去除重复元素 题目4&#xff1a;给定一个字符串…

【靶机】vulnhub靶机billu

靶机下载地址&#xff1a;https://download.vulnhub.com/billu/Billu_b0x.zip 一、环境搭建 1.1 实验环境设计 使用vmware导入靶机&#xff0c;模式为nat模式即可&#xff0c;同时开启kali作为攻击机&#xff0c;对靶机进行渗透&#xff0c;要确定两台主机在同一网段。 Kali…

[Python从零到壹] 六十六.图像识别及经典案例篇之基于机器学习的图像分类

五月太忙&#xff0c;还是写一篇吧&#xff01; 欢迎大家来到“Python从零到壹”&#xff0c;在这里我将分享约200篇Python系列文章&#xff0c;带大家一起去学习和玩耍&#xff0c;看看Python这个有趣的世界。所有文章都将结合案例、代码和作者的经验讲解&#xff0c;真心想把…

opencv_c++学习(十五)

一、图像的模板匹配 顾名思义&#xff0c;模板匹配是在一幅图像中寻找一个相同或相似的对象&#xff0c;如上图所示。 matchTemplate(lnputArray image, lnputArray templ,OutputArray result, int method, lnputArray mask noArray())image:待模板匹配的原图像&#xff0c;图…

【Spring/MySQL数据库系列】数据库事务的特点与隔离级别

⭐️前面的话⭐️ 本文已经收录到《Spring框架全家桶系列》专栏&#xff0c;本文将介绍有关数据库事务的特点以及隔离级别。 &#x1f4d2;博客主页&#xff1a;未见花闻的博客主页 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4…

数值计算 - 利用机器计算的基本方式

离散化方法 设f(x)是定义在[a,b]上的连续函数&#xff0c;当它们的表达式很复杂&#xff0c;甚至写不出来时&#xff0c;我们可以选择若干个离散点 求出f(x)在这些点处的函数值或函数值的近似值 从而得到一个如下的函数值列表&#xff1a; ⚠️提示&#xff1a;对于一个实际的…

Android源码环境搭建

Android源码环境搭建 参考&#xff1a; Android源码环境搭建 1.安装Ubuntu16.4 系统 2.openjdk 8 的安装 sudo apt-get install openjdk-8-jdk使用java -version检查版本 3.安装所有的软件包 sudo apt-get install git-core gnupg flex bison gperf build-essential zip c…

Shell基础学习---3、Read读取控制台输入、函数、正则表达式入门

1、Read读取控制台输入 1、基本语法 read &#xff08;选项&#xff09; &#xff08;参数&#xff09; 选项说明-p指定读取值的提示符-t指定读取值等待的时间(秒) 如果-t不加表示一直等待 参数说明变量指定读取值的变量名 2、案例实操 2、函数 2.1 系统函数 2.1.1 bas…

【数据库】SQLServer报修表,维修表,反馈表三表连查

大家好&#xff0c;我是雷工&#xff01; 最近参与的一个SCADA项目&#xff0c;客户要求增加设备维保的功能&#xff0c;对设备的报修&#xff0c;维修&#xff0c;反馈过程进行记录查询&#xff0c;进一步提升企业的信息化能力。 该过程的实现是通过创建三个表分别记录报修-维…

uniapp 用css画五边形(app 小程序),长方形中间斜线分割成两部分

效果图 css .scoreLabel{ background: $yxs-theme-color; width: 64rpx; height: 69rpx; line-height: 32rpx; font-size: 28rpx; font-family: DINPro; f…

chatgpt赋能Python-python3_9安装scrapy

Python3.9安装Scrapy——加速数据抓取的利器 在现代数字化时代&#xff0c;数据抓取和数据挖掘的重要性越来越受到重视。作为一种高效的爬虫框架&#xff0c;Scrapy能够实现快速的页面抓取和数据解析&#xff0c;并帮助我们快速获取所需数据。本篇文章将会为大家介绍如何在Pyt…

【零基础学web前端】CSS学习,字体属性,文本属性,背景属性,圆角矩形属性

前言: 大家好,我是良辰丫,在上一篇文章中我们了解了CSS引入方式,CSS基础选择器,CSS复合选择器,今天我们继续学习CSS的相关知识点.&#x1f49e;&#x1f49e; &#x1f9d1;个人主页&#xff1a;良辰针不戳 &#x1f4d6;所属专栏&#xff1a;零基础学web前端 &#x1f34e;励志…

其利天下技术居于32位MCU推出11万转无刷高速吹风筒方案--【高速吹风筒PCBA】

大家都知道高速吹风筒的兴起是因为戴森的产品体验&#xff0c;从另一角度赋予了吹风筒全新的产品形态和灵魂&#xff0c;于是产品有了智能和品质的体验感。 无刷电机的技术瓶颈在大家的共同努力下&#xff0c;从结构到驱动上都有了新的突破&#xff0c;所以近年来&#xff0c;高…

在疯狂三月之后,深入浅出分析AIGC的核心价值 (下篇)|【AI行研商业价值分析】

Rocky Ding 公众号&#xff1a;WeThinkIn 写在前面 【AI行研&商业价值分析】栏目专注于分享AI行业中最新热点/风口的思考与判断。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&#x1f4aa; 大家好&#xff0c;我是Rocky。 本文是《在疯狂三月之后&#xff0c;深…

openwrt-安装NGINX

openwrt-安装NGINX 介绍 OpenWrt 是一个用于嵌入式设备的开源操作系统。它基于 Linux 内核&#xff0c;并且主要被设计用于路由器和网络设备。 OpenWrt 的主要特点包括&#xff1a; 完全可定制&#xff1a;OpenWrt 提供了一个完全可写的文件系统&#xff0c;用户可以自定义设…