主頁 > 軟體設計 > 【c++】——STL容器之vector的使用和模擬實作

【c++】——STL容器之vector的使用和模擬實作

2021-09-23 13:55:48 軟體設計

目錄

1.vector的概述

2.vector常用介面

2.1 建構式

2.2 迭代器的使用:

2.3 修改的介面

push_back

pop_back

insert

erase

find

reverse

2.4 關于容量介面

resize

reverse

2.5 資料的訪問

3 vector的迭代器

迭代器失效的問題

4. vector的模擬實作

4.1reserve介面的實作

4.2 resize

4.3 insert

4.4 push_back

4.5 erase

4.6 pop_back

4.7 建構式


1.vector的概述

vector本質是資料結構中的線性表,它是動態空間的陣列,如果vector中的空間滿了以后,它會先開辟一塊更大的新空間,然后將舊空間的資料拷貝給新空間,再把舊空間的給釋放掉,vector開辟的新空間的容量一般是舊空間的容量的兩倍或者1.5倍,不同的編譯器增容方式可能是不同的,例如再g++中vector是以兩倍增長的,vs中vector是以1.5倍增長的,

vector可以儲存任意型別的資料,包括自定義型別,當定義vector的時候,需要指明vector存盤的資料是什么型別的,定義格式:

vector<型別> 名字;

	std::vector<int> v1;//v1是存盤int型別的資料
	std::vector<string> v2;//v2存盤的是string型別的資料
	std::vector<char> v3;//v3是存盤char型別的資料

2.vector常用介面

vector的介面有很多,在這里我就不一 一講解,我只講一些我們經常會用到的介面,如果遇到哪個介面不懂的話,自己可以去查一下檔案:vector - C++ Reference

2.1 建構式

vector無參的建構式
vector size_type n, const value_type& val = value_type()
構造并初始n個val
vector (const vector& x);
拷貝構造
vector (InputIterator fifirst, InputIterator last);
利用迭代器進行初始化構造
	std::vector<int> v1;//無參的建構式
	std::vector<int> v2(10, 2);//構造并初始化10個2
	std::vector<int> v3(v2.begin(), v2.end());//利用v2的迭代器初始化v3
	vector<int> v4(v2);//拷貝構造

2.2 迭代器的使用:

正向迭代器:begin+end 回傳的的型別是iterator/const_iterator

反向迭代器:rbegin+rend 回傳的型別是reverse_iterator/const_reverse_iterator

利用迭代器遍歷vector v1,v1中包含元素有 1 ,2 ,3,4,5

void test(vector<int> v)
{
	vector<int>::iterator it = v.begin();
	cout << "正向迭代器遍歷:";
	while (it != v.end())//正向迭代器遍歷
	{
		cout << *it << ' ';
		it++;
	}
	cout << endl;

	vector<int>::reverse_iterator rt = v.rbegin();
	cout << "反向迭代器遍歷:";
	while (rt != v.rend())//反向迭代器遍歷
	{
		cout << *rt << ' ';
		rt++;
	}	
	cout << endl;
}

輸出:

正向迭代器遍歷:1 2 3 4 5

反向迭代器遍歷:5 4 3 2 1

2.3 修改的介面

push_back 在末尾插入資料
pop_back 洗掉末尾的資料
insert 在position之前插入val
erase 洗掉position位置的資料
find 查找的某個資料的位置
operator[ ] 像陣列一樣去訪問vector
swap 與另一個vector進行交換
reverse 將vector中的資料進行逆置

push_back

void push_back (const value_type& val);

push_back介面的引數只有一個,它可以在vector的末尾插上一個資料,

pop_back

void pop_back();

pop_back介面沒有引數,它直接洗掉vector末尾的一個資料,

insert

insert有3種傳參的方式,

方式一:

iterator insert (iterator position, const value_type& val);

在position之前插入一個val,position是迭代器型別

方式二

void insert (iterator position, size_type n, const value_type& val);

在position之前插入n個val,positon是迭代器型別

方式三

template <class InputIterator>

void insert (iterator position, InputIterator first, InputIterator last);

position 和first,last都是迭代器型別,

將一個vector的[first,last)區間的資料插入到另一個相同型別的vector的position位置之前,

?

pisition不會隨著資料的移動而移動,

erase

erase有兩種傳參的方式:

iterator erase (iterator position);

方式一:洗掉position位置的資料、

iterator erase (iterator first, iterator last);

方式二:洗掉迭代器區間 [ first , lasr ) 中的元素,

find

template <class InputIterator, class T>

InputIterator find (InputIterator first, InputIterator last, const T& val);

在[ first , last )區間查找val,找到了就回傳相應的迭代器,找不到就回傳last,

find不是vector中的中的介面,是演算法中的函式,只要有迭代器都可以通過find進行查找

reverse

template <class BidirectionalIterator>

void reverse (BidirectionalIterator first, BidirectionalIterator last);

傳vector的迭代區間,將vector的迭代區間中的元素進行逆置,例如:將一個vector中1 2 3 4 5 進行逆置就成 5 4 3 2 1

	std::vector<int> v1;//無參的建構式
    v1.push_back(1);//尾插
	v1.push_back(2);//尾插
	v1.push_back(3);//尾插
	v1.push_back(4);//尾插
	v1.push_back(5);//尾插

	//查找3的位置,并將回傳的迭代器存盤在pos
	vector<int>::iterator pos = find(v1.begin(), v1.end(), 3);
	v1.insert(pos, 30);//在pos位置之前插入30
	reverse(v1.begin(), v1.end());//逆置vector
	//查找3的位置,并將回傳的迭代器存盤在it
	vector<int>::iterator it = find(v1.begin(), v1.end(), 4);
	v1.erase(it);//洗掉it位置的資料

2.4 關于容量介面

size 獲取資料個數
capacity 獲取容量的大小
empty 判斷vector是否為空
reserve 改變vector的capacity
resize

改變vector的size

resize


void resize (size_type n, value_type val = value_type());

使size到n個,如果不足本身的size不足n,則用val補齊vector到n個資料,如果本身的size大于n,則不需要進行任何操作,

reverse

void reserve (size_type n);

使vector有n個容量空間,如果原本的capacity大于n,則不會縮容,

	std::vector<int> v;
	cout << v.capacity() << endl;//輸出0
	cout << v.size() << endl;//輸出0
	v.reserve(10);//預留10個capacity的空間大小
	cout << v.capacity() << endl;//輸出10
	cout << v.size() << endl;//輸出0
	v.resize(20,10);//預留20個資料
	cout << v.capacity() << endl;// 輸出20
	cout << v.size() << endl;//輸出20

2.5 資料的訪問

operator[ ]可以像陣列下標去訪問vector中的元素
front回傳vector中的第一個資料
back返滬vector中最后一個資料

3 vector的迭代器

vector是一個連續的空間,它的迭代器就是原生指標,因為vector中的原生指標可以滿足迭代器 operator*,operator[ ],operator++,operator--,operator+=,operator-=的操作,所以vector的迭代器就只需要給原生指標起個別名就夠了,如下:

template<class T>
class vector
{
public:
typedef T* iterator; //vector的迭代器就是原生指標
typedef const T* const_iterator;

...

}

迭代器失效的問題

在我們用vector中,經常會碰到迭代器失效的問題,那么什么是迭代器失效呢?

我們先來看一段代碼,如下:

void test2()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(10);
	v.push_back(4);
    vector<int>::iterator pos = find(v.begin(), v.end(), 2);
	v.insert(pos,10);
	v.insert(pos, 20);
}

這段代碼在vs運行下會奔潰掉,為什么呢?

當我們洗掉掉2后,pos指向的位置的值就變為10,那么我們pos的意義也就改變了,此時的pos就迭代器就已經失效了,當我們再去使用它的時候,vs編譯器就檢查出來,

那么我再來看一下下面這個場景:

上面pos已經是野指標,因為舊空間被釋放掉所以不知道它指向的是什么值,所以該指標舊已經失效了,

所以迭代器失效有兩種方式:

一種是使用insert,erase使迭代器指向的數值發生改變,此時的迭代器就失去意義,這種有

些編譯器會檢查例如vs,有些編譯器不會檢查,例如g++

另一種是插入資料的時候,容量滿的時候會開辟新空間,舊空間被釋放,導致pos指向的資料

不知道是什么,此時的pos成了野指標,這個任何編譯器都會報錯,

4. vector的模擬實作

namespace sjp
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator; //vector的迭代器是可以修改的
		typedef const T* const_iterator;

        iterator begin()//回傳vector迭代區間的頭
		{
			return _first;
		}
		iterator end()//回傳vector的迭代區間的尾
		{
			return _end;
		}

		const_iterator begin()const
		{
			return _first;
		}

		const_iterator end()const
		{
			return _end;
		}

		size_t size()const//回傳vector的資料個數
		{
			return _end - _first;
		}

		size_t capacity()const//回傳vector的容量
		{
			return _end_of_storage - _first;
		}

        bool empty()const//判斷vector是否為空
		{
			return _first == _end;
		}

		const T& operator[](size_t i)const
		{
			return *(_first + i);
		}

		T& operator[](size_t i)
		{
			return *(_first + i);
		}

		void clear()//清空vector
		{
			_end = _first;
		}


		const T& back()const//回傳vector最后一個元素
		{
			return *(back - 1);
		}


		const T& front()const//回傳vector第一個元素
		{
			return *(front);
		}


	private:
		iterator _first;//表示目前使用空間的頭
		iterator _end;//表示目前使用空間的尾
		iterator _end_of_storage;//表示目前可用空間的尾
	};

在上面介面中,我們發現

1.有些介面在后面需要加上const,例如 empty ,size, capacity這些介面,因為呼叫這些介面的時候不會修改它的成員變數,所以我們加上const可以防止它的成員變數被修改,并且可以讓const物件和非const物件都可以呼叫這些介面(注意非const物件是可以呼叫const的介面,但const物件不能呼叫非const的介面

2.有些介面需要實作const和非const的版本,例如begin ,end,operator[]這些介面,

非const物件呼叫非const的介面,回傳的物件是可讀可寫的,const物件呼叫的是const的介面

回傳的物件是只能讀,例如,const物件回傳的也是const的迭代器,就是不能通過迭代器去修改它指向的值,

4.1reserve介面的實作

     void reserve(size_t n)
		{
			size_t sz = size();//先保存原本的size
			if (capacity() < n)
			{
				T* tmp = new T[n];//重新開一塊空間
				if (_first)//如果_first不為空指標
				{
					for (int i = 0; i < size(); i++)//將原空間的值拷貝給新空間
					{
						tmp[i] = _first[i];
					}
					delete[] _first;//釋放舊空間
				}
				//讓迭代器指向新空間
				_first = tmp;
				_end = _first + sz;
				_end_of_storage = _first + n;
			}
		}

這里有一個問題,上面的原空間的值拷貝給新空間中的:

for (int i = 0; i < size(); i++)
{
tmp[i] = _first[i];
}

可不可用memcpy(tmp, _first, sz*sizeof(T));來替代

memcpy進行的淺拷貝,當vector存盤的像string開辟動態空間的之類就會出錯

也就是說memcpy只能拷貝string中的指標,沒有將拷貝string的存盤字串的空間,當舊空間的中的存盤的指標被釋放掉后,同時指標指向的子符串也會被釋放掉,

那這段代碼為什么可以呢?

for (int i = 0; i < size(); i++)
{
tmp[i] = _first[i];
}

4.2 resize

		void resize(size_t n,T val=T())
		{
			if (n > size())
			{
				if (n > capacity())//如果預留資料個數大于容量則需要增容
				{
					reserve(n);
				}
				size_t sz = n - size();//將資料補齊到n個
				for (int i = 0; i < sz; i++)
				{
					push_back(val);
				}
			}
		}

如果n大于size的時候就插入val,再進行判斷,如果資料大于capacity的時候就需要進行增容,最后將val值補齊使vector的資料個數為n個,

4.3 insert

 		void insert(iterator pos,const T& x)
		{
			assert(pos >= _first && pos <= _end);
			if (_end == _end_of_storage)//判斷容量是否滿了
			{
				size_t lenth = pos - _first;//如果換新空間,需要保留pos在vector的位置
				int newcapacity = capacity() == 0 ? 5 : capacity() * 2;
				reserve(newcapacity);//預留新空間
				pos =_first+lenth;//跟新pos
			}
			//將x插入到pos位置的前面
			iterator cur = end();
			while (cur != pos)
			{
				*(cur) = *(cur-1);
				cur--;
			}
			*pos = x;	
			_end += 1;//資料個數再加一
		}

上面提到了insert迭代器會失效的問題,那么我們可不可以對insert適當修改一下使我們使用insert

不會發生迭代器失效的問題?

只需要在上面的代碼的基礎,在pos迭代器加上參考&,然后插入資料后,pos加1,這樣插入資料后,pos就可以一直指向原本那個資料,

4.4 push_back

		void push_back(const T& x)//尾插,直接在最后一個位置插入資料即可
		{
			insert(_end, x);
			//if (_end == _end_of_storage)
			//{
			//	int newcapacity = capacity() == 0 ? 5 : capacity() * 2;
			//	reserve(newcapacity);
			//}
			//*_end = x;
			//++_end;
		}

4.5 erase

		iterator erase(iterator pos)
		{
			assert(pos < _end);	
			iterator cur = pos;//將pos位置后的所有資料向前挪一步
			while (cur != _end - 1)
			{
				*cur = *(cur + 1);	
				cur++;
			}
			_end--;//資料個數再減一
			return pos;
		}

4.6 pop_back

		void pop_back()
		{
			--_end;
		}

4.7 建構式

		vector(size_t n, T val)//構造n個val值的vector
		{
			reserve(n);//先預留n個資料的空間
			for (int i = 0; i < n; i++)//再將val存滿這塊空間
			{
				push_back(val);
			}
		}

		vector()//無參的拷貝構造
		 :_first(nullptr),_end(nullptr),_end_of_storage(nullptr)
		{

		}

        vector(iterator first, iterator end)//利用迭代器區間構造vector
			:_first(nullptr), _end(nullptr), _end_of_storage(nullptr)
		{
			while (first != end)
			{
				push_back(*first);
				first++;
			}
		}

        //v2(v1);
		vector(const vector<T>& v)//拷貝建構式
			:_first(nullptr),_end(nullptr),_end_of_storage(nullptr)
		{
			reserve(v.capacity());//預留v1相同的空間
			for ( auto e: v)//然后將v1中的資料一個一個的推進v2
			{
				push_back(e);
			}
		}

        //v2=v1
		vector<T>& operator=(const vector<T>& v)//賦值建構式
		{
			vector<T> tmp(v);
			swap(_first, tmp._first);//不能用用=賦值進行賦值,tmp出函式作業域或被析構掉,
			swap(_end, tmp._end);
			swap(_end_of_storage, tmp._end_of_storage);
			return *this;
		}

v1=v2,將v1賦值給v2,需要將v1的空間大小和值跟v2是一模一樣的,在賦值程序中,先拷貝構造一個跟v1一模一樣的tmp,然后將tmp和v2中_first,_end, _end_of_storage交換過去,出函式作用域的時候,tmp會被解構式給釋放掉,此時v1的空間大小和值跟v2是一模一樣的,

總結:在上面中的push_back,pop_back,insert,erase,clear等介面中在后面不需要加上const,因為const物件本身不能被修改的,const的vector中的資料個數和資料都不能被改變,所以說const物件不能呼叫這些介面,

好了,今天的知識就分享到這里,喜歡的小伙伴們可以給博主點個贊 ,或者點個關注,大家一起努力學習,共同進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/302281.html

標籤:其他

上一篇:RabbitMQ 中的訊息會過期嗎?

下一篇:破解近 200 萬部 AT&T 手機,一男子被美國判處 12 年監禁

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more