第2章簡(jiǎn)單工廠(chǎng)模式_第1頁(yè)
第2章簡(jiǎn)單工廠(chǎng)模式_第2頁(yè)
第2章簡(jiǎn)單工廠(chǎng)模式_第3頁(yè)
第2章簡(jiǎn)單工廠(chǎng)模式_第4頁(yè)
第2章簡(jiǎn)單工廠(chǎng)模式_第5頁(yè)
已閱讀5頁(yè),還剩42頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第2章簡(jiǎn)單工廠(chǎng)模式(SimpleFactory)

(靜態(tài)工廠(chǎng)方法模式(StaticFactoryMethod))創(chuàng)建型模式創(chuàng)建型模式概述創(chuàng)建型模式在創(chuàng)建什么(What),由誰(shuí)創(chuàng)建(Who),何時(shí)創(chuàng)建(When)等方面都為軟件設(shè)計(jì)者提供了盡可能大的靈活性創(chuàng)建型模式隱藏類(lèi)實(shí)例的創(chuàng)建細(xì)節(jié),通過(guò)隱藏對(duì)象如何被創(chuàng)建和組合在一起達(dá)到使整個(gè)系統(tǒng)獨(dú)立的目的

創(chuàng)建型模式簡(jiǎn)單工廠(chǎng)模式(SimpleFactory)

工廠(chǎng)方法模式(FactoryMethod)抽象工廠(chǎng)模式(AbstractFactory)建造者模式(Builder)原型模式(Prototype)單例模式(Singleton)創(chuàng)建型模式類(lèi)別工廠(chǎng)模式工廠(chǎng)模式將大量有共同接口的類(lèi)實(shí)例化,而且不必事先知道每次是要實(shí)例化哪一個(gè)類(lèi)的模式(工廠(chǎng)模式可以動(dòng)態(tài)決定將哪一個(gè)類(lèi)實(shí)例化)工廠(chǎng)模式有以下幾種形態(tài):簡(jiǎn)單工廠(chǎng)(SimpleFactory)模式工廠(chǎng)方法(FactoryMethod)模式抽象工廠(chǎng)(AbstractFactory)模式

如何使用接口?假設(shè)有一個(gè)接口Api,然后有一個(gè)類(lèi)Impl實(shí)現(xiàn)它,在客戶(hù)端怎么用這個(gè)接口呢?通常都是在客戶(hù)端創(chuàng)建一個(gè)Impl的實(shí)例,把它賦值給一個(gè)Api接口類(lèi)型的變量,然后客戶(hù)端就可以通過(guò)這個(gè)變量來(lái)操作接口的功能不用模式的解決方案public

interface

Api

{

public

void

test1(String

s);

}

public

class

Impl

implements

Api{

public

void

test1(String

s)

{

System.out.println("The

input

s=="+s);

}

}

public

class

Client

{

public

static

void

main(String[]

args)

{

Api

api

=

new

Impl();

api.test1("測(cè)試!");

}

}

Api

api

=

new

Impl();

在客戶(hù)端調(diào)用的時(shí)候,客戶(hù)端不但知道接口,同時(shí)還知道具體的實(shí)現(xiàn)就是Impl。而接口的思想是“封裝隔離”,而Impl這個(gè)實(shí)現(xiàn)類(lèi),應(yīng)該是被接口Api封裝并同客戶(hù)端隔離開(kāi)的,也就是說(shuō),客戶(hù)端根本就不應(yīng)該知道具體的實(shí)現(xiàn)類(lèi)是Impl。有何問(wèn)題?問(wèn)題描述:在Java編程中,出現(xiàn)只知接口而不知實(shí)現(xiàn),該怎么辦?有何問(wèn)題?解決方案就是簡(jiǎn)單工廠(chǎng)簡(jiǎn)單工廠(chǎng)模式(SimpleFactory)(靜態(tài)工廠(chǎng)方法(StaticFactoryMethod))提供一個(gè)創(chuàng)建對(duì)象實(shí)例的功能,而無(wú)需關(guān)心其具體實(shí)現(xiàn)。被創(chuàng)建實(shí)例的類(lèi)型可以是接口、抽象類(lèi)、具體類(lèi)簡(jiǎn)單工廠(chǎng)定義分析上面的問(wèn)題,雖然不能讓模塊外部知道模塊內(nèi)的具體實(shí)現(xiàn),但是模塊內(nèi)部是可以知道實(shí)現(xiàn)類(lèi)的,而且創(chuàng)建接口是需要具體實(shí)現(xiàn)類(lèi)的是否可以在模塊內(nèi)部新建一個(gè)類(lèi),在這個(gè)類(lèi)里面來(lái)創(chuàng)建接口,然后把創(chuàng)建好的接口返回給客戶(hù)端,這樣外部應(yīng)用就只需要根據(jù)這個(gè)類(lèi)來(lái)獲取相應(yīng)的接口對(duì)象,然后就可以操作接口定義的方法了應(yīng)用簡(jiǎn)單工廠(chǎng)來(lái)解決的思路通過(guò)SimpleFactory類(lèi)生產(chǎn)產(chǎn)品,而對(duì)客戶(hù)端隱藏產(chǎn)品產(chǎn)生的細(xì)節(jié)實(shí)作時(shí)定義一個(gè)產(chǎn)品接口,并透過(guò)特定靜態(tài)方法來(lái)建立成品SimpleFactory類(lèi)根據(jù)傳入的參數(shù)決定創(chuàng)建出哪一種產(chǎn)品類(lèi)的實(shí)例一個(gè)工廠(chǎng)類(lèi)封裝很多類(lèi)的實(shí)例化(同一接口)簡(jiǎn)單工廠(chǎng)模式簡(jiǎn)單工廠(chǎng)模式簡(jiǎn)單工廠(chǎng)模式的類(lèi)圖結(jié)構(gòu)UML工廠(chǎng)類(lèi)角色Creator:工廠(chǎng)類(lèi)在客戶(hù)端的直接調(diào)用下,創(chuàng)建產(chǎn)品對(duì)象并返回該對(duì)象抽象產(chǎn)品角色Product:是工廠(chǎng)類(lèi)所創(chuàng)建對(duì)象的父類(lèi)或它們共同的接口具體產(chǎn)品角色ConcreteProduct:工廠(chǎng)類(lèi)所創(chuàng)建的任何對(duì)象都是這個(gè)角色的實(shí)例說(shuō)明publicinterfaceProduct{}publicclassConcreteProductimplementsProduct{

publicConcreteProduct(){}}publicclassCreator{

publicProductfactory(){

returnnewConcreteProduct();

}}使用簡(jiǎn)單工廠(chǎng)重寫(xiě)前面的示例

1)接口Api和實(shí)現(xiàn)類(lèi)Impl都和前面的示例一樣2)新創(chuàng)建一個(gè)簡(jiǎn)單工廠(chǎng)的對(duì)象,示例代碼//工廠(chǎng)類(lèi),用來(lái)創(chuàng)造Api對(duì)象

public

class

Factory

{

public

static

Api

createApi(){

return

new

Impl();

}

}

3)使用簡(jiǎn)單工廠(chǎng)public

class

Client

{

public

static

void

main(String[]

args)

{

//重要改變,沒(méi)有new

Impl()了,取而代之Factory.createApi()

Api

api

=

Factory.createApi();

api.test1("測(cè)試!");

}

}

例1

假設(shè)有一個(gè)音樂(lè)盒工廠(chǎng),購(gòu)買(mǎi)音樂(lè)盒的客人無(wú)需知道音樂(lè)盒是如何制作的,他只要知道如何播放音樂(lè)盒就可以了

UML類(lèi)別圖MusicBoxDemo代表客戶(hù)角色,它依賴(lài)于IMusicBox接口,而不關(guān)心特定的實(shí)作如何產(chǎn)生IMusicBox的實(shí)例由MusicBoxFactory完成

publicinterfaceIMusicBox{

publicvoidplay();

}publicclassPianoBoximplementsIMusicBox{

publicvoidplay(){

System.out.println(“播放鋼琴音樂(lè):)");

}

}publicclassViolinBoximplementsIMusicBox{

publicvoidplay(){

System.out.println(“播放小提琴音樂(lè)");

}

}

publicclassMusicBoxFactory{publicstaticIMusicBoxcreateMusicBox(Stringname)throwsInstantiationException,IllegalAccessException,ClassNotFoundException{

return(IMusicBox)Class.forName(name).newInstance();

}

}使用Java的Reflection機(jī)制來(lái)產(chǎn)生實(shí)例,以后即使修改程序,客戶(hù)端程序也不用更改

publicclassMusicBoxDemo{

publicstaticvoidmain(String[]args)throwsException{

playMusicBox(MusicBoxFactory.createMusicBox("PianoBox")); playMusicBox(MusicBoxFactory.createMusicBox("ViolinBox"));

}publicstaticvoidplayMusicBox(IMusicBoxmusicBox){

musicBox.play();

}

}

客戶(hù)端只依賴(lài)于IMusicBox接口,改變createMusicBox()中的實(shí)作方式,對(duì)客戶(hù)端沒(méi)有影響

Reflection是Java被視為動(dòng)態(tài)(或準(zhǔn)動(dòng)態(tài))語(yǔ)言的一個(gè)關(guān)鍵性質(zhì)。Java反射機(jī)制主要提供了以下功能:

1)在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類(lèi);

2)在運(yùn)行時(shí)構(gòu)造任意一個(gè)類(lèi)的對(duì)象;

3)在運(yùn)行時(shí)判斷任意一個(gè)類(lèi)所具有的成員變量和方法(含私有屬性);

4)在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法;

5)生成動(dòng)態(tài)代理。

在JDK類(lèi)庫(kù)中,主要由以下類(lèi)來(lái)實(shí)現(xiàn)Java反射機(jī)制,這些類(lèi)都位于java.lang.reflect包中。Class類(lèi):代表一個(gè)類(lèi)。

Field類(lèi):代表類(lèi)的屬性。

Method類(lèi):代表類(lèi)的方法。

Constructor類(lèi):代表類(lèi)的構(gòu)造方法。

Array類(lèi):提供了動(dòng)態(tài)創(chuàng)建數(shù)組,以及訪(fǎng)問(wèn)數(shù)組元素的靜態(tài)方法。

Proxy類(lèi)和InvocationHandler接口:提供了生成動(dòng)態(tài)代理類(lèi)及其實(shí)例的方法。

Q1:在Java運(yùn)行時(shí)環(huán)境中,對(duì)于任意一個(gè)類(lèi),能否知道這個(gè)類(lèi)有哪些屬性和方法?對(duì)于任意一個(gè)對(duì)象,能否調(diào)用它的任意一個(gè)方法?Q2:C++?動(dòng)態(tài)語(yǔ)言?有一個(gè)描述你的后花園的系統(tǒng),在你的后花園里有各種的花,但還沒(méi)有水果。你現(xiàn)在要往你的系統(tǒng)里引進(jìn)一些新的類(lèi),用來(lái)描述下列的水果:葡萄Grapes草莓Strawberry萍果Apple

例2

UML類(lèi)別圖作為小花園的主人兼園丁,也是系統(tǒng)的一部分,自然要由一個(gè)合適的類(lèi)來(lái)代表,這個(gè)類(lèi)就FruitGardener類(lèi)。園丁的工作(簡(jiǎn)單工廠(chǎng))FruitGardener類(lèi)會(huì)根據(jù)要求,創(chuàng)建出不同水果類(lèi)的實(shí)例園丁就如同一個(gè)可以創(chuàng)建水果產(chǎn)品的工廠(chǎng)一樣如果接到不合法的要求,FruitGardener類(lèi)會(huì)給出例外BadFruitException。

豐收的果園(客戶(hù)端)

使用時(shí),只須調(diào)用FruitGardener的factory()try{

FruitGardenergardener=newFruitGardener();

FruitIFgrape=gardener.factory("grape");

FruitIFapple=gardener.factory("apple");

FruitIFstrawberry=gardener.factory("strawberry");

...}catch(BadFruitExceptione){...}

FruitIF接口接口FruitIF確定水果類(lèi)必備的方法:種植plant(),生長(zhǎng)grow(),以及收獲harvest()。

publicinterfaceFruitIF{

voidgrow();

voidharvest();

voidplant();

Stringcolor=null;

Stringname=null;

}Apple類(lèi)

萍果是多年生木本植物,因此具備樹(shù)齡treeAge性質(zhì)publicclassAppleimplementsFruitIF{

publicvoidgrow(){

log("Appleisgrowing...");

}

publicvoidharvest(){

log("Applehasbeenharvested.");

}

publicvoidplant(){

log("Applehasbeenplanted.");

}

publicstaticvoidlog(Stringmsg){

System.out.println(msg);

}

publicintgetTreeAge(){returntreeAge;}

publicvoidsetTreeAge(inttreeAge){this.treeAge=treeAge;}

privateinttreeAge;

}Grape類(lèi)

葡萄分為有籽與無(wú)籽兩種,因此具有seedful性質(zhì)publicclassGrapeimplementsFruitIF{

publicvoidgrow(){

log("Grapeisgrowing...");

}

publicvoidharvest(){

log("Grapehasbeenharvested.");

}

publicvoidplant(){

log("Grapehasbeenplanted.");

}

publicstaticvoidlog(Stringmsg){

System.out.println(msg);

}

publicbooleangetSeedful(){

returnseedful;

}

publicvoidsetSeedful(booleanseedful){

this.seedful=seedful;

}

privatebooleanseedful;

}Strawberry類(lèi)publicclassStrawberryimplementsFruitIF{

publicvoidgrow(){

log("Strawberryisgrowing...");

}

publicvoidharvest(){

log("Strawberryhasbeenharvested.");

}

publicvoidplant(){

log("Strawberryhasbeenplanted.");

}

publicstaticvoidlog(Stringmsg){

System.out.println(msg);

}

}FruitGardener類(lèi)publicclassFruitGardener{

publicFruitIF

factory(Stringwhich)throwsBadFruitException

{

if(which.equalsIgnoreCase("apple")){returnnewApple();}

elseif(which.equalsIgnoreCase("strawberry")){returnnewStrawberry();}

elseif(which.equalsIgnoreCase("grape")){returnnewGrape();}

else{thrownewBadFruitException("Badfruitrequest");}

}

}BadFruitException類(lèi)publicclassBadFruitExceptionextendsException{

publicBadFruitException(Stringmsg{super(msg);})

}問(wèn)題1

例1和例2的代碼哪個(gè)更好?問(wèn)題2例1和例2符合開(kāi)閉原則?(對(duì)擴(kuò)展開(kāi)放,對(duì)改變關(guān)閉)數(shù)據(jù)庫(kù)開(kāi)發(fā)中的數(shù)據(jù)源選擇問(wèn)題:

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論