第2章简单工厂模式_第1页
第2章简单工厂模式_第2页
第2章简单工厂模式_第3页
第2章简单工厂模式_第4页
第2章简单工厂模式_第5页
已阅读5页,还剩42页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第2章简单工厂模式(SimpleFactory)

(静态工厂方法模式(StaticFactoryMethod))创建型模式创建型模式概述创建型模式在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性创建型模式隐藏类实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的

创建型模式简单工厂模式(SimpleFactory)

工厂方法模式(FactoryMethod)抽象工厂模式(AbstractFactory)建造者模式(Builder)原型模式(Prototype)单例模式(Singleton)创建型模式类别工厂模式工厂模式将大量有共同接口的类实例化,而且不必事先知道每次是要实例化哪一个类的模式(工厂模式可以动态决定将哪一个类实例化)工厂模式有以下几种形态:简单工厂(SimpleFactory)模式工厂方法(FactoryMethod)模式抽象工厂(AbstractFactory)模式

如何使用接口?假设有一个接口Api,然后有一个类Impl实现它,在客户端怎么用这个接口呢?通常都是在客户端创建一个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();

在客户端调用的时候,客户端不但知道接口,同时还知道具体的实现就是Impl。而接口的思想是“封装隔离”,而Impl这个实现类,应该是被接口Api封装并同客户端隔离开的,也就是说,客户端根本就不应该知道具体的实现类是Impl。有何问题?问题描述:在Java编程中,出现只知接口而不知实现,该怎么办?有何问题?解决方案就是简单工厂简单工厂模式(SimpleFactory)(静态工厂方法(StaticFactoryMethod))提供一个创建对象实例的功能,而无需关心其具体实现。被创建实例的类型可以是接口、抽象类、具体类简单工厂定义分析上面的问题,虽然不能让模块外部知道模块内的具体实现,但是模块内部是可以知道实现类的,而且创建接口是需要具体实现类的是否可以在模块内部新建一个类,在这个类里面来创建接口,然后把创建好的接口返回给客户端,这样外部应用就只需要根据这个类来获取相应的接口对象,然后就可以操作接口定义的方法了应用简单工厂来解决的思路通过SimpleFactory类生产产品,而对客户端隐藏产品产生的细节实作时定义一个产品接口,并透过特定静态方法来建立成品SimpleFactory类根据传入的参数决定创建出哪一种产品类的实例一个工厂类封装很多类的实例化(同一接口)简单工厂模式简单工厂模式简单工厂模式的类图结构UML工厂类角色Creator:工厂类在客户端的直接调用下,创建产品对象并返回该对象抽象产品角色Product:是工厂类所创建对象的父类或它们共同的接口具体产品角色ConcreteProduct:工厂类所创建的任何对象都是这个角色的实例说明publicinterfaceProduct{}publicclassConcreteProductimplementsProduct{

publicConcreteProduct(){}}publicclassCreator{

publicProductfactory(){

returnnewConcreteProduct();

}}使用简单工厂重写前面的示例

1)接口Api和实现类Impl都和前面的示例一样2)新创建一个简单工厂的对象,示例代码//工厂类,用来创造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

假设有一个音乐盒工厂,购买音乐盒的客人无需知道音乐盒是如何制作的,他只要知道如何播放音乐盒就可以了

UML类别图MusicBoxDemo代表客户角色,它依赖于IMusicBox接口,而不关心特定的实作如何产生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机制来产生实例,以后即使修改程序,客户端程序也不用更改

publicclassMusicBoxDemo{

publicstaticvoidmain(String[]args)throwsException{

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

}publicstaticvoidplayMusicBox(IMusicBoxmusicBox){

musicBox.play();

}

}

客户端只依赖于IMusicBox接口,改变createMusicBox()中的实作方式,对客户端没有影响

Reflection是Java被视为动态(或准动态)语言的一个关键性质。Java反射机制主要提供了以下功能:

1)在运行时判断任意一个对象所属的类;

2)在运行时构造任意一个类的对象;

3)在运行时判断任意一个类所具有的成员变量和方法(含私有属性);

4)在运行时调用任意一个对象的方法;

5)生成动态代理。

在JDK类库中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中。Class类:代表一个类。

Field类:代表类的属性。

Method类:代表类的方法。

Constructor类:代表类的构造方法。

Array类:提供了动态创建数组,以及访问数组元素的静态方法。

Proxy类和InvocationHandler接口:提供了生成动态代理类及其实例的方法。

Q1:在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?Q2:C++?动态语言?有一个描述你的后花园的系统,在你的后花园里有各种的花,但还没有水果。你现在要往你的系统里引进一些新的类,用来描述下列的水果:葡萄Grapes草莓Strawberry萍果Apple

例2

UML类别图作为小花园的主人兼园丁,也是系统的一部分,自然要由一个合适的类来代表,这个类就FruitGardener类。园丁的工作(简单工厂)FruitGardener类会根据要求,创建出不同水果类的实例园丁就如同一个可以创建水果产品的工厂一样如果接到不合法的要求,FruitGardener类会给出例外BadFruitException。

丰收的果园(客户端)

使用时,只须调用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性质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性质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符合开闭原则?(对扩展开放,对改变关闭)数据库开发中的数据源选择问题:

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论