《第2章 简单工厂模式课件》由会员分享,可在线阅读,更多相关《第2章 简单工厂模式课件(47页珍藏版)》请在金锄头文库上搜索。
1、第2章 简单工厂模式(Simple Factory)(静态工厂方法模式(Static Factory Method),创建型模式,创建型模式概述 创建型模式在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性 创建型模式隐藏类实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的,创建型模式,简单工厂模式(Simple Factory) 工厂方法模式(Factory Method) 抽象工厂模式(Abstract Factory) 建造者模式(Builder) 原型模式(Prototype) 单例模式(Singleton
2、),创建型模式类别,工厂模式,工厂模式 将大量有共同接口的类实例化,而且不必事先知道每次是要实例化哪一个类的模式(工厂模式可以动态决定将哪一个类实例化) 工厂模式有以下几种形态: 简单工厂(Simple Factory)模式 工厂方法(Factory Method)模式 抽象工厂(Abstract Factory)模式,如何使用接口? 假设有一个接口Api,然后有一个类Impl实现它,在客户端怎么用这个接口呢?,通常都是在客户端创建一个Impl的实例,把它赋值给一个Api接口类型的变量,然后客户端就可以通过这个变量来操作接口的功能,不用模式的解决方案,publicinterfaceApi pu
3、blicvoidtest1(Strings); publicclassImplimplementsApi publicvoidtest1(Strings) System.out.println(Theinputs=+s); publicclassClient publicstaticvoidmain(Stringargs) Apiapi=newImpl(); api.test1(测试!); ,Apiapi=newImpl(); 在客户端调用的时候,客户端不但知道接口,同时还知道具体的实现就是Impl。而接口的思想是“封装隔离”,而Impl这个实现类,应该是被接口Api封装并同客户端隔离开的,也
4、就是说,客户端根本就不应该知道具体的实现类是Impl。,有何问题?,问题描述: 在Java编程中,出现只知接口而不知实现,该怎么办?,有何问题?,解决方案就是简单工厂,简单工厂模式(Simple Factory) (静态工厂方法(Static Factory Method)),提供一个创建对象实例的功能,而无需关心其具体实现。被创建实例的类型可以是接口、抽象类、具体类,简单工厂定义,分析上面的问题,虽然不能让模块外部知道模块内的具体实现,但是模块内部是可以知道实现类的,而且创建接口是需要具体实现类的 是否可以在模块内部新建一个类,在这个类里面来创建接口,然后把创建好的接口返回给客户端,这样外部
5、应用就只需要根据这个类来获取相应的接口对象,然后就可以操作接口定义的方法了,应用简单工厂来解决的思路,通过Simple Factory类生产产品,而对客户端隐藏产品产生的细节 实作时定义一个产品接口,并透过特定静态方法来建立成品 Simple Factory类根据传入的参数决定创建出哪一种产品类的实例 一个工厂类封装很多类的实例化(同一接口),简单工厂模式,简单工厂模式,简单工厂模式的类图结构UML,工厂类角色Creator:工厂类在客户端的直接调用下,创建产品对象并返回该对象,抽象产品角色Product:是工厂类所创建对象的父类或它们共同的接口,具体产品角色ConcreteProduct:工
6、厂类所创建的任何对象都是这个角色的实例,说 明,public interface Product public class ConcreteProduct implements Product public ConcreteProduct() public class Creator public Product factory() return new ConcreteProduct(); ,使用简单工厂重写前面的示例,1)接口Api和实现类Impl都和前面的示例一样 2)新创建一个简单工厂的对象,示例代码 /工厂类,用来创造Api对象 publicclassFactory publicst
7、aticApicreateApi() returnnewImpl(); ,3)使用简单工厂 publicclassClient publicstaticvoidmain(Stringargs)/重要改变,没有newImpl()了,取而代之 Factory.createApi() Apiapi=Factory.createApi(); api.test1(测试!); ,例 1,假设有一个音乐盒工厂,购买音乐盒的客人无需知道音乐盒是如何制作的,他只要知道如何播放音乐盒就可以了,UML 类别图,MusicBoxDemo代表客户角色,它依赖于IMusicBox接口,而不关心特定的实作 如何产生IMus
8、icBox的实例由MusicBoxFactory完成,public interface IMusicBox public void play(); public class PianoBox implements IMusicBox public void play() System.out.println(“播放钢琴音乐:); public class ViolinBox implements IMusicBox public void play() System.out.println(“播放小提琴音乐); ,public class MusicBoxFactory public stat
9、ic IMusicBox createMusicBox(String name) throws InstantiationException, IllegalAccessException, ClassNotFoundException return (IMusicBox) Class.forName(name).newInstance(); ,使用Java的Reflection机制来产生实例,以后即使修改程序,客户端程序也不用更改,public class MusicBoxDemo public static void main(String args) throws Exception p
10、layMusicBox(MusicBoxFactory.createMusicBox(PianoBox); playMusicBox(MusicBoxFactory.createMusicBox(ViolinBox); public static void playMusicBox(IMusicBox musicBox) musicBox.play(); 客户端只依赖于IMusicBox接口,改变createMusicBox()中的实作方式,对客户端没有影响,Reflection 是Java被视为动态(或准动态)语言的一个关键性质。 Java反射机制主要提供了以下功能: 1) 在运行时判断任意
11、一个对象所属的类;2) 在运行时构造任意一个类的对象;3) 在运行时判断任意一个类所具有的成员变量和方法(含私有属性);4) 在运行时调用任意一个对象的方法;5) 生成动态代理。,在JDK类库中, 主要由以下类来实现Java反射机制,这些类都位于 java.lang.reflect 包中。 Class类:代表一个类。 Field类:代表类的属性。 Method类:代表类的方法。 Constructor 类:代表类的构造方法。 Array类:提供了动态创建数组,以及访问数组元素的静态方法。 Proxy类和 InvocationHandler 接口:提供了生成动态代理类及其实例的方法。,Q1:在J
12、ava 运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法? Q2: C+? 动态语言?,有一个描述你的后花园的系统,在你的后花园里有各种的花,但还没有水果。你现在要往你的系统里引进一些新的类,用来描述下列的水果: 葡萄 Grapes 草莓 Strawberry 萍果 Apple,例 2,UML 类别图,作为小花园的主人兼园丁,也是系统的一部分,自然要由一个合适的类来代表,这个类就FruitGardener类。,园丁的工作(简单工厂),FruitGardener类会根据要求,创建出不同水果类的实例 园丁就如同一个可以创建水果产品的工厂一样
13、如果接到不合法的要求,FruitGardener类会给出例外BadFruitException。,丰收的果园(客户端),使用时,只须调用FruitGardener的factory() try FruitGardener gardener = new FruitGardener();FruitIF grape = gardener.factory(grape);FruitIF apple = gardener.factory(apple);FruitIF strawberry = gardener.factory(strawberry);. catch(BadFruitException e)
14、.,FruitIF接口,接口FruitIF确定水果类必备的方法: 种植plant(),生长grow(), 以及收获harvest()。 public interface FruitIF void grow();void harvest();void plant();String color = null;String name = null;,Apple类,萍果是多年生木本植物,因此具备树龄treeAge性质 public class Apple implements FruitIF public void grow() log(Apple is growing.);public void h
15、arvest() log(Apple has been harvested.);public void plant() log(Apple has been planted.);public static void log(String msg) System.out.println(msg);public int getTreeAge() return treeAge; public void setTreeAge(int treeAge) this.treeAge = treeAge; private int treeAge;,Grape类,葡萄分为有籽与无籽两种,因此具有seedful性
16、质 public class Grape implements FruitIF public void grow() log(Grape is growing.);public void harvest() log(Grape has been harvested.);public void plant() log(Grape has been planted.);public static void log(String msg) System.out.println(msg);public boolean getSeedful() return seedful;public void setSeedful(boolean seedful) this.seedful = seedful;private boolean seedful;,Strawberry类,public class Strawberry