




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
Java設(shè)計模式
i.i創(chuàng)建型模式
AbstractFactory(抽象工廠)
FactoryMethod(工廠方法)
Singleton(單態(tài)模式)
Builder(建造者模式)
Prototype(原型模式)
1.2結(jié)構(gòu)型模式
Adapter(適配器模式)
Bridge(橋接模式)
Composite(組合模式)
Decorator(裝配模式)
Facade(外觀模式)
Flyweight(享元模式)
Proxy(代理模式)
1.3行為型模式
ChainofResponsibility(責(zé)任鏈模式)
Command(命令模式)
Interpreter(解釋器模式)
Iterator(迭代器模式)
Mediator(中介者模式)
Memento(備忘錄模式)
Observer(觀察者模式)
State(狀態(tài)模式)
Strategy(策略模式)
TemplateMethod(模板方法)
Visitor(訪問者模式)
ToneyChen的總結(jié)
Singleton設(shè)計模式
Singleton單類模式是最簡單的設(shè)計模式,它的主要作用是保證在程序運(yùn)行生命
周期中,使用了單類模式的類只能有一個實(shí)例對象存在。單類模式實(shí)現(xiàn)了類似C
語言中全局變量的功能,單類模式常用于注冊/查找的服務(wù)。
單類模式有兩種實(shí)現(xiàn)方式:飽漢模式和餓漢模式,如下:
飽漢單類模式例子代碼:
[java]viewplaincopy
1.publicclassSingletonl{
2.〃飽漢模式,聲明時就創(chuàng)建實(shí)例對象
3.publicstaticfinalSingletonlinstance=newSingletonl();
4.〃單類模式的構(gòu)造方法必須為private,以避免通過構(gòu)造方法創(chuàng)建對象實(shí)例,
5.〃并且必須顯示聲明構(gòu)造方法,以防止使用默認(rèn)構(gòu)造方法
6.privateSingletonl(){}
7.〃單類模式必須對外提供獲取實(shí)例對象的方法
8.publicstaticSingletonlgelnstance(){
9.returninstance;
10.}
11.}
餓漢單類模式即延遲初始化單類方式,例子代碼:
[java]viewplaincopy
1.publicclassSingleton2{
2.〃餓漢模式,聲明時不創(chuàng)建實(shí)例對象
3.publicstaticSingleton2instance;
4.〃單類模式的構(gòu)造方法必須為private,以避免通過構(gòu)造方法創(chuàng)建對象實(shí)例,
5.〃并且必須顯示聲明構(gòu)造方法,以防止使用默認(rèn)構(gòu)造方法
6.privateSingleton2(){}
7.〃單類模式必須對外提供獲取實(shí)例對象的方法,延遲初始化的單類模式必須使用
synchronized同步關(guān)鍵字,否則多線程情況下很容易產(chǎn)生多個實(shí)例對象
8.publicstaticsynchronizedSingleton2gelnstance(){
9.〃延遲初始化,只有當(dāng)?shù)谝淮问褂脮r才創(chuàng)建對象實(shí)例
10.if(instance==null){
11.returnnewSingleton2();
12.)
13.returninstance;
14.}
15.}
一般認(rèn)為飽漢模式要比餓漢模式更加安全。
上面兩種Singleton單類設(shè)計模式的實(shí)現(xiàn)方式都隱藏有如下的問題:
(1).雖然構(gòu)造方式的訪問修飾符為private,即除了自身以外其他任何類都無法
調(diào)用,但是通過反射機(jī)制的setAccessiable(true)方法可以訪問私有方法和屬
性。因此Singleton單類模式必須考慮這種例外情況。
⑵.對象序列化之后再反序列化時會生成新的對象,因此當(dāng)Singleton單類模式
類實(shí)現(xiàn)序列化接口時,必須顯式聲明所有的字段為tranisento
在JDK1.5之后引入了Enum枚舉,因此在JDK1.5之后Singleton單類模式又有
了第三種實(shí)現(xiàn)方式,也是最好的實(shí)現(xiàn)方式,例子如下:
[java]viewplaincopy
1.publicenumSingleton3{
2.INSTANCE{
3.publicvoiddoSomething(){
4.……
5.)
6.);
7.publicSingleton3getlnstance(){
8.returnINSTANCE;
9.)
10.publicabstractvoiddoSomething();
11.}
Singleton單類模式中只有一個INSTANCE枚舉元素,枚舉可以保證真?zhèn)€程序生命周期中只有
一個實(shí)例對象存在,同時還避免了常規(guī)Singleton單類模式private構(gòu)造方法被反射調(diào)用和序
列化問題。
注意:java中除了構(gòu)造方法可以創(chuàng)建對象實(shí)例以外,還可以通過克隆方法
(clone()是Object中的protected方法)來創(chuàng)建對象,若單類對象直接繼承自
Object對象,則如果沒有提供具體clone方法實(shí)現(xiàn),則當(dāng)調(diào)用克隆方法創(chuàng)建對
象時,會拋出運(yùn)行時的異常CloneNotSupportedExceptiono
若單類類繼承了實(shí)現(xiàn)克隆方法的類,則在單類類中必須覆蓋父類的克隆方法,顯
式拋出異常CloneNotSupportedExceptiono
另外,實(shí)現(xiàn)了單類模式的類不能再有派生子類,因?yàn)闃?gòu)造方式是私有的,子類無
法調(diào)用父類構(gòu)造方法,因此達(dá)到了Final的效果。
Proxy設(shè)計模式
Proxy代理設(shè)計模式是一種控制對象訪問的設(shè)計模式,類似于網(wǎng)絡(luò)代理,網(wǎng)絡(luò)代
理機(jī)制如下圖:
客戶端代理服務(wù)器目標(biāo)資源
Proxy代理設(shè)計模式機(jī)制如下:
客戶端程序代理程序目標(biāo)程序
客戶端程序通過代理程序來訪問真正的目標(biāo)程序,代理程序?qū)ν怆[藏了目標(biāo)程
序。普通代理設(shè)計模式例子代碼如下:
[java]viewplaincopy
1.interfaceProxyBase{
2.publicvoidf();
3.publicvoidg();
4.publicvoidh();
5.)
6.〃代理程序
7.classProxyimplementProxyBase{
8.privateProxyBaseimplementation;
9.publicProxy(){
10.〃目標(biāo)程序
11.implementation=newProxylmplementation();
12.)
13.publicvoidf(){
14.implementation.f();
15.}
16.publicvoidg(){
17.implementation.g();
18.}
19.publicvoidh(){
20.implementation.h();
21.)
22.}
23.〃目標(biāo)程序
24.classProxyimplementationimplementsProxyBase{
25.publicvoidf(){
26.System.out.println(//Proxylmplementation.f(),,);
27.}
28.publicvoidg(){
29.System.out.println(zzProxylmplementation.g(),,);
30.}
31.publicvoidh(){
32.System.out.println(//Proxylmplementation.h(),,);
33.}
34.}
35.〃客戶端程序調(diào)用代理
36.publicclassProxyDemo{
37.publicstaticvoidmain(String[]args){
38.〃客戶端調(diào)用代理程序
39.Proxyp=newProxy();
40.p.f();
41.p.g();
42.p.h();
43.}
44.}
從JDK1.3以后,java引入動態(tài)代理機(jī)制,java的動態(tài)代理只能針對接口進(jìn)行動
態(tài)代理,即要實(shí)現(xiàn)動態(tài)代理的類必須實(shí)現(xiàn)接口,CGLIB提供了針對類的動態(tài)代理
功能。JDK動態(tài)代理的例子如下:
[java]viewplaincopy
1.〃代理接口
2.interfaceFoo{
3.publicvoidf(Strings);
4.publicvoidg(inti);
5.publicvoidh(inti,Strings);
6.}
7.〃接口實(shí)現(xiàn)類,即被代理類
8.classFoolmplimplementsFoo{
9.publicvoidf(Strings){
10.System.out.printlnCTooImpl.fO,s="+s);
11.}
12.publicvoidg(inti){
13.System.out.printlnC'FooImpl,gO,i=",+i);
14.)
15.publicvoidh(inti,Strings){
16.System.out.printlnC'FooImpl.hO,\=f,+i+s="+s);
17.)
18.)
19.〃動態(tài)代理處理類
20.classProxyHandlerimplementslnvocationHandler{
21.〃代理實(shí)現(xiàn)類
22.privateObjectdelegate;
23.publicProxyHandler(Objectobj){
24.delegate=obj;
25.)
26.publicObjectinvoke(Objectproxy,Methodmethod,Object[]args){
27.System.out.println(zzBeforemothod:"+method);
28.method.invoke(this.delegate,args);
29.System.out.printlnf^Aftermothod:〃+method);
30.returnnull;
31.)
32.}
33.publicclassDynamicProxyDemo{
34.publicstaticvoidmain(String[]args){
35.Foofoo=newFoolmpl();
36.ProxyHandlerhandler=newProxyHandler(foo);
37.〃產(chǎn)生動態(tài)代理
38.Fooproxy=(Foo)Proxy.newProxylnstance(Foo.class.getClassLoader(),newClass[]{Foo.
class},handler);
39.proxy.f("f〃);
40.proxy.g(l);
41.proxy.h("h",2);
42.}
43.)
動態(tài)代理和普通的代理模式的區(qū)別:動態(tài)代理中的代理類是由
java.lang,reflect.Proxy類在運(yùn)行期時根據(jù)接口定義,采用Java反射功能動
態(tài)生成的。和java.lang,reflect.InvocationHandler結(jié)合,可以加強(qiáng)現(xiàn)有類的
方法實(shí)現(xiàn)。動態(tài)帶來自定義Handler實(shí)現(xiàn)InvocationHandler接口,自定義
Handler實(shí)例化時,將代理的實(shí)現(xiàn)類傳入自定義Handler對象中。自定義Handler
需要實(shí)現(xiàn)invoke方法,該方法可以使用Java反射調(diào)用實(shí)現(xiàn)類的實(shí)現(xiàn)的方法,同
時當(dāng)然可以實(shí)現(xiàn)其他功能,例如在調(diào)用實(shí)現(xiàn)類方法前后加入Log,實(shí)現(xiàn)安全認(rèn)證
等。而Proxy類根據(jù)Handler和需要代理的接口動態(tài)生成一個接口實(shí)現(xiàn)類的對象。
當(dāng)用戶調(diào)用這個動態(tài)生成的實(shí)現(xiàn)類時,實(shí)際上是調(diào)用了自定義Handler的
invoke方法。
State設(shè)計模式
State狀態(tài)設(shè)計模式類似于Switch多路分支功能的開關(guān),State狀態(tài)模式機(jī)制如
下:
State狀態(tài)設(shè)計模式用于改變對象的行為,在代理的生命周期里,隨著狀態(tài)變化
從一個目標(biāo)實(shí)現(xiàn)程序切換到另一個目標(biāo)實(shí)現(xiàn)程序。
我們經(jīng)常遇到如下的程序代碼:
[java]viewplaincopy
1.publicclassCreature{
2.privateBooleanisFrog=true;〃標(biāo)識
3.publicvoidgreet(){
4.if(isForg){
5.System.out.println(//Ribbet!,,);
6.}else{
7.System.out.println(/zDarling!,/);
8.)
9.)
10.〃轉(zhuǎn)換標(biāo)識
11.publicvoidkiss(){
12.isForg=false;
13.}
14.publicstaticvoidmain(String[]args){
15.Creaturecreature=newCreature();
16.creature.greet();
17.creature.kiss();
18.creature.greet();
19.}
20.}
上面例子代碼中g(shù)reet。方法在執(zhí)行具體操作之前必須要判斷一下標(biāo)識,代碼顯得笨拙繁
瑣,使用簡單State狀態(tài)模式改寫上面代碼如下:
[java]viewplaincopy
1.publicclassCreature{
2.〃狀態(tài)接口
3.privateinterfaceState{
4.Stringresponse();
5.)
6.privateclassForgimplementsState{
7.publicStringresponse(){
8.return"Ribbet!〃;
9.)
10.}
11.privateclassPrinceimplementsState{
12.publicStringresponse(){
13.return"Darling!”;
14.}
15.}
16.privateStatestate=newForg();
17.publicvoidgreet(){
18.System.out.println(state.response);
19.}
20.publicvoidkiss(){
21.state=newPrince();
22.}
23.publicstaticvoidmain(String[]args){
24.Creaturecreature=newCreature();
25.creature.greet();
26.creature.kiss();
27.creature.greet();
28.}
29.}
State狀態(tài)設(shè)計模式中,狀態(tài)自動切換并傳播,不需要再改動標(biāo)識,代碼顯得非
常優(yōu)雅。
State狀態(tài)設(shè)計模式一個基本框架如下:
[java]viewplaincopy
1.〃狀態(tài)接口
2.interfaceState{
3.voidoperationl();
4.voidoperation2();
5.voidoperation3();
6.}
7.〃狀態(tài)實(shí)現(xiàn)類1
8.classimplementation!implementsState{
9.publicvoidoperationl(){
10.System.out.println(//lmplementationl.operationl(),,);
11.}
12.publicvoidoperation2(){
13.System.out.println(//lmplementationl.operation2(),,);
14.}
15.publicvoidoperation3(){
16.System.out.println(//lmplementationl.operation3(),,);
17.}
18.}
19.〃狀態(tài)實(shí)現(xiàn)類2
20.classimplementation2implementsState{
21.publicvoidoperationl(){
22.System.out.println(//lmplementation2.operationl(),,);
23.}
24.publicvoidoperation2(){
25.System.out.println(z/lmplementation2.operation2(),,);
26.}
27.publicvoidoperation3(){
28.System.out.println(//lmplementation2.operation3(),,);
29.}
30.}
31.〃服務(wù)提供者
32.classServiceProvider{
33.privateStatestate;
34.publicServiceProvider(Statestate){
35.this.state=state;
36.)
37.〃狀態(tài)更改
38.publicvoidchangeState(StatenewState){
39.state=newState;
40.)
41.publicvoidservicel(){
42.//……
43.state.operationl();
44.//……
45.state.operation3();
46.}
47.publicvoidservice2(){
48.//……
49.state.operationl();
50.//……
51.state.operation2();
52.}
53.publicvoidservice3(){
54.//……
55.state.operation3();
56.//……
57.state.operation2();
58.}
59.}
60.publicclassStateDemo{
61.privateServiceProvidersp=newServiceProvider(newlmplementationl());
62.privatevoidrun(ServiceProvidersp){
63.sp.servicel();
64.sp.service2();
65.sp.service3();
66.}
67.publicstaticvoidmain(String[]args){
68.StateDemodemo=newStateDemo();
69.demo.run(sp);
70.sp.changeState(newImplementation2());
71.demo.run(sp);
72.)
73.}
State狀態(tài)模式和Proxy代理模式都為客戶端程序提供了一個目標(biāo)程序代理,真
正的目標(biāo)程序被代理所隱藏,當(dāng)客戶端程序調(diào)用目標(biāo)程序時,首先將調(diào)用請求發(fā)
送給代理,代理才真正調(diào)用目標(biāo)程序,但是Proxy代理模式和State狀態(tài)模式有
如下區(qū)別:
(D.Proxy代理模式中被調(diào)用的目標(biāo)程序只有一個,而State狀態(tài)模式中被調(diào)
用的目標(biāo)程序有多個。
⑵.Proxy代理模式的目的是控制客戶端對目標(biāo)程序的訪問,而State狀態(tài)模式
是為了根據(jù)條件動態(tài)改變目標(biāo)程序。
Itrator設(shè)計模式
Iterator迭代器模式,提供一種統(tǒng)一的方法訪問-一個容器(container)對象中
各個元素,而又不需暴露該對象的內(nèi)部細(xì)節(jié),迭代器模式是為容器而設(shè)計。
程序?qū)θ萜鲗ο蟮脑L問必然涉及到遍歷算法,不同的容器遍歷算法是不同的,
List,Stack和Set等等常用容器遍歷元素的算法各不相同。解決容器遍歷算
法差異有兩種方案:第一,可以將遍歷方法塞到容器對象中去,容器承受了過多
的功能,它不僅要負(fù)責(zé)自己“容器”內(nèi)的元素維護(hù)(添加、刪除等等),而且
還要提供遍歷自身的接口;第二,根本不提供容器遍歷算法,讓容器使用者自己
去實(shí)現(xiàn)。該方法雖然是省事,卻又將容器的內(nèi)部細(xì)節(jié)暴露無遺。迭代器模式的
出現(xiàn),很好的解決了上面兩種情況的弊端,不但將遍歷容器的算法從不同集合
容器類中抽象出來,同時又對外隱藏了容器的具體實(shí)現(xiàn)細(xì)節(jié)。
迭代器模式由以下角色組成:
1)迭代器角色(Iterator):迭代器角色負(fù)責(zé)定義訪問和遍歷元素的接口。
2)具體迭代器角色(ConcreteIterator):具體迭代器角色要實(shí)現(xiàn)迭代器接口,
并要記錄遍歷中的當(dāng)前位置。
3)容器角色(Container):容器角色負(fù)責(zé)提供創(chuàng)建具體迭代器角色的接口。
4)具體容器角色(ConcreteContainer):具體容器角色實(shí)現(xiàn)創(chuàng)建具體迭代器
角色的接口——這個具體迭代器角色于該容器的結(jié)構(gòu)相關(guān)。
Java集合框架中迭代設(shè)計模式的應(yīng)用:
[java]viewplaincopy
1.〃迭代器,該接口提供了迭代遍歷的通用方法
2.publicinterfaceIterator{
3.booleanhasNext();
4.Objectnext();
5.voidremove();
6.)
7.〃容器迭代化接口,凡是實(shí)現(xiàn)此接口的集合容器距可以生成相應(yīng)的迭代器
8.publicinterfacelterable<T>{
9.〃產(chǎn)生迭代器,將容器對象轉(zhuǎn)換為迭代器對象
10.lterator<T>interator();
11.}
12.〃java集合框架的根接口,該接口繼承了容器迭代化接口,因此java中的集合都可
以被迭代
13.publicinterfaceCollection<E>extendslterable<E>
自定義迭代器,以ArrayList為自定義迭代容器的底層數(shù)據(jù)結(jié)構(gòu),實(shí)現(xiàn)自定義迭
代器的代碼如下:
[java]viewplaincopy
1.publicclassMylteratorimplementsIterable{
2.〃存放數(shù)據(jù)的集合
3.privateArrayListlist;
4.〃負(fù)責(zé)創(chuàng)建具體迭代器角色的工廠方法
5.publicIteratoriterator(){
6.returnnewItr(list);
7.)
8.〃作為內(nèi)部類的具體迭代器角色
9.privateclassItrimplementsIterator{
10.ArrayListmyList;
11.intposition=0;
12.publicltr(ArrayListlist){
13.this.myList=list;
14.}
15.publicObjectnext(){
16.Objectobj=myList.get(position);
17.position++;
18.returnobj;
19.}
20.publicbooleanhasNext(){
21.if(position>=myList.size()){
22.returnfalse;
23.}else{
24.returntrue;
25.)
26.}
27.〃不支持remove操作
28.publicvoidremove(){
29.thrownewUnsupportedOperationException(
30."AlternatingMylteratordoesnotsupportremove()");
31.}
32.}
33.}
使用時,Mylterator對象直接調(diào)用iterator()方法就可以將自定義容器對象轉(zhuǎn)
換為迭代器對象。
Iterator模式的優(yōu)點(diǎn):
(1).實(shí)現(xiàn)功能分離,簡化容器接口。讓容器只實(shí)現(xiàn)本身的基本功能,把迭代功能
委讓給外部類實(shí)現(xiàn),符合類的設(shè)計原則。
(2).隱藏容器的實(shí)現(xiàn)細(xì)節(jié)。
(3).為容器或其子容器提供了一個統(tǒng)一接口,一方面方便調(diào)用;另一方面使得調(diào)
用者不必關(guān)注迭代器的實(shí)現(xiàn)細(xì)節(jié)。
(4).可以為容器或其子容器實(shí)現(xiàn)不同的迭代方法或多個迭代方法o
Strategy設(shè)計模式
Strategy策略設(shè)計模式主要是定義一系列的算法,把這些算法封裝成單獨(dú)的類,
在運(yùn)行時動態(tài)選擇需要的算法,策略模式機(jī)制如下:
策略模式例子如下:
[java]viewplaincopy
1.〃文本替換策略
2.abstractclassTextstrategy{
3.protectedStringtext;
4.
5.publicTextStrategyfStringtext){
6.this.text=text;
7.}
8.publicabstractStringreplace();
9.)
10.〃替換算法1:將文本中"@r@n"替換為"@n"
11.classStrategyOneextendsTextStrategy{
12.publicStrategyOne(Stringtext){
13.super(text);
14.}
15.publicStringreplace(){
16.System.out.println(/zStrategyOne:,,);
17.Stringresult=text.replaceAII("@r?n","@n"));
18.returnresult;
19.}
20.}
21.〃替換算法2:將文本中"@n"替換為"@r@n"
22.classStrategyTwoextendsTextstrategy{
23.publicStrategyTwo(Stringtext){
24.super(text);
25.}
26.publicStringreplace(){
27.System.out.println(//StrategyTwo:,9;
28.Stringresult=text.replaceAII(〃@n”,“@r@n”));
29.returnresult;
30.}
31.}
32.publicclassTextCharChange{
33.publicstaticvoidreplace(TextStrategystrategy){
34.strategy.replace();
35.}
36.publicstaticvoidmain(String[]args){
37.StringtestTextl="Thisisatesttext!!@nOh!LineReturn!!@n";
38.StringtestText2=Thisisatesttext!!@r@nOh!LineReturn@r@n";
39.TextCharChange.replace(newStrategyOne(testText2));
40.TextCharChange.replace(newStrategyTwo(testTextl));
41.}
42.}
State狀態(tài)模式和Strategy策略模式非常類似,但是有如下區(qū)別:
(1).State狀態(tài)模式重點(diǎn)在于設(shè)定狀態(tài)變化,根據(jù)狀態(tài),返回相應(yīng)的響應(yīng)。
⑵.Strategy策略模式重點(diǎn)在于根據(jù)需求直接采用設(shè)定的策略,即根據(jù)場景選
擇合適的處理算法,而不需要改變狀態(tài)。
Factory設(shè)計模式
Factory工廠設(shè)計模式為創(chuàng)建對象提供了一種抽象,而對使用者屏蔽了對象創(chuàng)建
的具體細(xì)節(jié)過程,工廠模式有三種:簡單工廠模式,抽象工廠模式和工廠方法模
式。
(1).簡單工廠模式:
又叫靜態(tài)工廠模式,簡單工廠只包括一個抽象產(chǎn)品類(該類可以是接口,也可以
是具體的類),所有需要的產(chǎn)品類都是該抽象產(chǎn)品類的子類。簡單工廠模式中工
廠為具體產(chǎn)品工廠,產(chǎn)品為抽象產(chǎn)品,由工廠實(shí)例創(chuàng)建產(chǎn)品實(shí)例:
?interTace?
Product
?____________________________________________________
creates
一個生成圓形和矩形的圖形工廠,例子如下:
[java]viewplaincopy
1.〃圖形接口
2.interfaceShape(){
3.publicvoiddraw();
4.)
5.〃圓形
6.classCircleimplementsShape{
7.publicvoiddraw(){
8.System.out.println(zzCircleisdrawing");
9.)
10.}
IL〃矩形
12.classRectangleimplementsShape{
13.publicvoiddraw(){
14.System.out.println("Rectangleisdrawing");
15.)
16.}
17.〃圖形工廠
18.classShapeFactory{
19.publicstaticShapecreateShape(Stringname)throwsInstantiationException,
20.HlegalAccessException,
21.ClassNotFoundException
22.{
23.〃使用java的反射機(jī)制來產(chǎn)生對象實(shí)例
24.return(Shape)class.forName(name),newlnstance();
25.}
26.}
27.publicclassShapeDemo{
28.publicstaticvoiddraw(Shapeshape){
29.shape.draw();
30.}
31.publicstaticvoidmain(String[]args){
32.draw(ShapeFactory.createShape(zzCircle,/));
33.draw(ShapeFactory.createShape(//Rectangle,/));
34.}
35.}
圖形工廠負(fù)責(zé)具體圖形的對象實(shí)例化工作,圖形使用者使用時不需要關(guān)心圖形對
象的具體產(chǎn)生過程。
(2).抽象工廠模式:
抽象工廠模式中可以包括多個抽象產(chǎn)品類,每個抽象產(chǎn)品類可以產(chǎn)生出多個具體
產(chǎn)品類,一個抽象工廠用于定義所需產(chǎn)品的組合形式,抽象工廠派生具體工廠類,
這些具體工廠類就是簡單工廠模式中的工廠類,具體工廠類負(fù)責(zé)具體產(chǎn)品實(shí)例的
創(chuàng)建:
Client
?interface??interface?
AbstractFactoryProductA
+productAOProductA+operationW-void
+productBQ-ProductB+operation20:void
F?飛,
FactorylProductA1ProductA2
+productAO:ProductA+operationlO:void+operationlO:void
+productBQ:Products+operation?。:void+operation20:void
K
Factoiy2
+productAO:ProductA
+productBQ:Products?interface?
ProductB
+operationlO:void
+operation20:void
/\
ProductB1ProductB2
+operationlO:void+operationlO:void
+operation?。:void+operation?。:void
I
以軟件皮膚為例,軟件皮膚由樣式style和顏色color組成,實(shí)現(xiàn)一套I0S風(fēng)格
的軟件皮膚,一套Android風(fēng)格的軟件皮膚,通過抽象工廠實(shí)現(xiàn)軟件皮膚自由切
換例子如下:
[java]viewplaincopy
1〃軟件皮膚類
2classSkin{
3privateSkinFactoryskinFactory;
4publicSkin(SkinFactoryfactory){
5setSkinFactory(factory);
6)
7publicvoidsetSkinFactory(SkinFactoryfactory){
8this.skinFactory=factory
9.)
10.publicvoidshowSkin(){
11.System.out.println("Style="+factory.getStyle().showStyle()+”,color="+factory,getCo
lor().showColor());
12.)
13.}
14.〃軟件Style
15.interfaceStyle(){
16.publicvoidshowStyle();
17.}
18.//IOSstyle
19.classlOSStyleimplementsStyle{
20.publicvoidshowStyle(){
21.System.out.println(/zThisisIOSstyle");
22.}
23.}
24.//Androidstyle
25.classAndroidStyleimplementsStyle{
26.publicvoidshowStyle(){
27.System.out.println(z/ThisisAndroidstyle");
28.}
29.}
30.〃軟件Color
31.interfaceColor(){
32.publicvoidshowColor();
33.}
34.//IOScolor
35.classlOSColorimplementsColor{
36.publicvoidshowColor(){
37.System.out.println(/zThisisIOScolor");
38.}
39.}
40.//Androidcolor
41.classAndroidColorimplementsColor{
42.publicvoidshowColor(){
43.System.out.println(/zThisisAndroidcolor");
44.}
45.)
46.〃抽象皮膚工廠
47.interfaceSkinFactory{
48.publicStylegetStyle();
49.publicColorgetColor();
50.}
51.//IOS皮膚工廠
52.classlOSSkinFactoryimplementsSkinFactory{
53.publicStylegetStyle(){
54.returnnewIOSStyle();
55.}
56.publicColorgetColor(){
57.returnnewIOSColor();
58.}
59.}
60.//Android皮膚工廠
61.classAndroidSkinFactoryimplementsSkinFactory{
62.publicStylegetStyle(){
63.returnnewAndroidStyle();
64.}
65.publicColorgetColor(){
66.returnnewAndroidColor();
67.}
68.}
69.publicclassSkinDemo{
70.publicstaticvoidmain(String[]args){
71.〃顯示一套IOS皮膚
72.Skinskin=newSkin(newIOSSkinFactory());
73.skin.showSkin();
74.〃換一套Android的皮膚
75.skin.setSkinFactory(newAndroidSkinFactoryO);
76.skin.showSkin();
77.}
78.}
抽象工廠指定了產(chǎn)品組合形式,具體的工廠產(chǎn)生具體的產(chǎn)品,抽象工廠適用于多個產(chǎn)品相互
組合的情況。
(3).工廠方法模式:
工廠方法中也只包含一個抽象產(chǎn)品類,抽象產(chǎn)品類可以派生出多個具體產(chǎn)品類。
工廠方法定義一個用于創(chuàng)建產(chǎn)品的接口,讓子類決定實(shí)例化哪一個類,使得類的
實(shí)例化延遲到子類。
^A
ConcreateProductA
ConcreateFactoryA
T
+operationlO:void
+ereate0:Product
+operation2Q:void
ConcreateProductB
ConcreateFactoryB
+operationlO:void
+ereate0:Product
+operation?。:void
工廠方法模式例子如下:
[java]viewplaincopy
1.〃汽車接口
2.interfaceICar{
3.publicvoidrun();
4.}
5.〃奔馳車
6.classBenzCarimplementsICar{
7.publicvoidrun(){
8.System.out.println(/zBenzcarrun");
9.}
10.}
n.〃寶馬車
12.classBMWCarimplementsICar{
13.publicvoidrun(){
14.System.out.println(zzBMWcarrun?,);
15.)
16.}
17.〃抽象汽車工廠
18.abstractclassCarFactory{
19.publicabstractICarcreateCar();
20.}
21.〃奔馳車工廠
22.classBenzCarFactoryextendsCarFactory{
23.publicICarcreateCar(){
24.returnnewBenzCar();
25.}
26.}
27.〃寶馬車工廠
28.classBMWCarFactoryextendsCarFactory{
29.publicICarcreateCar(){
30.returnnewBMWCar();
31.}
32.}
33.publicclassFactoryMethodDemo{
34.publicstaticvoidmain(String[]args){
35.CarFactoryfactory=newBenzCarFactory();
36.ICarcar=factory.createCar();
37.car.run();
38.factory=newBMWCarFactoryO;
39.car=factory.createCar();
40.car.run();
41.}
42.}
工廠模式中,重要的是工廠類,而不是產(chǎn)品類。產(chǎn)品類可以是多種形式,多層繼
承或者是單個類都是可以的。但要明確的,工廠模式的接口只會返回一種類型的
實(shí)例,這是在設(shè)計產(chǎn)品類的時候需要注意的,最好是有父類或者共同實(shí)現(xiàn)的接口。
使用工廠模式,返回的實(shí)例一定是工廠創(chuàng)建的,而不是從其他對象中獲取的。工
廠模式返回的實(shí)例可以不是新創(chuàng)建的,返回由工廠創(chuàng)建好的實(shí)例也是可以的。
三種工廠模式的區(qū)別:
簡單工廠:用來生產(chǎn)同一等級結(jié)構(gòu)中的任意產(chǎn)品,對于增加新的產(chǎn)品,無能為
力。
工廠方法:用來生產(chǎn)同一等級結(jié)構(gòu)中的固定產(chǎn)品,支持增加任意產(chǎn)品。
抽象工廠:用來生產(chǎn)不同產(chǎn)品族(由不同產(chǎn)品組合成的一套產(chǎn)品)的全部產(chǎn)品,
對于增加新的產(chǎn)品,無能為力;支持增加產(chǎn)品族。
Prototype設(shè)計模式
Prototype原型設(shè)計模式是指用原型實(shí)例指定創(chuàng)建對象的種類,并且通過拷貝這
些原型來創(chuàng)建新的對象。Prototype原型模式允許一個對象再創(chuàng)建另外一個可定
制的對象,根本無需知道任何關(guān)于對象創(chuàng)建的細(xì)節(jié)。
Prototype模式例子如下:
[java]viewplaincopy
1.〃抽象原型類
2.abstractclassShapeimplementsColneable{
3.StringshapeName;
4.publicStringgetShapeName(){
5.retunshapeName;
6.)
7.publicvoidsetShapeName(StringshapeName){
8.this.shapeName=shapeName;
9.)
10.〃實(shí)現(xiàn)了Colneable接口的類,可以使用clone。方法復(fù)制對象
11.publicObjectclone(){
12.try{
13.returnsuper.clone();
14.}catch(CloneNotSupportedExceptione){
15.System.eirprintln(〃此對象不支持復(fù)制〃);
16.}
17.returnnull;
18.}
19.}
20.〃具體原型類
21.pubicclassCircleextendsShape{
22.publicCircle(){
23.setShapeName(/zCircleshape");
24.}
25.publicstaticvoidmain(String[]args){
26.Shapeshape=newCircle();
27.System.out.println(shape.getShapeName());
28.〃通過clone。方法獲得一個對象拷貝
29.Shapeshape2=(Shape)shape.clone();
30.System.out.println(shape2.getShapeName());
31.}
32.}
clone。方法是在Object中定義的,而且是protected的,只有實(shí)現(xiàn)了Cloneable
接口的類才可以在其實(shí)例上調(diào)用clone。方法,否則會拋出
CloneNotSupportException0
為了獲取對象的一份拷貝,我們可以利用Object類的clone。方法,也可以實(shí)
現(xiàn)Cloneable接口,覆蓋基類的clone()方法,在clone。方法中,調(diào)用
super,clone()。
Cloneable接口是一個標(biāo)記接口,也就是沒有任何內(nèi)容,定義如下:
[java]viewplaincopy
1.packagejava.lang;
2.pubilcinterfaceCloneable{
3.)
更多有關(guān)java拷貝方面的內(nèi)容請參考
http://blog.csdn.net/chjttony/article/details/7477346
克隆只是實(shí)現(xiàn)Prototype原型模式的一種方法,也可以直接通過new對象的方式
創(chuàng)建原型實(shí)例,二者區(qū)別在于:
(1).通過new方式創(chuàng)建的原型和現(xiàn)存的實(shí)例對象沒有任何聯(lián)系。
(2).通過克隆方法創(chuàng)建的原型,雖然也是創(chuàng)建新對象,但是將原型實(shí)例對象的數(shù)
據(jù)復(fù)制到了新的對象中,相當(dāng)于使用被克隆對象的數(shù)據(jù)作為克隆對象的初始數(shù)
據(jù)。
Prototype原型設(shè)計模式和Singleton單類設(shè)計模式是相對的,單類模式中,在
整個程序生命周期里,單類模式類的實(shí)例對象只有一個。而Prototype原型設(shè)計
模式則正好相反,每次都返回的是原型類的不同實(shí)例對象。
Java中的深拷貝和淺拷貝
1.淺拷貝與深拷貝概念
⑴淺拷貝(淺克?。?/p>
淺拷貝又叫淺復(fù)制,將對象中的所有字段復(fù)制到新的對象(副本)中。其中,
值類型字段(java中8中原始類型)的值被復(fù)制到副本中后,在副本中的修改不
會影響到源對象對應(yīng)的值。而引用類型的字段被復(fù)制到副本中的還是引用類型的
引用,而不是引用的對象,在副本中對引用類型的字段值做修改會影響到源對象
本身。
淺拷貝簡單歸納就是只復(fù)制一個對象,對象內(nèi)部存在指向其他對象,數(shù)組或引用
則不復(fù)制。
⑵深拷貝(深克?。?/p>
將對象中的所有字段復(fù)制到新的對象中。不過,無論是對象的值類型字段,還
是引用類型字段,都會被重新創(chuàng)建并賦值,對于副本的修改,不會影響到源對象
本身。
深拷貝簡單歸納就是對象內(nèi)部引用的對象均復(fù)制。
2.Java中的clone()方法
(1)clone。方法將對象復(fù)制了一份并返回給調(diào)用者。一般而言,clone。方法滿
足下面規(guī)范:
①對任何的對象x,都有x.clone。!=x;〃克隆對象與原對象不是同一個對象
②對任何的對象x,都有x.clone().getClass()==x.getClass();〃克隆對象與
原對象的類型一樣
③如果對象x的equals()方法定義恰當(dāng),那么x.clone().equals(x);應(yīng)該成立。
(2)Java中對象的克隆
clone()方法是在Object中定義的,而且是protected的,只有實(shí)現(xiàn)了Cloneable
接口的類才可以在其實(shí)例上調(diào)用clone。方法,否則會拋出
CloneNotSupportException0
為了獲取對象的一份拷貝,我們可以利用Object類的clone。方法,也可以實(shí)
現(xiàn)Cloneable接口,覆蓋基類的clone()方法,在clone。方法中,調(diào)用
super,clone()。
Cloneable接口是一個標(biāo)記接口,也就是沒有任何內(nèi)容,定義如下:
packagejava,lang;
publicinterfaceCloneable{
)
例子代碼如下:
[java]viewplaincopy
1.classStudentimplementsCloneable
2.(
3.Stringname;
4.intage;
5.Student(Stringname,intage){
6.=name;
7.this.age=age;
8.)
9.publicObjectclone(){
10.Objecto=null;
11.try{
12.//Object中的clone。識別出你要復(fù)制的是哪一個對象
13.o=(Student)super.clone();
14.}catch(CloneNotSupportedExceptione){
15.System.out.println(e.toString());
16.}
17.returno;
18.}
19.}
20.publicstaticvoidmain(String[]args){
21.Studentsl=newStudent("zhangsan",18);
22.Students2=(Student)sl.clone();
23.="lisi";
24.s2.age=20;
25.System.out.println("name="++","+"age="+sl.age);//>g^^^2后,不影響學(xué)生
1的值。
26.}
說明:
①為什么我們在派生類中覆蓋Object的clone()方法時,一定要調(diào)用
super,clone()呢?
在運(yùn)行時刻,Object中的clone。識別出你要復(fù)制的是哪一個對象,然后為此對
象分配空間,并進(jìn)行對象的復(fù)制,將原始對象的內(nèi)容一一復(fù)制到新對象的存儲空
間中。
②繼承自java.lang.Object類的clone()方法是淺復(fù)制。以下代碼可以證明:
[java]viewplaincopy
1.//Professor沒有實(shí)現(xiàn)Cloneable接口,默認(rèn)使用java.lang.Object類的clone。方法
2.classProfessor{
3.Stringname;
4.intage;
5.Professor(Stringname,intage){
6.=name;
7.this.age=age;
8.}
9.)
10."Student實(shí)現(xiàn)了Cloneable接口
11.classStudentimplementsCloneable{
12.Stringname;〃常量對象。
13.intage;
14.Professorp;
15.Student(Stringname,intage,Professorp){
16.=name;
17.this.age=age;
18.this.p=p;
19.}
20.publicObjectclone(){
21.Studento=null;
22.try{
23.o=(Student)super.clone();
24.}catch(CloneNotSupportedExceptione){
25.System.out.println(e.toString());
26.}
27.〃使用Object類的clone。方法
28.o.p=(Professo
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 小班家長健康教育實(shí)施要點(diǎn)
- 健康素食課件下載安裝
- 獲嘉縣初二數(shù)學(xué)試卷
- 合江小學(xué)五年級數(shù)學(xué)試卷
- 健康管理題講解課件視頻
- 《網(wǎng)絡(luò)綜合布線》教案 項(xiàng)目5任務(wù)3 管道和橋架工程施工
- 湖北省天門市天門外國語2025年物理高一下期末調(diào)研模擬試題含解析
- 加氫裂解汽油項(xiàng)目節(jié)能評估報告(節(jié)能專用)
- 浙江省工業(yè)固定資產(chǎn)投資項(xiàng)目節(jié)能評估報告審查程序
- 健康知識星球創(chuàng)意畫課件
- 3.5-跨學(xué)科實(shí)踐:探索廚房中的物態(tài)變化問題(課件)八年級物理上冊(人教版2024)
- 2023-2024學(xué)年上海市普陀區(qū)三年級(上)期末數(shù)學(xué)試卷
- 居家養(yǎng)老上門服務(wù)投標(biāo)文件
- 短劇演員合同范本
- 2mm土工膜長絲土工布檢測報告合格證
- 鼻炎膏的透皮吸收機(jī)制研究
- 金融市場業(yè)務(wù)
- DB11-T 1979-2022 住宅廚衛(wèi)排氣道系統(tǒng)應(yīng)用技術(shù)標(biāo)準(zhǔn)
- 物 理2024-2025學(xué)年人教版初中物理八年級上冊各章節(jié)知識點(diǎn)講解
- 高級衛(wèi)生專業(yè)技術(shù)資格考試慢性非傳染性疾病控制(088)(正高級)試題與參考答案(2024年)
- 風(fēng)險分級管控責(zé)任清單(路面工程)
評論
0/150
提交評論