第2章简单工厂模式(SimpleFactory)(静态工厂方法模式(StaticFactoryMethod))创建型模式创建型模式概述–创建型模式在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性–创建型模式隐藏类实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的创建型模式–简单工厂模式(SimpleFactory)–工厂方法模式(FactoryMethod)–抽象工厂模式(AbstractFactory)–建造者模式(Builder)–原型模式(Prototype)–单例模式(Singleton)创建型模式类别工厂模式①工厂模式将大量有共同接口的类实例化,而且不必事先知道每次是要实例化哪一个类的模式(工厂模式可以动态决定将哪一个类实例化)②工厂模式有以下几种形态:简单工厂(SimpleFactory)模式工厂方法(FactoryMethod)模式抽象工厂(AbstractFactory)模式如何使用接口?假设有一个接口Api,然后有一个类Impl实现它,在客户端怎么用这个接口呢?通常都是在客户端创建一个Impl的实例,把它赋值给一个Api接口类型的变量,然后客户端就可以通过这个变量来操作接口的功能不用模式的解决方案publicinterfaceApi{publicvoidtest1(Strings);}publicclassImplimplementsApi{publicvoidtest1(Strings){System.out.println(Theinputs==+s);}}publicclassClient{publicstaticvoidmain(String[]args){Apiapi=newImpl();api.test1(测试!);}}Apiapi=newImpl();在客户端调用的时候,客户端不但知道接口,同时还知道具体的实现就是Impl。而接口的思想是“封装隔离”,而Impl这个实现类,应该是被接口Api封装并同客户端隔离开的,也就是说,客户端根本就不应该知道具体的实现类是Impl。有何问题?问题描述:在Java编程中,出现只知接口而不知实现,该怎么办?有何问题?解决方案就是简单工厂简单工厂模式(SimpleFactory)(静态工厂方法(StaticFactoryMethod))提供一个创建对象实例的功能,而无需关心其具体实现。被创建实例的类型可以是接口、抽象类、具体类简单工厂定义分析上面的问题,虽然不能让模块外部知道模块内的具体实现,但是模块内部是可以知道实现类的,而且创建接口是需要具体实现类的是否可以在模块内部新建一个类,在这个类里面来创建接口,然后把创建好的接口返回给客户端,这样外部应用就只需要根据这个类来获取相应的接口对象,然后就可以操作接口定义的方法了应用简单工厂来解决的思路通过SimpleFactory类生产产品,而对客户端隐藏产品产生的细节实作时定义一个产品接口,并透过特定静态方法来建立成品SimpleFactory类根据传入的参数决定创建出哪一种产品类的实例一个工厂类封装很多类的实例化(同一接口)简单工厂模式简单工厂模式简单工厂模式的类图结构UML工厂类角色Creator:工厂类在客户端的直接调用下,创建产品对象并返回该对象抽象产品角色Product:是工厂类所创建对象的父类或它们共同的接口具体产品角色ConcreteProduct:工厂类所创建的任何对象都是这个角色的实例说明publicinterfaceProduct{}publicclassConcreteProductimplementsProduct{publicConcreteProduct(){}}publicclassCreator{publicProductfactory(){returnnewConcreteProduct();}}使用简单工厂重写前面的示例1)接口Api和实现类Impl都和前面的示例一样2)新创建一个简单工厂的对象,示例代码//工厂类,用来创造Api对象publicclassFactory{publicstaticApicreateApi(){returnnewImpl();}}3)使用简单工厂publicclassClient{publicstaticvoidmain(String[]args){//重要改变,没有newImpl()了,取而代之Factory.createApi()Apiapi=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()中的实作方式,对客户端没有影响1.Reflection是Java被视为动态(或准动态)语言的一个关键性质。2.Java反射机制主要提供了以下功能:1)在运行时判断任意一个对象所属的类;2)在运行时构造任意一个类的对象;3)在运行时判断任意一个类所具有的成员变量和方法(含私有属性);4)在运行时调用任意一个对象的方法;5)生成动态代理。1.在JDK类库中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中。•Class类:代表一个类。•Field类:代表类的属性。•Method类:代表类的方法。•Constructor类:代表类的构造方法。•Array类:提供了动态创建数组,以及访问数组元素的静态方法。•Proxy类和InvocationHandler接口:提供了生成动态代理类及其实例的方法。Q1:在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?Q2:C++?动态语言?有一个描述你的后花园的系统,在你的后花园里有各种的花,但还没有水果。你现在要往你的系统里引进一些新的类,用来描述下列的水果:葡萄Grapes草莓Strawberry萍果Apple例2UML类别图作为小花园的主人兼园丁,也是系统的一部分,自然要由一个合适的类来代表,这个类就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{publicFruitIFfactory(S