因?yàn)楹?jiǎn)書(shū)字?jǐn)?shù)限制,完整版地址:https://www.zybuluo.com/hainingwyx/note/609905
如有錯(cuò)誤,煩請(qǐng)指正!
第11章 對(duì)象數(shù)組
11.1 如何把對(duì)象串接成數(shù)組
串接:使用方括號(hào)[]把已有的變量組合起來(lái),使其成為一個(gè)數(shù)組。使用這種方式構(gòu)造的對(duì)象數(shù)組,適用于對(duì)象數(shù)量比較少的情況。對(duì)objArray中對(duì)象元素的訪問(wèn)和普通數(shù)組中元素的訪問(wèn)是一樣的。在此基礎(chǔ)上使用點(diǎn)+屬性名稱的語(yǔ)法,可以訪問(wèn)對(duì)象元素的屬性。
objArray=[b1 b2 b3];
objArray(1).a=10;
11.2 如何直接聲明對(duì)象數(shù)組
自動(dòng)生成一個(gè)1*10的數(shù)組,并把第10個(gè)元素置為1,其余為沒(méi)有被賦予初值的元素,用0作為其初值。
array(1,10)=1;
對(duì)象擴(kuò)展:objArray(1,10)=Square(5);
MATLAB解釋器會(huì)把這個(gè)命令翻譯成如下指令:對(duì)第10個(gè)元素調(diào)用Square(5);其余的1-9個(gè)元素調(diào)用缺省的構(gòu)造函數(shù)。缺省的構(gòu)造函數(shù)只被調(diào)用一次,產(chǎn)生了一個(gè)對(duì)象,其余的都是直接拷貝對(duì)象。調(diào)用缺省的構(gòu)造函數(shù)說(shuō)明函數(shù)要考慮輸入0參數(shù)的情況。在此擴(kuò)展的對(duì)象數(shù)組是handle類(lèi)的,盡管其內(nèi)部數(shù)據(jù)的數(shù)值相同,但如果直接比較被拷貝的元素,它們的handle仍然是不同的。
注意Value類(lèi)對(duì)象沒(méi)有定義==運(yùn)算符,所以為了比較兩個(gè)對(duì)象,需要重載==(eq)運(yùn)算符。
11.3 如何使用findobj尋找特定的對(duì)象
首先使用串接語(yǔ)法,構(gòu)造一個(gè)對(duì)象數(shù)組。然后使用邏輯‘-and’或者‘-or’關(guān)鍵詞,在findobj函數(shù)中查找指定對(duì)象。
11.4 如何利用Cellarray把不同類(lèi)的對(duì)象組合到一起
MATLAB規(guī)定對(duì)象數(shù)組中元素的種類(lèi)必須保持一致,如果不一致,matlab就會(huì)嘗試把一個(gè)對(duì)象轉(zhuǎn)換成另一個(gè),如果找不到可以使用的對(duì)象轉(zhuǎn)換函數(shù),MATLAB就會(huì)報(bào)錯(cuò)。最簡(jiǎn)單的解決辦法就是使用元胞數(shù)組(Cell Array),元胞數(shù)組是MATLAB中專門(mén)用來(lái)存放不同種類(lèi)數(shù)據(jù)的工具。例如:
o1=Square();
o2=Circle();
oCell={o1,o2}
oCell{1}.a%訪問(wèn)CellArray中的一個(gè)元素
使用Cell取代array,簡(jiǎn)單實(shí)用,但是沒(méi)有辦法利用向量化式地方式集中訪問(wèn)數(shù)組中對(duì)象內(nèi)部的元素。
11.5 什么是轉(zhuǎn)換函數(shù)
定義:一種負(fù)責(zé)把該類(lèi)的對(duì)象轉(zhuǎn)換成其他類(lèi)的對(duì)象的一種類(lèi)的方法。
只需要在該類(lèi)中定義轉(zhuǎn)換函數(shù),則調(diào)用的時(shí)候就能完成轉(zhuǎn)換。轉(zhuǎn)換函數(shù)只需要調(diào)用轉(zhuǎn)換對(duì)象的Constructor。
11.6 如何利用轉(zhuǎn)換函數(shù)把不同類(lèi)的對(duì)象組合到一起
轉(zhuǎn)換函數(shù)一般是隱式轉(zhuǎn)換。假設(shè)數(shù)組的第一個(gè)為Square對(duì)象,則第二個(gè)賦值時(shí)需要檢查,如果不相同,則需調(diào)用第二個(gè)對(duì)象的轉(zhuǎn)換函數(shù)。如果沒(méi)有定義轉(zhuǎn)換函數(shù),MATLAB會(huì)直接把第二個(gè)對(duì)象作為參數(shù)提供給square的構(gòu)造函數(shù)。如果無(wú)法處理,MATLAB會(huì)報(bào)錯(cuò)。
11.7 如何用非同類(lèi)(Heterogeneous)數(shù)組盛放不同類(lèi)對(duì)象
11.7.1 為什么需要Heterogeneous數(shù)組
轉(zhuǎn)換函數(shù)把不同類(lèi)型的對(duì)象組合到一起,并且不改變對(duì)象的類(lèi)型。
使用Heterogeneous需要兩個(gè)類(lèi)具有共同的父類(lèi),并且父類(lèi)繼承自一個(gè)叫做Heterogeneous的基類(lèi)。
基類(lèi)聲明:
classdef Shape2D<handle&matlab.mixin. Heterogeneous
end
優(yōu)點(diǎn):
- 不用定義convert函數(shù),不存在對(duì)象之間的相互轉(zhuǎn)換;
- 構(gòu)造出的數(shù)組可以存放共同基類(lèi)的對(duì)象;
- 可以使用數(shù)組的下標(biāo)語(yǔ)法,向量化訪問(wèn)對(duì)象的共同特征;
- 可以使用對(duì)象的共同方法,必須是Sealed。
11.7.2 含有不同類(lèi)對(duì)象的數(shù)組類(lèi)型
包含有不同對(duì)象的數(shù)組類(lèi)型,總是取對(duì)象們最近的共同父類(lèi)。
11.7.3 使用Heterogeneous要避免哪些情況
1、沒(méi)有除Heterogeneous之外的共同的父類(lèi)。
2、多重繼承存在交叉繼承,這時(shí)候也不能將子類(lèi)的對(duì)象放到一個(gè)對(duì)象數(shù)組中去。
11.7.4 如何向量化遍歷數(shù)組中對(duì)象的屬性
如果用Dot語(yǔ)法訪問(wèn)數(shù)組中對(duì)象的共同屬性,返回的結(jié)果將是一個(gè)用都好分隔的list。
11.7.5 如何設(shè)計(jì)成員方法使其支持向量化遍歷
s=objArray.area
objArray被當(dāng)做一個(gè)參數(shù)傳入area方法中。
如果是HeterogeneousArray,想要支持向量化訪問(wèn)的成員方法,必須將其聲明成sealed,禁止子類(lèi)中有不一致的定義。
對(duì)象數(shù)組是否可以向量化調(diào)用destructor?
destructor禁止定義成Sealed,否則子類(lèi)資源可能無(wú)法釋放。但是MATLAB對(duì)delete方法仍支持使用objArray.delete的格式調(diào)用對(duì)象們的析構(gòu)函數(shù)。MATLAB并沒(méi)有向量化地調(diào)用對(duì)象們的析構(gòu)函數(shù),因?yàn)楦静淮嬖谶@樣一個(gè)共同的delete方法。objArray.delete這里為:逐個(gè)調(diào)用每個(gè)對(duì)象的析構(gòu)函數(shù)。
第12章 類(lèi)的運(yùn)算符重載
12.1 理解MATLAB的subsref和subsasgn函數(shù)
12.1.1 MATLAB如何處理形如a(1,:)的表達(dá)式
A(1:2,:)會(huì)被MATLAB解釋器轉(zhuǎn)換成一個(gè)subsref的函數(shù)調(diào)用。該函數(shù)的第一個(gè)參數(shù)是要訪問(wèn)的數(shù)據(jù)A;第二個(gè)參數(shù)是要訪問(wèn)元素所在的位置,并且該位置信息存放在一個(gè)結(jié)構(gòu)體中。subsref(A,s);例如A(1:2,:),這里s.type=’()’;s.subs={1:2,’:’};也可以通過(guò)以下方法訪問(wèn)數(shù)組元素:
s.type=’()’;
s.subs={1:2,’:’};
subsref(A,s);
對(duì)數(shù)組元素的賦值會(huì)被Interpreter轉(zhuǎn)換成一個(gè)subsasgn的函數(shù)調(diào)用,例如:
A(1,1)=0;被轉(zhuǎn)換成subsasgn(A,s,0),其中s是一個(gè)結(jié)構(gòu)體,
可以通過(guò)以下實(shí)現(xiàn)A(1,1)=0:
s.type=’()’;
s.subs={1,1};
subsasgn(A,s,0);
12.1.2 MATLAB如何處理形如a{1,:}的表達(dá)式
對(duì)元胞數(shù)組B第一列的訪問(wèn)B{:,1}將會(huì)被Interpreter轉(zhuǎn)換成如下的subsref函數(shù)調(diào)用:
s.type=’{}’;
s.subs={‘:’,1};
subsref(B,s);
對(duì)元胞數(shù)組B的第一個(gè)元胞的賦值:
B{1,1}=0;將被MATLAB轉(zhuǎn)換成如下subsasgn函數(shù)調(diào)用。
s.type=’{}’;
s.subs={1,1};
subsasgn(B,s,0);
12.1.3 MATLAB如何處理形如s.f的表達(dá)式
對(duì)struct的訪問(wèn)和賦值也可以直接通過(guò)直接調(diào)用內(nèi)置函數(shù)來(lái)完成。
days.f1和以下等價(jià)
s.type=’.’;
s.subs={‘f1’};
subsref(days,s);
days.f3=’NULL’ 和以下等價(jià)
s.type=’.’;
s.subs={‘f3’};
subsref(days,s,‘NULL’);
12.2 如何重載subsref函數(shù)
數(shù)組、矩陣、元胞數(shù)組、對(duì)象都支持上面的等價(jià)調(diào)用。形如subsref(obj,s)的調(diào)用,優(yōu)先調(diào)用用戶自定義的方法。
12.3 如何重載subsasgn函數(shù)
優(yōu)先調(diào)用用戶自定義的方法。
重載的時(shí)候需要返回obj.matrix和obj.cell因?yàn)樵撝剌d函數(shù)的任務(wù)是修改對(duì)象的屬性,但是obj.matrix和obj.cell不是handle對(duì)象,所以在函數(shù)內(nèi)部的修改僅僅是局部修改,必須將它傳回來(lái)。
重載subsasgn和subsref,將會(huì)重載該類(lèi)的屬性訪問(wèn)權(quán)限,使用時(shí)要慎重。
12.4 什么情況下重載下標(biāo)運(yùn)算符
- 當(dāng)用戶想完全禁止通過(guò)dot來(lái)訪問(wèn)對(duì)象內(nèi)部屬性時(shí),可以重載subsref函數(shù)。
- 當(dāng)用戶想構(gòu)造一個(gè)對(duì)象,使其行為看上去像函數(shù) 一樣,可以重載subsref函數(shù)。
- 當(dāng)用戶想在賦值對(duì)象數(shù)組時(shí),做更多的檢查和限制,可以重載subsasgn函數(shù)。
- 讓一個(gè)標(biāo)量對(duì)象行為像矢量一樣。
注意:使用自定義的下標(biāo)運(yùn)算符取代內(nèi)置定義的下邊運(yùn)算符應(yīng)當(dāng)是一個(gè)方便編程的手段,不應(yīng)該使用在對(duì)性能要求很高的程序中。
12.5 如何重載plus函數(shù)
MATLAB中+默認(rèn)是做算數(shù)運(yùn)算,所以在內(nèi)部會(huì)把string轉(zhuǎn)換成數(shù)字,調(diào)用plus函數(shù)。
12.6 MATLAB的Dispatching規(guī)則是什么
對(duì)于形如obj.foo(arg1,arg2,arg3)的調(diào)用,Dispatcher會(huì)直接檢查obj類(lèi)定義中是否定義了foo的方法,如果定義了,那就調(diào)用;沒(méi)有定義,報(bào)錯(cuò)。
形如foo (obj,arg1,arg2,arg3),Dispatcher不會(huì)首先檢查obj類(lèi)定義中是否定義了foo的方法,而是首先檢查四個(gè)參數(shù)obj,arg1,arg2,arg3哪個(gè)參數(shù)所屬的類(lèi)是更高級(jí)別的類(lèi),即為dominant類(lèi),然后查找dominant類(lèi)中是否定義了foo方法,如果定義就調(diào)用;沒(méi)有定義,報(bào)錯(cuò)。
類(lèi)的級(jí)別:任何用戶定義的類(lèi),級(jí)別高于MATLAB內(nèi)置的類(lèi)。
指定用戶定義的類(lèi)之間的級(jí)別
classdef (InferiorClasses={?A,?B})C
end
C的級(jí)別比A和B的高,如果這三類(lèi)出現(xiàn)在參數(shù)列表中,C的對(duì)象是dominant對(duì)象。
12.7 如何判斷兩個(gè)對(duì)象是否相同
handle對(duì)象,==運(yùn)算時(shí)在handle中就定義好的算法,用于檢查handle類(lèi)所指向的實(shí)際數(shù)據(jù)時(shí)同一個(gè)。handle對(duì)象的拷貝是淺拷貝,只復(fù)制了類(lèi)中的地址,沒(méi)有復(fù)制類(lèi)中實(shí)際指向的數(shù)據(jù)對(duì)象。
Value類(lèi)數(shù)據(jù),沒(méi)有定義‘==’運(yùn)算符,需要用戶自己指定行為。
12.8 如何讓一個(gè)對(duì)象在行為上像一個(gè)函數(shù)
仿函數(shù):使普通函數(shù)具有類(lèi)的功能。
12.9 MATLAB中哪些算符允許重載

第13章 超類(lèi)
13.1 什么是超類(lèi)(MetaClass)
定義:用一種普遍的方式來(lái)描述類(lèi),即用類(lèi)的方式來(lái)描述類(lèi)。
13.2 如何獲得一個(gè)類(lèi)的meta.class對(duì)象
第一種得到meta對(duì)象的方法是:已知類(lèi)的名字,可以在類(lèi)名前面加上一個(gè)問(wèn)號(hào)來(lái)獲得meta.class例如:metaObj=?FileIterator。
第二種方法是:如果有了一個(gè)類(lèi)的對(duì)象,可以用meta.class函數(shù)來(lái)獲得meta.class對(duì)象,如:metaObj=metaclass(obj);
第三種方法最靈活:如果類(lèi)的名字是以字符串的形式存在的,可以利用meta.class類(lèi)中的成員方法fromName,該函數(shù)接受string input,返回meta.class對(duì)象,例如:name=’Vehicle’;metaObj=meta.class.fromName(name);
13.3 meta.class對(duì)象中有些什么內(nèi)容
如何系統(tǒng)地獲得類(lèi)中所有property的名字?
metaobj=?Derived;
propNameList={metaobj.PropertyList.Name}
- metaobj.PropertyList是一個(gè)對(duì)象數(shù)組,其中的內(nèi)容是meta.property的對(duì)象
- 使用.語(yǔ)法可以向量化訪問(wèn)數(shù)組中對(duì)象的共同屬性
- metaobj.PropertyList.Name返回的結(jié)果是string類(lèi)型,由于string的長(zhǎng)度不同,使用{}把返回的結(jié)果收集到元胞數(shù)組中去。
13.4 如何手動(dòng)克隆一個(gè)對(duì)象
- handle類(lèi)的淺拷貝
對(duì)象的屬性相互關(guān)聯(lián),不獨(dú)立,俗稱淺拷貝。 - 簡(jiǎn)單克隆
優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單。
缺點(diǎn):如果要克隆有很多的屬性,那么一個(gè)一個(gè)鍵入屬性會(huì)很麻煩。
方法1:構(gòu)造一個(gè)方法,先在該方法中聲明一個(gè)新的對(duì)象,叫做newObj,再把舊的對(duì)象每一個(gè)屬性的值都復(fù)制到新的對(duì)象newObj中,最后在將該newObj返回。
方法2:用meta.class函數(shù),先獲得該類(lèi)的metaObject,然后取出其中的propertyList中屬性的名字,然后遍歷賦值即可。
該方法中newobj.(props{j})=obj.(props{j})有一個(gè)隱藏的前提,所有的property都是Value類(lèi)型的對(duì)象,如果有一個(gè)property是handle類(lèi)型的,則得到的拷貝仍然是淺拷貝。 - 遞歸克隆
為了解決仍然是淺拷貝的問(wèn)題,用戶需要提供兩個(gè)類(lèi)的clone函數(shù)
classdef Ref<handle
properties
a
bobj
end
methods
function obj=Ref()
obj.a=rand(1);
obj.bobj=BHandle;
end
function newobj=clone(obj)
newobj=Ref();
metaobj=metaclass(obj);%得到meta Object
props={metaobj.PropertyList.Name};%得到props名字
for j=1:length(props)
tmpProp=obj.(props{j});
if(isa(tmpProp,'handle'))%調(diào)用該類(lèi)的Prop方法
newobj.(props{j})=tmpProp.clone();
else
newobj.(props{j})=tmpProp;
end
end
end
end
end
Bhandle:
classdef BHandle<handle
properties
var
end
methods
function obj=BHandle()
obj.var=rand(1);
end
function newobj=clone(obj)
newobj=BHandle();
metaobj=metaclass(obj);%得到meta Object
props={metaobj.PropertyList.Name};%得到props名字
for j=1:length(props)
tmpProp=obj.(props{j});
if(isa(tmpProp,'handle'))
newobj.(props{j})=tmpProp.clone();%程序不會(huì)運(yùn)行到這里
else
newobj.(props{j})=tmpProp;
end
end
end
end
end
13.5 如何使用matlab.mixin.Copyable自動(dòng)克隆一個(gè)對(duì)象
MATLAB提供mixin類(lèi)的Copyable,其中包括copy和copyElement兩個(gè)方法幫助用戶完成基本的handle類(lèi)對(duì)象的深拷貝。copy方法是sealed,不允許子類(lèi)重載,copyElement是protected,允許子類(lèi)重載。用戶只需要讓自己的類(lèi)繼承自matlab.mixin.Copyable即可,此時(shí)仍為handle類(lèi)。和前面類(lèi)似,copy和copyElement組合在一起也是自動(dòng)遍歷的對(duì)象中的各個(gè)屬性做拷貝。
clear all;clc;
record1=StudentRecord();
record1.name='A';
record2=copy(record1);
record2.name='B';
record1.name
record2.name
copyable類(lèi)中的方法默認(rèn)的并不包括對(duì)屬性做遞歸的深拷貝,如果對(duì)象有一個(gè)handle對(duì)象,使用copy方法進(jìn)行對(duì)象拷貝時(shí),該對(duì)象被淺拷貝。
用戶可以重載copyElement方法。先在copyElement中調(diào)用父類(lèi)的copyElement方法,得到新的StudentRecord對(duì)象,這時(shí)homework屬性是淺拷貝。然后對(duì)其中的homework屬性做完全的復(fù)制。
第14章 面向?qū)ο蟪绦蛟O(shè)計(jì)的基本思想
14.1 單一職責(zé)原則
一個(gè)類(lèi)最好只有一個(gè)引起它變化的因素。
UML,實(shí)心菱形表示非包括不可的組合關(guān)系;空心菱形表示松散的可有可無(wú)的組合關(guān)系,也叫聚集。
14.2 開(kāi)放與封閉原則
程序的設(shè)計(jì)應(yīng)該對(duì)修改是封閉的,對(duì)擴(kuò)展是開(kāi)放的。
14.3 多用組合少用繼承
使用組合可以讓系統(tǒng)有更大的彈性,不僅可以將算法封裝成類(lèi),還可以在運(yùn)行時(shí)動(dòng)態(tài)地改變對(duì)象的行為。
14.4 面向接口編程
上層模塊通常是包含抽象方法的抽象類(lèi),而繼承他們的子類(lèi)要提供這些方法的實(shí)現(xiàn)。通常這些子類(lèi)叫做對(duì)接口的實(shí)現(xiàn)。
第15章 創(chuàng)建型模式
15.1工廠模式:構(gòu)造不同種類(lèi)的面條
15.1.1簡(jiǎn)單工廠模式

簡(jiǎn)單工廠模式:對(duì)象的產(chǎn)生細(xì)節(jié)由一個(gè)特定的類(lèi)負(fù)責(zé),并且該類(lèi)中包含了必要的邏輯判斷以產(chǎn)生不同的對(duì)象。

15.1.2工廠模式

工廠模式的關(guān)鍵在于具體的對(duì)象的創(chuàng)建時(shí)機(jī)推遲到工廠子類(lèi)中完成。不希望高層的模塊和具體的硬件細(xì)節(jié)打交道,所以把產(chǎn)生這個(gè)對(duì)象的工作交給工廠模式去完成。

15.1.3Factory模式總結(jié)
定義一個(gè)創(chuàng)建對(duì)象的接口,讓子類(lèi)決定實(shí)例化哪個(gè)類(lèi)。factory模式使一個(gè)類(lèi)的實(shí)例化延遲到其子類(lèi)。

15.1.4如何進(jìn)一步去掉switch/if語(yǔ)句
對(duì)于缺省的Constructor可以:
function obj=createObj(classname)
obj=eval(classname);
end
test:createObj(‘Sub1’);
否則對(duì)于如下的Constructor:
classdef Sub1<handle
properties
a
end
methods
function obi=Sub1(var)
obj.a=var;
end
end
end
可以使用strcat構(gòu)造要執(zhí)行的命令的字符,然后再用eval函數(shù)執(zhí)行命令。
test:
classname=’Sub1’;
cmd=strcat(classname,’(’,’10’,’)’);
obj=eval(cmd);
或者使用str2func函數(shù),從classname處獲得類(lèi)的構(gòu)造函數(shù)的句柄,然后像正常使用構(gòu)造函數(shù)那樣調(diào)用該函數(shù)句柄。
classname=’Sub1’;
ConstructHandle=str2func(classname);
obj=ConstructHandle(3);
15.1.5 抽象工廠
最后的產(chǎn)品是各種面條的聚集。

15.1.6 AbstractFactory模式總結(jié)
提供一個(gè)創(chuàng)建一系列相關(guān)或者相互依賴的對(duì)象的接口,而無(wú)需指定它們具體的類(lèi)。
-
模式結(jié)構(gòu)
類(lèi)之間的協(xié)作
在運(yùn)行時(shí),client將負(fù)責(zé)創(chuàng)建一個(gè)ConcreteFactory類(lèi)的實(shí)例,這個(gè)具體的工廠具有創(chuàng)建不同對(duì)象的代碼。Client可以更換具體的工廠以得到不同的具體的產(chǎn)品。何時(shí)使用AbstractFactory模式
當(dāng)一個(gè)系統(tǒng)要獨(dú)立于它的產(chǎn)品創(chuàng)建、組合、表示時(shí)。
當(dāng)一個(gè)系統(tǒng)需要多個(gè)產(chǎn)品系列中的一個(gè)來(lái)配置時(shí)。
當(dāng)需要強(qiáng)調(diào)一系列相關(guān)產(chǎn)品的設(shè)計(jì)時(shí),以便進(jìn)行聯(lián)合調(diào)用。
15.2 單例模式:給工程計(jì)算添加一個(gè)LOG文件
15.2.1 如何控制對(duì)象的數(shù)量
MATLAB工程科學(xué)計(jì)算時(shí),在過(guò)程中輸出一些結(jié)果,用來(lái)調(diào)試程序。一般記錄中間結(jié)果的文件叫做LOG。在程序運(yùn)行期間,都能往LOG中寫(xiě)入數(shù)據(jù),并且程序運(yùn)行期間有且只有一個(gè)LOG。
單例Singleton模式:該模式用來(lái)控制一個(gè)類(lèi)所產(chǎn)生的對(duì)象的數(shù)量。
classdef MyClass<handle
methods(Access=private)%私有構(gòu)造函數(shù)
function obj=MyClass()
disp('constructor called');
end
end
methods(Static)
function obj=getInstance()%靜態(tài)接口方法
persistent localObj
if isempty(localObj)||~isvalid(localObj)%如果localObj不存在則創(chuàng)建
localObj=MyClass();
end
obj=localObj;%如果localObj已存在則返回
end
end
end
obj1=MyClass.getInstance();
obj2=MyClass.getInstance();
obj3=MyClass.getInstance();
這是一個(gè)Handle類(lèi),所以構(gòu)造出來(lái)的obj1,obj2,obj3實(shí)際指向同一個(gè)實(shí)例。
15.2.2 應(yīng)用:如何包裝一個(gè)對(duì)象供全局使用
classdef LogClass<handle
properties
FID
end
methods(Access=private)%私有構(gòu)造函數(shù)
function obj=LogClass()%打開(kāi)文件
obj.FID=fopen('logfile.txt','a');
end
end
methods
function delete(obj)%關(guān)閉文件
fclose(obj.FID);
end
function print(obj,string)
fprintf(obj.FID,string);
end
end
methods(Static)%控制外部訪問(wèn)
function obj=getInstance()%靜態(tài)接口方法
persistent localObj
if isempty(localObj)||~isvalid(localObj)%如果localObj不存在則創(chuàng)建
localObj=LogClass();
end
obj=localObj;%如果localObj已存在則返回
end
end
end
15.3 建造者模式:如何用MATLAB構(gòu)造一輛自行車(chē)
15.3.1 問(wèn)題的提出

15.3.2 應(yīng)用:Builder模式為大規(guī)模計(jì)算做準(zhǔn)備工作
15.3.3Builder模式總結(jié)
將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示方法分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示。
- Builder模式結(jié)構(gòu)
Director、Builder、ConcreteBuilder、Product、Part

- 類(lèi)之間的協(xié)作
- Client(外部程序)負(fù)責(zé)構(gòu)造Director對(duì)象,并且設(shè)定該Director所要指導(dǎo)的具體Builder。
- Director擁有Builder對(duì)象,并且可以替換。
- Builder擁有product對(duì)象,Product對(duì)象由parts對(duì)象組成
- 構(gòu)造產(chǎn)品的請(qǐng)求發(fā)自于Director,Builder接到請(qǐng)求之后按照Director所指導(dǎo)的順序把parts對(duì)象添加到產(chǎn)品中去
- 何時(shí)使用Builder
- 當(dāng)構(gòu)造過(guò)程中允許被構(gòu)造的對(duì)象有不同的表示時(shí)。
- 當(dāng)創(chuàng)建復(fù)雜對(duì)象的算法,要獨(dú)立于該地對(duì)象的裝配方式時(shí)。
第16章 構(gòu)造型模式
16.1 裝飾者模式:動(dòng)態(tài)地給對(duì)象添加額外的職責(zé)
16.1.1 裝飾者模式的引入

16.1.2 面館菜單代碼
這種設(shè)計(jì)對(duì)修改是封閉的,還支持多次裝飾,對(duì)擴(kuò)展是開(kāi)放的。

16.1.3 裝飾者模式總結(jié)
動(dòng)態(tài)地給對(duì)象添加一些額外的職責(zé),就增加功能來(lái)說(shuō),Decorator模式相比生成子類(lèi)更為靈活,Decorator模式也叫做包裝器。
-
裝飾者模式結(jié)構(gòu)
Component、ConcreteComp1、ConcreteComp2、Decorator、ConcreteDeco1、ConcreteDeco2
類(lèi)之間的協(xié)作
Concrete Component和Concrete Decorator都有相同的基類(lèi),并且Decorator基類(lèi)中的compHandle被用來(lái)指向何時(shí)使用Decorator模式
Decorator模式可以避免通過(guò)創(chuàng)建子類(lèi)來(lái)擴(kuò)展類(lèi)的功能,Decorator是以動(dòng)態(tài)的方式給單個(gè)對(duì)象添加新的功能。想要擴(kuò)展類(lèi),又想避免子類(lèi)數(shù)量爆炸時(shí),可以考慮使用Decorator模式。
第17章 行為模式
17.1 觀察者模式:用MATLAB實(shí)現(xiàn)觀察者模式
17.1.1 發(fā)布和訂閱的基本模型

17.1.2 訂閱者查詢發(fā)布者的狀態(tài)

17.1.3 把發(fā)布者和訂閱者抽象出來(lái)

17.1.4 Observer模式總結(jié)
定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知,并且自動(dòng)被更新。
-
模式結(jié)構(gòu)
Subject、ConcreteSubject、Observer、ConcreteObserver
類(lèi)之間的協(xié)作
- 具體的觀察者向ConcreteSubject對(duì)象發(fā)出訂閱的請(qǐng)求,該ConcreteSubject對(duì)象把具體觀察者加到其內(nèi)部的一個(gè)列表中。
- 當(dāng)ConcreteSubject內(nèi)部發(fā)生改變,需要通知其觀察者時(shí),它將遍歷其內(nèi)部的觀察者的列表,依次調(diào)用這些觀察者的update方法。
- 觀察者得到更新的通知,它可以向ConcreteSubject對(duì)象提出查詢請(qǐng)求。
17.2 策略模式:分離圖像數(shù)據(jù)和圖像處理算法
17.2.1 問(wèn)題的提出

17.2.2 應(yīng)用:更復(fù)雜的分離數(shù)據(jù)和算法的例子

17.2.3 Strategy模式總結(jié)
- 模式結(jié)構(gòu)
Context、Strategy、StrategyA、StrategyB、StrategyC

- 類(lèi)之間的協(xié)作
- 在Context對(duì)象中存放數(shù)據(jù),而Strategy對(duì)象中存放算法,Context對(duì)象可以選擇所需要的算法。
- Context對(duì)象把來(lái)自外界的計(jì)算請(qǐng)求轉(zhuǎn)交給Strategy對(duì)象。
- 轉(zhuǎn)交請(qǐng)求是,Context把自己作為一個(gè)參數(shù)傳遞給Strategy對(duì)象,以提供Strategy對(duì)象計(jì)算所需要的數(shù)據(jù)。
- Strategy模式何時(shí)使用
Strategy模式是用來(lái)封裝算法的,在實(shí)踐中,可以用來(lái)封裝幾乎任何類(lèi)型的規(guī)則。如果在分析過(guò)程中,需要在不同的情況下應(yīng)用不同的算法,就可以考慮使用Strategy模式來(lái)處理問(wèn)題。
17.3 遍歷者模式:工程科學(xué)計(jì)算中如何遍歷大量數(shù)據(jù)
17.3.1 問(wèn)題的提出
files=dir(c:\datafolder);
files=files(cell2mat({files(:).isdir})~=1);%去除文件夾中的目錄
for i=1:length(files)
inputname=file(i).name;
imgObj=Image(inputname);
imgObj.doMethod();
end
17.3.2 聚集(Aggregator)和遍歷者(Iterator)

17.3.3 Iterator模式總結(jié)
Iterator(內(nèi)部)的意圖是用一種方法順序去訪問(wèn)一個(gè)聚集對(duì)象中的各個(gè)元素,而又不用暴露對(duì)象的內(nèi)部顯示。
- Iterator模式結(jié)構(gòu)
Aggregator、ConcreteAggregator1、ConcreteAggregator2、Iterator、ConcreteIterator1、ConcreteIterator2

- 類(lèi)之間的協(xié)作
- 因?yàn)楸闅v的方式和Aggregator自身的內(nèi)部情況有關(guān)。只有Aggregator才有足夠的信息來(lái)告訴外部類(lèi)該如何遍歷自己,所以具體的Aggregator負(fù)責(zé)產(chǎn)生具體的Iterator。
- 具體的Iterator類(lèi)將擁有Aggregator的Handle用來(lái)從集合中取元素
- 兩個(gè)Base類(lèi)用來(lái)提供接口,規(guī)定具體的Aggregator和具體的Iterator應(yīng)該提供何種方法,以及方法的signature應(yīng)該是怎么樣的
- ConcreteIterator提供不同的遍歷方式,比如ConcreteIterator1提供從前往后的遍歷,而第二個(gè)則是隨機(jī)遍歷。
17.4 狀態(tài)模式:用MATLAB模擬自動(dòng)販賣(mài)機(jī)
17.4.1 使用if語(yǔ)句的自動(dòng)販賣(mài)機(jī)
17.4.2 使用StatePattern的自動(dòng)販賣(mài)機(jī)


17.4.3 State模式總結(jié)
狀態(tài)模式:允許對(duì)象修改內(nèi)部狀態(tài)是改變它的行為,對(duì)象看起來(lái)好像是修改了它的類(lèi)。
-
State模式的結(jié)構(gòu)
Context、State、ConcreteState1、ConcreteState2
類(lèi)之間的協(xié)作
對(duì)于來(lái)自外界的和自身狀態(tài)相關(guān)的請(qǐng)求,Context對(duì)象將這些請(qǐng)求委托給ConcreteState對(duì)象處理。
ConcreteStata對(duì)象可以訪問(wèn)Context對(duì)象,也可以改變Context對(duì)象的內(nèi)部狀態(tài)。這就要求:在request方法中,Context對(duì)象必須把自己作為一個(gè)參數(shù)傳遞給ConcreteState對(duì)象。
使用Context類(lèi)的client不需要和State的對(duì)象打交道。何時(shí)使用State模式
- 當(dāng)對(duì)象的行為取決于它的狀態(tài),并且該對(duì)象在運(yùn)行時(shí)會(huì)改變狀態(tài)。也就是說(shuō)對(duì)象的行為會(huì)在運(yùn)行時(shí)改變,可以考慮使用State模式。
- 當(dāng)一個(gè)操作中含有龐大的多分支條件語(yǔ)句,而且這些分支語(yǔ)句依賴于對(duì)象的狀態(tài)時(shí),可以考慮使用State模式將每個(gè)條件分支放入一個(gè)獨(dú)立的類(lèi)中,而對(duì)象的狀態(tài)對(duì)應(yīng)于擁有一個(gè)狀態(tài)類(lèi)對(duì)象。
17.5 模板模式:下面條和煮水餃有什么共同之處
17.5.1 抽象下面條和煮水餃的過(guò)程
17.5.2 應(yīng)用:把策略和模板模式結(jié)合起來(lái)
17.5.3 Template模式總結(jié)
模板方法模式:定義一個(gè)操作中的算法的骨架,將一些步驟延遲到子類(lèi)中。模板方法使得子類(lèi)可以不改變一個(gè)算法的結(jié)構(gòu)即可以重新定義該算法的某些特殊的步驟。
- Template模式的結(jié)構(gòu)
AbstractClass、ConcreteClass1、ConcreteClass2。Template模式中,含有反向控制的結(jié)構(gòu),因?yàn)橥ǔJ亲宇?lèi)調(diào)用父類(lèi)的操作,而在這個(gè)模式里,卻是父類(lèi)調(diào)用子類(lèi)。這種結(jié)構(gòu)也被叫做好萊塢模式。

17.6 備忘錄模式:實(shí)現(xiàn)GUI的UNDO功能
17.6.1如何記錄對(duì)象的內(nèi)部狀態(tài)
Map:http://blog.sina.com.cn/s/blog_6163bdeb0100rdx3.html
http://blog.sina.com.cn/s/blog_4a0824490102vamk.html
17.6.2如何利用備忘錄模式實(shí)現(xiàn)GUI的do和undo操作
17.6.3Memento模式總結(jié)
在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài)。這樣,以后可以將該對(duì)象復(fù)原到原先的狀態(tài)。
-
memento模式結(jié)構(gòu)
- 類(lèi)之間的協(xié)作
- Originator是擁有狀態(tài)的對(duì)象,外部的命令向originator發(fā)出一個(gè)請(qǐng)求,要求保存?zhèn)渫洝?/li>
- originator把自身狀態(tài)數(shù)據(jù)封裝到一個(gè)memento對(duì)象中,并且提交給caretaker保存。
- 只有Originator知道該如何利用Memento對(duì)象中的數(shù)據(jù),Caretaker的工作僅僅是保存各個(gè)Memento對(duì)象,不能對(duì)備忘錄的內(nèi)容進(jìn)行操作。




