设计模式(2)创造型设计模式

news2024/11/26 12:38:13

创建型模式

  • 创建型模式
      • 1.工厂模式
          • 1.1 抽象工厂模式(Abstract factory)
          • 1.2 工厂方法模式(Factory Method)
          • 1.3 简单工厂模式(Simple Factory)
      • 2. 建造者模式(Builder)
      • 3. 原型模式(Prototypes)
      • 4. 单例模式
      • 5. 创建型模式之间的联系和区别

创建型模式

前提:为一个电脑游戏创建一个迷宫,忽略迷宫的诸多细节,仅仅关注迷宫是怎样被创建的。

定义:将迷宫定义为一系列房间(Room),房间的四面要么是一堵墙(Wall),要么是一扇门(Door)。

//房间四个面
enum Direction{ North, South, East, West};
//房间
class Room{...}
//墙
class Wall{...}
//门
class Door{...}
//迷宫
class Maze{...}
//迷宫游戏
class MazeGame{...}

一个简单的迷宫创建函数,如下:

Maze* MazeGame::CreateMaze()
{
	Maze *aMaze = new Maze;
	Room *r1 = new Room(1);
	Room *r2 = new Room(2);
	Door *dr = new Door(r1,r2);
	aMaze->addRoom(r1);
	aMaze->addRoom(r2);
	r1->setSide(North, new Wall);
	r1->setSide(South, dr);
	r1->setSide(East, new Wall);
	r1->setSide(West, new Wall);
	r2->setSide(North, new Wall);
	r2->setSide(North, new Wall);
	r2->setSide(North, new Wall);
	r2->setSide(North, dr);
	return aMaze;
}

这个函数的缺点在于: 对迷宫布局硬编码,改变布局意味着需要改变这个函数本身,容易产生错误,且不利于重利用。试想一下,重用该迷宫的布局,但是迷宫中的部件和来原来不一致了,例如现在的门是施了魔法的,需要咒语才能开启等等。在这种情况下,改变的最大障碍就是对被实例化的类进行硬编码。

创建型模型提供了多种不同方法从实例化它们的代码中除去对这些具体类的显示引用:

  1. 如果CreateMaze调用虚函数而不是显式构造来创建它需要的房间、门和墙壁;那么可以通过创建一个MazeGame的子类并重定义这些虚函数,从而改变被实列化的类。正如工厂方法模式
  2. 如果传递一个对象给CreateMaze作参数来创建房间、墙壁和门,那么可以通过传递不同的参数来改变这些部件的类。正如抽象工厂模式
  3. 如果传递一个对象给CreateMaze,这个对象可以在它所建造的迷宫中增加房间、墙壁和门的操作,来创建一个新的迷宫。那么可以通过继承当方式来改变迷宫被建造的方式,正如建造者模式
  4. 如果CreateMaze由多种原型的房间、墙壁和门对象参数化,它拷贝并将这些对象增加到迷宫中。正如原型模式
  5. 单例模式可以保证每个游戏中仅有一个迷宫存在,而且所有的游戏对象都可以迅速的访问它。

1.工厂模式

工厂模式定义:
工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种创建对象的接口,而无需指定它们具体的类,实例化的类是哪一个由子类决定。工厂模式将对象的实例化过程封装在一个工厂类中,使得客户端代码与具体类解耦,提供了一种灵活、可扩展的对象创建机制。

工厂模式的核心思想是将对象的创建过程封装在工厂类中,客户端代码通过与工厂类进行交互来获取所需的对象,而不需要直接实例化具体产品类。这种解耦的设计使得客户端代码更加灵活,可以通过切换具体工厂类来创建不同的产品对象。

工厂模式有以下几种常见的变体:

  1. 简单工厂模式(Simple Factory Pattern):使用一个单独的工厂类来创建所有的产品对象,通过传递不同的参数给工厂方法来选择创建哪种产品
  2. 工厂方法模式(Factory Method Pattern):每个具体产品都有对应的工厂类,客户端通过调用具体工厂类来创建具体产品对象
  3. 抽象工厂模式(Abstract Factory Pattern):提供一个抽象工厂接口,具体工厂类实现该接口并负责创建一系列相关或相互依赖的产品对象(把一系列工厂方法归结到一起)
1.1 抽象工厂模式(Abstract factory)

抽象工厂结构图:
在这里插入图片描述

在抽象工厂模式中,通常有以下几个角色:
抽象工厂(Abstract Factory):定义了创建产品的接口,包含了创建产品的抽象方法。
具体工厂(Concrete Factory):实现了抽象工厂接口,负责实际创建具体产品的对象。
抽象产品(Abstract Product):定义了产品的接口,是具体产品类的共同父类或接口。
具体产品(Concrete Product):实现了抽象产品接口,是工厂模式所创建的对象。

用抽象工厂来实现迷宫创建,代码如下:

class MazeFactory
{
	virtual Maze *MakeMaze(){return new Maze;}
	virtual Wall *MakeWall(){return new Wall;}
	virtual Room *MakeRoom(int n){return new Room(n);}
	virtual Door *MakeDoor(Room* r1, Room* r2){return new Door(r1,r2);}
}
//建造迷宫的程序使用MazeFactory作为参数,程序便能指定创建的房间、门、墙壁类型
Maze* MazeGame::CreateMaze(MazeFactor& factory)
{
	Maze *aMaze = factory.MakeMaze();
	Room *r1 = factory.MakeRoom(1);
	Room *r2 = factory.MakeRoom(2);
	Door *dr = factory.MakeDoor(r1,r2);
	aMaze->addRoom(r1);
	aMaze->addRoom(r2);
	r1->setSide(North, factory.MakeWall());
	r1->setSide(South, dr);
	r1->setSide(East, factory.MakeWall());
	r1->setSide(West, factory.MakeWall()l);
	r2->setSide(North, factory.MakeWall());
	r2->setSide(North, factory.MakeWall());
	r2->setSide(North, factory.MakeWall());
	r2->setSide(North, dr);
	return aMaze;
}
//创建一个MazeFactory的子类EnchanteMazeFactory,这是一个创建了施加魔法的迷宫工厂,EnchanteMazeFactory将重定义不同的成员函数并返回Room、Wall等不同的子类
class EnchanteMazeFactory : public MazeFactory
{
	...
}
//创建迷宫
MazeGame game;
EnchanteMazeFactory  factory;
game.CreateMaze(factory);
1.2 工厂方法模式(Factory Method)

工厂方式模式定义:
定义一个用于创建对象的接口,让子类决定实例化具体的类。Factory Method使一个类的实例化延迟到其子类中。

工厂方法结构图,如下:
在这里插入图片描述
适用性:

  • 当一个类不知道它所必须创建的对象的类的时候。
  • 当一个类希望由它的子类来指定它所创建的对象的时候。

工厂方法的一个潜在问题是它们可能为了创建适当的Product对象而迫使你创建Creator的子类,在c++种可以通过模板解决这种问题,如下:

class Creator
{
	virtual Product* CreateProduct() = 0 ;
}

template <class TheProduct>
class StanderdCreator : public Creator
{
	virtual Product* CreateProduct();
}
template <class TheProduct>
Product* StanderdCreator<TheProduct>::CreateProduct()
{
	return new TheProduct;
}
//使用这个模板,客户只需要提供产品类
class MyProduct : public Product
{
	...
}
//使用
StanderdCreator<MyProduct> mycreator;

用工厂方法模式来实现迷宫创建,代码如下:

class MazeGame()
{
	Maze * CreateMaze();
	//工厂方法,推迟到子类中实现
	virtual Maze* makeMaze(){ return new Maze; }
	virtual Room* makeRoom(int n){ return new Room(n); }
	virtual Wall* makeWall(){ return new Wall; }
	virtual Door* makeDoor(Room* r1, Room* r2){ return new Door(r1,r2); }
}

Maze* MazeGame::CreateMaze()
{
	Maze *aMaze = makeMaze();
	Room *r1 = makeRoom(1);
	Room *r2 = makeRoom(2);
	Door *dr = makeDoor(r1,r2);
	aMaze->addRoom(r1);
	aMaze->addRoom(r2);
	r1->setSide(North, makeWall());
	r1->setSide(South, dr);
	r1->setSide(East, makeWall());
	r1->setSide(West, makeWall());
	r2->setSide(North, makeWall());
	r2->setSide(North, makeWall());
	r2->setSide(North, makeWall());
	r2->setSide(North, dr);
	return aMaze;
}

//不同的游戏可以创建MazeGame子类以特别指明一些迷宫的部件,MazeGame子类可以重定义所有或者部分工厂方法以指定产品中的变化,如下
class BombedMazeGame : public MazeGame
{
	virtual Wall* makeWall(){ return new BombedWall; }
	virtual Room* makeRoom(int n){ return new RoomWithABomb(n); }
}
1.3 简单工厂模式(Simple Factory)

简单工厂模式定义:也称为静态工厂模式,是一种创建型设计模式,它通过一个工厂类来封装对象的创建过程,根据客户端的请求返回不同的具体对象。简而言之就是在实现过程中通过指定参数来创建相应的产品。

class Creator
{
	virtual Product* Create(ProductId id)
	{
		if(id == MINE) return new MyProduct;
		if(id == YOURS) return new YoursProduct;
		return 0;
	}
}
//子类可以重写Product,并引入新的标识
class MyCreator : public Creator
{
	virtual Product* Create(ProductId id)
	{
		if(id == MINE) return new YoursProduct;
		if(id == YOURS) return new MyProduct;
		if(id == THRIRS) return new ThierProduct;
		return Creator::Create(id);
		return 0;
	}
}

2. 建造者模式(Builder)

建造者模式的定义:将一个复杂对象的构建与其表示(定义)分离,使得同样的构建过程可以创建不同的表示。
建造者模式的核心思想是将一个复杂对象的构建过程分解为多个简单的步骤,每个步骤由具体建造者来实现。通过指挥者将这些步骤按照一定的顺序组合起来,最终构建出一个完整的复杂对象。这样,客户端代码只需要与指挥者进行交互,而无需关心具体的构建过程和细节。

建造者模式适用于以下情况:

  • 当需要创建的对象具有复杂的内部结构,且内部部件的构建顺序和组合方式不稳定或多变时。
  • 当需要创建的对象的配置选项较多,构造函数参数过多且难以维护时。
  • 当希望通过一种统一的方式构建不同表示的对象时。

建造者模式结构图:
在这里插入图片描述
用建造者模式来实现迷宫创建,代码如下:

//MazeBuilder类定义下面的接口来创建迷宫
class MazeBuilder
{
	//复杂对象的构建过程分解为多个简单的步骤,每个步骤由具体建造者来实现
	virtual void BuildMaze(){}
	virtual void BuildRoom(int n){}
	virtual void BuildDoor(int roomFrom, int rootTo){}
	virtual Maze* GetMaze(){return 0;}
};

Maze* MazeGame::CreateMaze(MazeBuilder& builder)
{
	builder.BuildMaze();
	builder.BuildRoom(1);
	builder.BuildRoom(2);
	builder.BuildDoor(1,2);
	return builder.GetMaze();
}
//子类StandarMazeBuilder实现了简单迷宫的创建
class StandarMazeBuilder : public MazeBuilder
{
	...
}
//创建迷宫
Maze * maze;
MazeGame game;
StandarMazeBuilder  builder;
maze = game.CreateMaze(builder);

3. 原型模式(Prototypes)

原型模式定义:原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有对象来创建新的对象,而无需通过调用构造函数来创建。原型模式基于对象的克隆来创建新的对象,可以避免重复创建相似对象的开销。

原型模式的优点包括:

  • 可以避免重复创建相似对象的开销,提高创建对象的效率。
  • 可以通过克隆来动态地创建对象,无需依赖具体类。
  • 可以在运行时动态添加和删除原型对象。

原型模式的主要缺陷:每一个Protoypes子类都必须实现Clone操作,当类已经存在时就难以新增Clone操作,或当内部包括一些不支持拷贝或由循环引用的对象时,实现克隆可能会很困难。

原型模式特别适用于以下情形:

  • 创建一个对象需要消耗的资源较多,如数据读取、硬件访问等,可以通过原型复制来提高性能
  • 系统需要大量相同或相似对象(例如,克隆已有对象,改变值以指定新对象)的时候,可通过复制原型的方式来减少创建对象的开销
  • 对象的状态满足上述描述,并且状态需要持续变化的场景中,可以选择原型模式。

原型模式结构图,如下:
在这里插入图片描述
当实现原型时,可以考虑下面一些问题:

  1. 使用一个原型管理器。使用一个注册表存储和检索原型。在克隆一个原型前向注册表请求该原型。原型管理器是一个关联存储器,它返回一个与给定关键字相匹配的原型。
  2. 原型需要实现clone操作。
  3. 原型clone后的初始化操作。

用原型模式来实现迷宫创建(相关类声明在抽象工厂章节),代码如下:

class MazePrototypeFactory : public MazeFactory
{
	MazePrototypeFactory(Maze* m, Wall* w, Room* r, Door* d)
	{
		_prototypeMaze = m;
		_prototypeRoom = r;
		_prototypeWall = w;
		_prototpyeDoor = d;
	}
	virtual Maze *MakeMaze(){return _prototypeMaze->clone();}
	virtual Wall *MakeWall(){return _prototypeWall->clone();}
	virtual Room *MakeRoom(int n)
	{
		Room* r = _prototypeRoom->clone();
		r->init(n);
		return r;
	}
	virtual Door *MakeDoor(Room* r1, Room* r2)
	{
		Door* d = _prototpyeDoor->clone();
		d->init(r1,r2);
		return d;
	}
	
	Maze* _prototypeMaze;
	Room* _prototypeRoom;
	Wall* _prototypeWall;
	Door* _prototpyeDoor;
}

//创建迷宫
MazeGame game;
MazePrototypeFactory factory(new Maze, new Wall, new Room, new Door);
Maze * maze = game.CreateMaze(factory);

4. 单例模式

单例模式定义:单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供了一个全局访问该实例的入口点。

单例模式优点:

  • 提供了对唯一实例的全局访问点,方便其他类使用该实例。
  • 避免了重复创建对象的开销,节省了系统资源。
  • 确保了对象的一致性,因为只有一个实例存在。

单例模式的两种实现:

  • 懒汉模式

    class Singletion;
    Singletion* Singletion::sing = NULL;
    class Singletion
    {
    public:
    	//方式1
    	static Singletion *creat_singletion()
    	{
    		if (!sing)
    		{
    			lock();
    			if(!sing)
    			{
    				sing = new Singletion();
    			}
    			unlock();
    		}
    		return sing;
    	}
    	//由于双检锁失败的原因,这里提供方式2
    	static Singletion& create_singletion1()
    	{
    		static Singletion sing1;
    		return sing1
    	}
    	void task()
    	{
    		cout << "singtion task ..." << endl;
    	}
    private:
    	Singletion();
    	Singletion(Singletion&);
    	Singletion(Singletion&&);
    	Singletion& operator=(const Singletion&);
    	static Singletion *sing;
    
    //添加无智能指针时删除https://www.cnblogs.com/ring1992/p/9592817.html
    }
    //单例模板https://www.cnblogs.com/sunchaothu/p/10389842.html
    
  • 饥汉模式

    class Singletion
    {
    public:
    	Singletion* get_instance()
    	{
    		return sing;
    	}	
    	void task ()
    	{
    		//task
    	}
    private:
    	Singletion();
    	Singletion(Singletion&);
    	Singletion(Singletion&&);
    	Singletion& operator=(const Singletion&);
    	static Singletion *sing;
    }
    Singletion* Singletion::sing = new Singletion();
    

5. 创建型模式之间的联系和区别

  1. Abstract Factory和Builder相似,两者都可以创建复杂的对象。主要的区别是builder模式着重于一步一步构造一个复杂对象,而Abstract Factory着重于多个系列的产品对象。
  2. Abstract Factory模式可以通过Factory Method模式或者Builder模式来实现。
  3. Prototype和Abstract Factory模式在某种方面是相互竞争的,但是它们也可以一起使用。Abstract Factory可以存储一个被克隆的原型集合,并且通过集合返回大量对象。
  4. 在一个框架系统中,用一个系统创建的抽象类对系统进行参数化(CreateMaze函数)的方式有两种:
    a.生成创建对象的子类,比如工厂方法模式,这种方法的缺点在于,如果要改变产品类,就需要创建一个新的子类。
    b.定义一个对象负责明确产品对象的类,并将它作为该系统的参数,比如抽象工厂、原型模式、建造者模式。抽象工厂由这个工厂对象产生多个类的对象;建造者由这个工厂对象使用一个复杂协议逐步创建一个复杂产品;原型模式由该工厂对象通过拷贝原型对象来创建产品。

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

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

相关文章

【Spring Boot 源码学习】深入 ApplicationArguments 接口及其默认实现

《Spring Boot 源码学习系列》 深入 ApplicationArguments 接口及其默认实现 一、引言二、主要内容2.1 ApplicationArguments2.2 DefaultApplicationArguments2.2.1 成员变量2.2.2 构造方法2.2.3 成员方法 2.3 SimpleCommandLinePropertySource2.4 应用场景2.4.1 准备和配置应用…

基于FPGA的音视频监视器,音视频接口采集器的应用

① 支持1路HDMI1路SDI 输入 ② 支持1路HDMI输出 ③ 支持1080P高清屏显示实时画面以 及叠加的分析结果 ④ 支持同时查看波形图&#xff08;亮度/RGB&#xff09;、 直方图、矢量图 ⑤ 支持峰值对焦、斑马纹、伪彩色、 单色、安全框遮幅标记 ⑥ 支持任意缩放画面&#xff0c;支…

【Java EE】数据库连接池详解

文章目录 &#x1f38d;数据库连接池&#x1f338;Hikari&#x1f338;Druid &#x1f340;MySQL开发企业规范⭕总结 &#x1f38d;数据库连接池 在上⾯Mybatis的讲解中,我们使⽤了数据库连接池技术,避免频繁的创建连接,销毁连接 下⾯我们来了解下数据库连接池 数据库连接池负…

如何利用代理IP进行SEO优化?

“SEO”这个词相信对于做在线业务的朋友来说一定不陌生。 在网络营销中&#xff0c;SEO是至关重要的一环&#xff0c;对于增加有机流量、提升品牌知名度、增加网站的信任度和权威性非常有效。而代理IP在SEO优化中有着不可或缺的作用&#xff0c;它可以帮助网站管理员和SEO专家…

[muduo网络库]——muduo库的Reactor模型(剖析muduo网络库核心部分、设计思想)

一、前言 在学习 C 服务端的过程中&#xff0c;必不可少的一项就是熟悉一个网络库&#xff0c;包括网络库的应用和其底层实现。我们熟知的网络库有 libevent、libev、muduo、Netty 等&#xff0c;其中 muduo 是由陈硕大佬个人开发的 TCP 网络库&#xff0c;最近跟着课程正在深…

回炉重造java----单列集合

体系结构: 集合主要分为两种&#xff0c;单列集合collection和双列集合Map&#xff0c;区别在于单列集合一次插入一条数据&#xff0c;而双列的一次插入类似于key-value的形式 单列集合collection 注:红色的表示是接口&#xff0c;蓝色的是实现类 ①操作功能: 增加: add()&am…

上亿用户面临风险!小米、WPS等知名安卓应用竟藏有“文件覆盖”漏洞

Google Play商店中的几款热门安卓应用程序容易受到与路径遍历相关的漏洞攻击&#xff0c;该漏洞的代号为“Dirty Stream”攻击&#xff0c;恶意应用程序可能会利用此漏洞覆盖易受攻击的应用程序主目录中的任意文件。 微软威胁情报团队的Dimitrios Valsamaras在周三发布的一份报…

【最新点云数据增强综述】深度学习点云数据增强技术的进展

深度学习(DL)已成为点云分析任务(如检测、分割和分类)的主流和有效方法之一。为了减少深度学习模型训练过程中的过拟合,提高模型性能,尤其是在训练数据的数量和/或多样性有限的情况下,增强往往至关重要。虽然各种点云数据增强方法已被广泛应用于不同的点云处理任务中,但…

9.为什么有时候会“烫烫烫”——之函数栈桢

目录 1. 什么是函数栈帧 2. 理解函数栈帧能解决什么问题呢&#xff1f; 3. 函数栈帧的创建和销毁解析 3.1 什么是栈&#xff1f; 3.2 认识相关寄存器和汇编指令 3.3 解析函数栈帧的创建和销毁 小知识&#xff1a;烫烫烫~ Q&A 1. 什么是函数栈帧 我们在写C语言代码…

2024 年 数维杯(A题)大学生数学建模挑战赛 | 多源机会信号建模| 数学建模完整代码+建模过程全解全析

2024数维杯数学建模A题B题C题思路模型代码&#xff08;开赛后第一时间更新&#xff09;及时留意关注哦 https://mbd.pub/o/bread/ZpWakpdq https://mbd.pub/o/bread/ZpWakpdq 2024数维杯数学建模A题B题C题思路模型代码&#xff08;开赛后第一时间更新&#xff09;及时留意关注…

leetcode63.跳跃游戏2(动态规划)

问题描述&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物…

vue项目中使用websocke即时通讯实现系统公告实时获取并提醒

一、使用场景 发布者设置需要发布的公告内容、公告接收用户和发布时间&#xff0c;到达发布时间时及时通知提醒已登录系统用户&#xff0c;使用websocke来实现前端与服务器保持长连接&#xff0c;以便实时过去公告信息。 WebSocket是一种在单个TCP连接上进行全双工通信的协议…

17.Blender RC大佬EEVEE皮肤节点预设导入

如何添加节点预设 在底下的左下角打开Geometry Node Editor 选中正方体&#xff0c;点击新建 当鼠标指针在两个模块之间&#xff0c;是十字的样子时 可以拖出一个新的板块 然后打开文件浏览器 找到节点预设然后拖入到底下的节点编辑界面就可以了或者是blend文件&#xf…

微信小程序流量主如何自定义广告组件后台控制广告显示方式附源码[收藏]

最近开发了一个微信小程序&#xff0c;开通了流量主&#xff0c;引用广告显示。本教程干货满满&#xff0c;附上代码&#xff0c;建议**【收藏点赞】** 微信小程序广告有以下几种&#xff1a;Banner广告、激励广告、插屏广告、视频广告、视频贴片广告、封面广告。 为了增加广告…

pycharm如何对for循环中第n次循序执行断点

目录 在 PyCharm 中&#xff0c;您可以设置条件断点来实现这个功能&#xff0c;这样只有在满足特定条件时断点才会被触发。以下是设置仅在 for 循环的第 n 次迭代时触发断点的步骤&#xff1a; 设置断点&#xff1a; 首先&#xff0c;找到您想要在 for 循环中设置断点的行。点击…

找最大数字-第12届蓝桥杯国赛Python真题解析

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第60讲。 找最大数字&#…

【C++】C/C++中新const用法:const成员

欢迎来到CILMY23的博客 本篇主题为&#xff1a; C/C中新const用法&#xff1a;const成员 个人主页&#xff1a;CILMY23-CSDN博客 系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux 感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞…

如何设置海外虚拟IP的地址?

经济全球化发展&#xff0c;需要使用到海外ip的场景越来越多&#xff0c;比如跨境电商、海外投放、市场调研等等。海外虚拟ip地址已经成为了个人和企业不可或缺的工具。那么作为用户&#xff0c;该如何设置海外虚拟IP的地址&#xff1f; 设置海外IP的方式有以下几种&#xff1a…

栈结构(c语言)

1.栈的概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈&am…

Day2:调节屏幕驱动

Day2调节屏幕驱动 原理图&#xff1a; 要想调节屏幕驱动