一、SAX
- SAX同样也有参考实现,相对DOM,其代码结构相对要复杂一些, 其中的核心是需要首先实现预定义的事件处理器
- 事件处理器由org.xml.sax.ContentHandler接口声明,在JDK中也提供了该接口的一个默认实现,叫DefaultHandler,我们在实现自定义事件处理器时可以继承该类,事件处理器中几个必要的重要方法如下:
- 常见的第三方XML解析器主要有以下几种: JDOM和DOM4J的结构非常类似JDK中提供的JAXP(即之前章节介绍的DOM和SAX的JDK参考实现),均是比较知名的开源解析组件
- JDOM
- DOM4J
- Google随Android推出的结合DOM和SAX的Pull
1 package com.chinasofti.sax; 2 3 import org.xml.sax.*; 4 import org.xml.sax.helpers.DefaultHandler; 5 6 import javax.xml.parsers.SAXParser; 7 import javax.xml.parsers.SAXParserFactory; 8 import java.io.FileInputStream; 9 10 // 事件处理器 11 class MyHandler extends DefaultHandler { 12 StringBuilder sb = new StringBuilder(); 13 // 在每次开始时都初始化字符串中内容 14 @Override 15 public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException { 16 sb = new StringBuilder(); 17 } 18 19 // 解析xml 20 @Override 21 public void characters(char[] ch, int start, int length) throws SAXException { 22 sb.append(ch,start,length); 23 } 24 25 // 26 @Override 27 public void endElement(String uri, String localName, String qName) throws SAXException { 28 // 接受元素结尾的通知 29 System.out.println(qName + "----" + sb); 30 } 31 } 32 33 // 34 class SaxParseXml{ 35 // 使用sax来解析xml文档 36 public static void main(String[] args) throws Exception { 37 // 通过saxparser工厂来获取一个saxparser对象 38 SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser(); 39 // 通过saxPaeser获得xml解析器 40 XMLReader xmlReader = saxParser.getXMLReader(); 41 // 绑定事件处理器 42 xmlReader.setContentHandler(new MyHandler()); 43 // 解析xml 44 xmlReader.parse(new InputSource(new FileInputStream("src/com/chinasofti/sax/note.xml"))); 45 } 46 }
- Pull方式将在后续的课程中详细介绍
- XML文档有什么特点?
- DOM和SAX方式解析XML有什么区别?
- XML文档构建除了一棵树,XML文档必须有一个根元素,XML节点元素都必须有一个关闭标签,XML标签对大小写敏感,XML元素必须被正确的嵌套,XML属性值必须加引号
- DOM:Document Object Model,文档对象模型,将整个文档加载进内存并分析整颗树的数据结构,根据节点元素之间的父子关系完成整棵树上所有节点的遍历,
- 优势:符合XML树的数据结构逻辑定义,可以对树结构进行修改,
- 劣势:需要完整加载文档,对于LDAP领域等能够产生超大型XML文档的环境明显不适用。
- SAX:Simple API for XML,针对XML文档的事件驱动解析引擎,逐行对文档进行分析,遇到文档的特定组成部分后回调预先定义的事件回调,
- 优势:无需预先完整加载文档,不会对程序的运行时内存造成毁灭性影响,
- 劣势:不符合XML文档的本质数据结构,只能用来解析遍历,而不能修改。
二、json
- 什么是JSON?
- JSON指的是 JavaScript 对象表示法(JavaScript Object Notation)
- JSON是轻量级的文本数据交换格式,类似 XML,JSON 比 XML 更小、更快,更易解析
- JSON独立于语言
- JSON 具有自我描述性,更易理解
- JSON和XML的异同,相同处:
- 是纯文本
- 具有"自我描述性"(人类可读)
- 具有层级结构(值中存在值)
- 不同处:
- 没有结束标签
- 更短
- 读写的速度更快
- 能够使用内建的 JavaScript eval() 方法进行解析
- 使用数组
- 不使用保留字
- JSON 语法是 JavaScript 对象表示法语法的子集:JSON 对象在大括号({})中书写,对象可以包含多个 key/value(键/值)对
- 数据在名称/值对中,名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值:
JSON 值可以是:数字(整数或浮点数)、字符串(在双引号中)、逻辑值(true 或 false)、数组、对象、null- 数据由逗号分隔
- 大括号保存对象{ }
- 中括号保存数组[ ]
- key 必须是字符串,value 可以是合法的 JSON 数据类型(字符串, 数字, 对象, 数组, 布尔值或 null)
- key 和 value 中使用冒号(:)分割
- 每个 key/value 对使用逗号(,)分割
- JSON 数组在中括号中书写,JSON 中数组值必须是合法的 JSON 数据类型(字符串, 数字, 对象, 数组, 布尔值或 null):
- Gson是Google提供的一个能够将Java对象转换成相应JSON表达形式的一个开源Java类库,当然用Gson也能将JSON字符串转换成与之等价的Java对象。Gson对于任何Java对象都有效,包括那些预先存在没有源代码的对象
- GSON对JSON的处理基本流程是什么?
创建Gson对象, 然后使用toJson将java数据类型传入参数中,返回对应的json字符串格式的数据。
使用fromJson将json字符串转换成java数据类型数据。
三、设计模式
设计模式是一套代码设计经验的总结。项目中合理的运用设计模式可以巧妙的解决很多问题
- 总体来说设计模式可以分为三大类:
- 创建型模式
- 工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
- 结构型模式
- 适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
- 行为型模式
- 策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
- 创建型模式
- 设计模式的六大原则:
- 开闭原则(Open Close Principle)
- 开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。
- 里氏代换原则(Liskov Substitution Principle)
- 里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
- 依赖倒转原则(Dependence Inversion Principle)
- 这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
- 接口隔离原则(Interface Segregation Principle)
- 这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。
- 迪米特法则,又称最少知道原则(Demeter Principle)
- 最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。
- 合成复用原则(Composite Reuse Principle)
- 合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承。
- 单例模式是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式
- 单例模式确保在一个应用程序中某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例实例。单例模式只应在有真正的“单一实例”的需求时才可使用:
- 单例类只能有一个实例
- 单例类必须自己创建自己的唯一实例
- 单例类必须给所有其他对象提供这一实例
- Java中实现单例模式可以通过两种形式实现:
- 懒汉模式(类加载时不初始化)
- 饿汉模式(在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快)
1 package com.chinasofti.Singleton; 2 3 // 单例模式 4 public class SongleTon { 5 public static void main(String[] args) { 6 // 单例模式下通过懒汉式 来获取对象 7 SongleTon1 songleTon1 = SongleTon1.newInstance(); 8 // 单例模式下通过饿汉式 来获取对象 9 SongleTon2 songleTon2 = SongleTon2.newInstance(); 10 } 11 } 12 13 // 懒汉式 调用时加载 synchronized 所以线程安全 速度慢 14 class SongleTon1 { 15 // 声明一个静态的类对象 16 private static SongleTon1 songleTon1; 17 // 私有构造方法 单例模式 防止再次创建对象 18 private SongleTon1(){} 19 // 通过静态的newInstance来获取类对象 需要同步 以防线程不安全
在创建实例时启动变慢 因为启动时会调用返回实例的一些逻辑处理代码 20 public synchronized static SongleTon1 newInstance(){ 21 if (songleTon1==null){ 22 songleTon1 = new SongleTon1(); 23 } 24 System.out.println("懒汉式"); 25 return songleTon1; 26 } 27 } 28 29 // 饿汉式 类加载时初始化 线程不安全 延时加载 30 class SongleTon2 { 31 // 声明一个静态的类对象 32 private static SongleTon2 songleTon2; 33 // 私有的构造方法 34 private SongleTon2(){} 35 // 在类加载时初始化对象 36 static { 37 songleTon2 = new SongleTon2(); 38 } 39 // 声明一个静态的newInstance方法来获取类对象 40 public static SongleTon2 newInstance(){ 41 System.out.println("饿汉式"); 42 return songleTon2; 43 } 44 } 45 46 // 静态内部类的方式实现懒汉模式 47 // 只有在第一次调用newInstance时才会实例化 也就是说内部类只加载一次 加载过程是安全的 48 class SongleTon3{ 49 // 使用静态内部类 50 private static class Songle{ 51 private static final SongleTon3 INTANCE = new SongleTon3(); 52 } 53 // 私有构造方法 54 private SongleTon3(){} 55 // 创建一个获取静态内部类中常量对象的方式 56 public static SongleTon3 newInstance(){ 57 return Songle.INTANCE; 58 } 59 } 60 61 // 使用枚举实现懒汉模式 62 //优点:使用JDK1.5提供的枚举来实现单例设计模式,不仅能避免多线程同步问题,
而且还能防止反序列化创建新的对象 63 enum SongleTon4{ 64 INSTANCE; 65 }
- 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的
- 工厂模式在一般分为三类:这三种模式从上到下逐步抽象,并且更具一般性
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
- 简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口,先来看看它的组成:
- 工厂类角色
- 这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现
- 抽象产品角色
- 它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。
- 具体产品角色
- 工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
- 工厂类角色
- 使用了简单工厂模式后,我们的程序不在“有病”,更加符合现实中的情况;而且客户端免除了直接创建产品对象的责任,而仅仅负责“消费”产品(正如暴发户所为)
- 可以从开闭原则上来分析简单工厂模式。当暴发户增加了一辆车的时候,只要符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想,因为每增加一辆车,都要在工厂类中增加相应的业务逻辑或者判断逻辑,这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的
- 随着暴发户的生意越做越大,越来越有钱,于是乎他又买了几辆豪车-兰博基尼、保时捷、悍马…,由于车辆增加了,所有的汽车都要有老司机一个人管理,年检、保险、罚单、洗车,老司机一个人实在吃不消,而且老板会吩咐老司机从周一到周六要开不同款式的车外出,这个时候老司机就不得不记住老板哪天需要开哪辆车外出,于是乎给老板提议:给每台车都聘请一个司机,每辆汽车都有一个专门的人员负责,需要外出的时候招呼我一声,我就会派相应的人员过来接老板,老板毫不犹豫的说:就这么办.......
- 工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽象工厂的子类去做。 来看下它的组成:
-
- 抽象工厂角色:
- 工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现
- 具体工厂角色:
- 含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象
- 抽象产品角色:
- 它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现
- 具体产品角色:
- 具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现
- 抽象工厂角色:
- 工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来:当有新的产品(即暴发户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代 码。可以看出工厂角色的结构也是符合开闭原则的
- 使用工厂方法模式足以应付我们可能遇到的大部分业务需求。但是当产品种类非常多时,就会出现大量的与之对应的工厂类,这不应该是我们所希望的。所以建议在这种情况下使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现
- 事实上很多时候工厂所产生的产品会划分为很多层次
- 产品族
- 位于不同产品等级结构中,功能相关联的产品组成的家族
- 如果项目中涉及到多个产品族,则可以使用抽象工厂模式,抽象工厂模式的各个角色和工厂方法的如出一辙:
- 抽象工厂角色
- 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现
- 具体工厂角色
- 它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现
- 抽象产品角色
- 它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现
- 具体产品角色
- 具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现
- 抽象工厂角色
- 抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。而且使用抽象工厂模式还要满足一下条件:
- 系统中有多个产品族,而系统一次只可能消费其中一族产品
- 同属于同一个产品族的产品以其使用
- 在抽象工厂模式中,抽象产品可能是一个或多个,从而构成一个或多个产品族。 在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式
1 package com.chinasofti.factory2; 2 3 // 抽象工厂方法 4 public class Factory2 { 5 public static void main(String[] args) throws Exception { 6 // 通过工厂构造器 实例化一个奔驰工厂 7 Factory factory = FactoryBuilder.newInstance(1); 8 // 通过奔驰工厂 实例化一个bus奔驰对象 9 BusCar busCar = factory.getBusCar(); 10 // 执行奔驰的drive方法 11 busCar.drive(); 12 // 通过奔驰工厂 实例化一个small奔驰对象 13 SmallCar smallCar = factory.getSmallCar(); 14 // 执行奔驰的drive方法 15 smallCar.drive(); 16 } 17 } 18 19 // 创建一个工厂接口 20 interface Factory{ 21 BusCar getBusCar(); 22 SmallCar getSmallCar(); 23 } 24 25 // 创建获取bus工厂或者small工厂的工厂 26 class FactoryBuilder{ 27 public static Factory newInstance(int i) throws Exception { 28 if(i==1){ 29 return new BenzFactory(); 30 }else if (i==2){ 31 return new BwmFactory(); 32 }else if (i==3){ 33 return new AudiFactory(); 34 }else { 35 throw new Exception(); 36 } 37 } 38 } 39 40 // 奔驰工厂 41 class BenzFactory implements Factory{ 42 public BusCar getBusCar(){ 43 return new BenzBusCar(); 44 } 45 46 public SmallCar getSmallCar(){ 47 return new BenzSmallCar(); 48 } 49 } 50 51 class BwmFactory implements Factory{ 52 public BusCar getBusCar(){ 53 return new BwmBusCar(); 54 } 55 56 public SmallCar getSmallCar(){ 57 return new BwmSmallCar(); 58 } 59 } 60 61 class AudiFactory implements Factory{ 62 public BusCar getBusCar(){ 63 return new AudiBusCar(); 64 } 65 public SmallCar getSmallCar(){ 66 return new AudiSmallCar(); 67 } 68 } 69 70 // 创建Car接口 71 interface Car{ 72 // 启动车 73 void drive(); 74 } 75 // Bus车 76 interface BusCar extends Car { 77 } 78 // Small车 79 interface SmallCar extends Car { 80 } 81 // 各种车 82 class BenzBusCar implements BusCar{ 83 @Override 84 public void drive() { 85 System.out.println("奔驰bus"); 86 } 87 } 88 class BenzSmallCar implements SmallCar{ 89 @Override 90 public void drive() { 91 System.out.println("奔驰小车"); 92 } 93 } 94 class BwmBusCar implements BusCar{ 95 @Override 96 public void drive() { 97 System.out.println("宝马bus"); 98 } 99 } 100 class BwmSmallCar implements SmallCar{ 101 @Override 102 public void drive() { 103 System.out.println("宝马小车"); 104 } 105 } 106 class AudiBusCar implements BusCar{ 107 @Override 108 public void drive() { 109 System.out.println("奥迪bus"); 110 } 111 } 112 class AudiSmallCar implements SmallCar{ 113 @Override 114 public void drive() { 115 System.out.println("奥迪小车"); 116 } 117 }
四、观察者模式
- 假设现在有A、B、C、D等四个独立的对象,其中B、C、D这三个对象想在A对象发生改变的第一时间知道这种改变,以便做出相应的响应。这就是观察者模式。
- 当然每个被观察者可以有多个观察者,每个观察者也可以有多个被观察者。观察者与被观察者也不是对立的,一个对象可以观察其他对象,也可以被其他对象观察
- Java中通过Observable类和Observer接口实现了观察者模式。Observer对象监视着Observable对象的变化,当Observable对象发生变化时,Observer得到通知,就可以进行相应的工作
- Observable类的两个方法比较重要:
1 package com.chinasofti.Observer; 2 3 import java.util.Observable; 4 import java.util.Observer; 5 6 public class ObserverTest { 7 public static void main(String[] args) { 8 Son son = new Son(); 9 Father father = new Father(son); 10 son.setI(0); 11 son.setI(1); 12 son.setI(1); 13 System.out.println("观察结束"); 14 } 15 16 } 17 // 观察者需要实现Oberser 18 class Father implements Observer { 19 20 public Father(Son son) { 21 son.addObserver(this); 22 } 23 24 @Override 25 public void update(Observable o, Object arg) { 26 System.out.println("值发生了改变:" + ((Son)o).getI()); 27 } 28 } 29 30 // 被观察者需要实现Observable类 类中提供了setChanged方法 用来通知观察者:
被观察者发生改变 notifyObservers方法用来唤醒观察者 31 class Son extends Observable { 32 private int i = 0; 33 34 public int getI() { 35 return i; 36 } 37 38 public void setI(int i) { 39 if (this.i!=i) { 40 this.i = i; 41 setChanged(); 42 notifyObservers(); 43 } 44 } 45 }
五、代理模式
- 代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主体对象与真实主体对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入
- 在上例中,如果孩子买劣质白菜克扣菜钱一直没有被发现,母亲每次都让他去代为买菜,形成了客户端和代理的一一绑定关系,我们称为这种代理为静态代理,这种代理方式实现非常简单
- 如果母亲经常更换代为买菜的目标,如父亲甚至是别人家的孩子用以对比谁更会买菜,那么客户端和代理实例之间会进行动态关联,这种代理我们称为动态代理
- 相比于静态代理,动态代理避免了我们编写各个繁锁的静态代理类,只需简单地指定一组接口及目标类对象就能动态的获得代理对象
- JDK中对动态代理提供了默认支持,使用JDK动态代理的步骤如下:
- 通过实现InvocationHandler接口来自定义自己的InvocationHandler
- 通过 Proxy.newProxyInstance()获得动态代理实体
- 通过代理对象调用目标方法
package com.chinasofti.proxy2; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // son 被代理 father 动态代理 public class Proxy2 { public static void main(String[] args) { Person son = new Son("张三"); Father father = new Father(son); // 第一个参数 类加载器来定义代理类 // 第二个参数 代理类可能实现的接口列表 // 第三个参数 代理者(必须实现InvocationHandler) Person son2 = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, father); son2.mm(); } } // 被代理者的类 interface Person{ String getName(); void setName(String name); void qq(); void mm(); } // 创建被代理者 class Son implements Person{ private String name; @Override public String getName() { return name; } @Override public void setName(String name) { this.name = name; } public Son(String name) { this.name = name; } @Override public void qq() { System.out.println("执行qq方法"); } @Override public void mm() { System.out.println("执行mm方法"); } } // 创建代理者 实现InvocationHandler class Father implements InvocationHandler { // 创建被代理者的对象 private Person son; public Father(Person son) { this.son = son; } // 参数 调用方法的代理实例 方法名 参数 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 创建一个Obj Object obj = null; // if(method.getName().equals("mm")){ String msg = "mm方法已被拦截"; System.out.println(msg); return obj; } // 动态代理的对象执行方法 obj = method.invoke(son,args); // 返回调用方法的代理实例 return obj; } }
- 了解JDK动态代理的实现机理后就会发现,JVM在这个过程中会帮助我们动态构建实际创建对象的代理类,由于有了这个特性,我们可以在很多地方使用动态代理来解决一些看似无法实现的功能,如实现自定义的类似RMI(远程方法调用)的二进制RPC
- 在后续介绍开发框架时,还会发现MyBatis的自动映射机制也离不开JDK动态代理的支持
- CGLIB(Code Generation Library)是一个开源项目,它是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口
- CGLIB是一个强大的高性能的代码生成包。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。最流行的OR Mapping工具hibernate也使用CGLIB来代理单端single-ended(多对一和一对一)关联(对集合的延迟抓取,是采用其他机制实现的)。EasyMock和jMock是通过使用模仿(mock)对象来测试java代码的包。它们都通过使用CGLIB来为那些没有接口的类创建模仿(mock)对象
- CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。除了CGLIB包,脚本语言例如Groovy和BeanShell,也是使用ASM来生成java的字节码。当然不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉
- 工厂模式分为哪几种?
- Java中如何实现观察者模式?
- 单例模式中懒汉和饿汉有什么区别?
- 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的,工厂模式在一般分为三类:简单工厂模式、工厂方法模式、抽象工厂模式,这三种模式从上到下逐步抽象,并且更具一般性
- Java中通过Observable类和Observer接口实现了观察者模式。Observer对象监视着Observable对象的变化,当Observable对象发生变化时,Observer得到通知,就可以进行相应的工作
- Java中实现单例模式可以通过两种形式实现:懒汉模式(类加载时不初始化)、饿汉模式(在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快)