第2章簡單工廠模式_第1頁
第2章簡單工廠模式_第2頁
第2章簡單工廠模式_第3頁
第2章簡單工廠模式_第4頁
第2章簡單工廠模式_第5頁
已閱讀5頁,還剩42頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第2章簡單工廠模式(SimpleFactory)

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

創(chuàng)建型模式簡單工廠模式(SimpleFactory)

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

如何使用接口?假設(shè)有一個接口Api,然后有一個類Impl實現(xiàn)它,在客戶端怎么用這個接口呢?通常都是在客戶端創(chuàng)建一個Impl的實例,把它賦值給一個Api接口類型的變量,然后客戶端就可以通過這個變量來操作接口的功能不用模式的解決方案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("測試!");

}

}

Api

api

=

new

Impl();

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

publicConcreteProduct(){}}publicclassCreator{

publicProductfactory(){

returnnewConcreteProduct();

}}使用簡單工廠重寫前面的示例

1)接口Api和實現(xiàn)類Impl都和前面的示例一樣2)新創(chuàng)建一個簡單工廠的對象,示例代碼//工廠類,用來創(chuàng)造Api對象

public

class

Factory

{

public

static

Api

createApi(){

return

new

Impl();

}

}

3)使用簡單工廠public

class

Client

{

public

static

void

main(String[]

args)

{

//重要改變,沒有new

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

Api

api

=

Factory.createApi();

api.test1("測試!");

}

}

例1

假設(shè)有一個音樂盒工廠,購買音樂盒的客人無需知道音樂盒是如何制作的,他只要知道如何播放音樂盒就可以了

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

publicinterfaceIMusicBox{

publicvoidplay();

}publicclassPianoBoximplementsIMusicBox{

publicvoidplay(){

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

}

}publicclassViolinBoximplementsIMusicBox{

publicvoidplay(){

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

}

}

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

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

}

}使用Java的Reflection機制來產(chǎn)生實例,以后即使修改程序,客戶端程序也不用更改

publicclassMusicBoxDemo{

publicstaticvoidmain(String[]args)throwsException{

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

}publicstaticvoidplayMusicBox(IMusicBoxmusicBox){

musicBox.play();

}

}

客戶端只依賴于IMusicBox接口,改變createMusicBox()中的實作方式,對客戶端沒有影響

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

1)在運行時判斷任意一個對象所屬的類;

2)在運行時構(gòu)造任意一個類的對象;

3)在運行時判斷任意一個類所具有的成員變量和方法(含私有屬性);

4)在運行時調(diào)用任意一個對象的方法;

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

在JDK類庫中,主要由以下類來實現(xiàn)Java反射機制,這些類都位于java.lang.reflect包中。Class類:代表一個類。

Field類:代表類的屬性。

Method類:代表類的方法。

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

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

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

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

例2

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

豐收的果園(客戶端)

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

FruitGardenergardener=newFruitGardener();

FruitIFgrape=gardener.factory("grape");

FruitIFapple=gardener.factory("apple");

FruitIFstrawberry=gardener.factory("strawberry");

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

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

publicinterfaceFruitIF{

voidgrow();

voidharvest();

voidplant();

Stringcolor=null;

Stringname=null;

}Apple類

萍果是多年生木本植物,因此具備樹齡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類

葡萄分為有籽與無籽兩種,因此具有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類publicclassStrawberryimplementsFruitIF{

publicvoidgrow(){

log("Strawberryisgrowing...");

}

publicvoidharvest(){

log("Strawberryhasbeenharvested.");

}

publicvoidplant(){

log("Strawberryhasbeenplanted.");

}

publicstaticvoidlog(Stringmsg){

System.out.println(msg);

}

}FruitGardener類publicclassFruitGardener{

publicFruitIF

factory(Stringwhich)throwsBadFruitException

{

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

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

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

else{thrownewBadFruitException("Badfruitrequest");}

}

}BadFruitException類publicclassBadFruitExceptionextendsException{

publicBadFruitException(Stringmsg{super(msg);})

}問題1

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

溫馨提示

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

評論

0/150

提交評論