1.什么是设计模式
(1)设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结.
(2)此术语是在1990年代由Erich Gamma等人从建筑设计领域引入到计算机科学中来的。
(3)使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
2.设计模式的分类
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
其实还有两类:并发型模式和线程池模式.
3.设计模式的六大开闭原则(Open Close Principle)
里氏代换原则(Liskov Substitution Principle)
依赖倒转原则(Dependence Inversion Principle)
接口隔离原则(Interface Segregation Principle)
迪米特法则(最少知道原则)(Demeter Principle)
合成复用原则(Composite Reuse Principle)
4.单例模式
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
Java中单例模式定义:“一个类有且仅有一个实例,并且自行实例化向整个系统提供。”
单例的实现:
提供一个私有构造方法。
提供一个公开的静态的方法返回类的对象
5.单例模式实现一
缺点:线程不安全,多线程不能正常访问
在静态方法中new
举例;
public class Single1 {
private static Single1 single=null;
private Single1(){
}
public static Single1 getSingle1(){
if (single==null) {
single=new Single1();
}
return single;
}
}
public class SingleTest {
/**
* @param args
*/
public static void main(String[] args) {
//Single1 s1=new Single1();不能被实例化
Single1 s1=Single1.getSingle1();
Single1 s2=Single1.getSingle1();
System.out.println(s1==s2);
System.out.println(s1.equals(s2));
}
}
6.单例模式实现二
在一开始就new
举例
public class Single2 {
/***
*
* 单例模式实现方式二 饿汉式
*
* */
private final static Single2 single=new Single2();
private Single2(){
}
public static Single2 getSingle(){
return single;
}
}
7.工厂模式
工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因工厂模式就相当于创建实例对象的new,我们经常要根据Class生成实例对象。
未采用工厂模式的情况
interface Fruit{ // 定义一个水果的接口
public void eat() ; // 吃水果的方法
}
class Apple implements Fruit{ // 定义子类 —— Apple
public void eat(){
System.out.println("** 吃苹果。") ;
}
};
class Orange implements Fruit{ // 定义子类—— Orange
public void eat(){ // 覆写eat()方法
System.out.println("** 吃橘子。") ;
}
};
public class InterfaceCaseDemo03 {
public static void main(String args[]){
Fruit f = new Apple() ; // 实例化接口
f.eat() ; // 调用方法
}
}
第一种方式:直接通过调用方法。采用工厂模式后,相当于在子类与接口之间增加了过渡端,通过过渡端,取得接口,
实例化对象,一般都会称这个过渡端为工程类。如
采用工厂模式
class Factory{ // 定义工厂类
public static Fruit getInstance(String className){
Fruit f = null ; // 定义接口对象
if("apple".equals(className)){ // 判断是那个子类的标记
f = new Apple() ; // 通过Apple类实例化接口
}
if("orange".equals(className)){ // 判断是那个子类的标记
f = new Orange() ; // 通过Orange类实例化接口
}
return f ;
}
}
举例
package day.factory;
public class Apple implements Fruit {
@Override
public void eat() {
System.out.println("apple实现类");
}
}
package day.factory;
public class Orange implements Fruit {
@Override
public void eat() {
System.out.println("orange实现类");
}
}
package day.factory;
public interface Fruit {
void eat();
}
package day.factory;
public class FuritFactory {
public Fruit getFruit(String f){
Fruit fruit=null;
if ("apple".equals(f)) {
fruit=new Apple();
} else if("orange".equals(f)){
fruit=new Orange();
}
return fruit;
}
public static void main(String[] args) {
Fruit f=new FuritFactory().getFruit("orange");
f.eat();
}
}
8.代理模式
代理设计也是在java开发中使用较多的一种设计模式,所谓的代理设计就是指一个代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关业务的处理,就好比在生活中经常使用到的代理上网那样,客户通过网络代理连接网络,由代理服务器完成用户权限,访问限制等与上网操作相关的操作。
举例:
package demo1;
public class NetProxy {
private NetWork netWork;
public NetProxy(NetWork nw){
this.netWork=nw;
}
public void check(){
System.out.println("===检查用户是否合法===");
}
public void browse(){
check();//检查用户是否合法
netWork.browse();
}
}
package demo1;
public interface NetWork {
void browse();
}
package demo1;
public class Client implements NetWork {
@Override
public void browse() {
System.out.println("浏览网络");
}
}
package demo1;
public class Test {
public static void main(String[] args) {
NetProxy np=new NetProxy(new Client());
np.browse();
}
}
9.适配器模式
对于Java程序来说,如果一个类要实现一个接口,则肯定要覆写此接口中的全部抽象方法,那么如果,此时一个接口中定义的抽象方法过多,但是在子类中又用不到这么多抽象方法的话,则肯定很麻烦,所以此时就需要一个中间的过渡,但是此过渡类又不希望被直接使用,所以将此过渡类定义成抽象类最合适,即一个接口首先被一个抽象类(此抽象类通常称为适配器类),并在此抽象类中实现若干方法(方法体为空),则以后的子类直接继承此抽象类,就可以有选择的覆写所需要的方法。
10.内部类主要内容
成员式内部类1
举例:
package day06.inner;
/**
* 成员式内部类
* @author dell
*
*/
public class Outer1 {
public String name;
public void method(){
class Inner0{
int i;
public void speak(){
}
}
}
//成员式内部类
public class Inner{
int num;
public void print(){
System.out.println("内部类的方法"+name);
}
}
}package day06.inner;
public class Test1 {
public static void main(String[] args) {
//创建成员式内部类的对象
Outer1.Inner oi=new Outer1().new Inner();
oi.print();
}
}
成员式内部类(静态)2
举例:
package day06.inner;
/**
* 成员式内部类
* @author dell
*
*/
public class Outer1 {
public String name;
public void method(){
}
//成员式内部类
public static class Inner2{
int n;
public void inner2_method(){
System.out.println("static inner");
}
}
}
package day06.inner;
public class Test1 {
public static void main(String[] args) {
//创建静态的内部类对象
Outer1.Inner2 oi2=new Outer1.Inner2();
}
}
局部内部类
局部内部类对象只能在方法内创建
举例:
package day06.inner;
/**
* 成员式内部类
* @author dell
*
*/
public class Outer1 {
public String name;
public void method(){
class Inner0{
int i;
public void speak(){
}
}
}
//成员式内部类
public static class Inner2{
int n;
public void inner2_method(){
System.out.println("static inner");
}
}
}
11.反射机制
(1)Java反射
在编译时不确定哪个类被加载,而在程序运行时才加载、探知、使用
(2)反射常用的Java 类型
Class类—可获取类和类的成员信息
Field类—可访问类的属性
Method类—可调用类的方法
Constructor类—可调用类的构造方法
12.反射应用步骤
使用反射的基本步骤
导入java.lang.reflect.*
获得需要操作的类的Java.lang.Class对象
调用Class的方法获取Field、Method等对象
使用反射API迚行操作 (设置属性﹑调用方法)
举例:
package demo3;
public class Student {
private String name; //姓名
private int age;//年龄
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return " name is "+name+",age is" + age;
}
}
package demo3;
import java.lang.reflect.Field;
public class Test_Student {
public static void main(String[] args) throws Exception {
//创建一个Student对象
Student p=new Student();
//获取Student对应的Class对象
Class cla=Student.class;
//获取Student类的name属性,使用getDeclaredField()方法可获取各种访问级别的属性
Field nameField =cla.getDeclaredField("name");
//设置通过反射访问Filed时取消权限检查
nameField.setAccessible(true);
//调用set()方法为p对象的指定Filde设置值
nameField.set(p,"jack");
//获取Student类的name属性,使用getDeclaredField()方法可获取各种访问级别的属性
Field ageField =cla.getDeclaredField("age");
//设置通过反射访问Filed时取消权限检查
ageField.setAccessible(true);
//调用setInt()方法为p对象的指定Field设置值
ageField.setInt(p,20);
System.out.println(p);
}
}
package demo3;
import java.lang.reflect.Method;
public class Test_Method {
public static void main(String[] args) throws Exception {
//获取Student对应的Class对象
Class cla=Student.class;
//创建Student对象
Student p=new Student();
//得到setName方法
Method met1=cla.getMethod("setName",String.class);
//调用setName,为name赋值
met1.invoke(p,"jack");
//得到setName方法
Method met=cla.getMethod("getName",null);
//调用setName,为name赋值
Object o=met.invoke(p, null);
System.out.println(o);
}
}
13.反射的应用
获取Class对象
获取对象的结构信息
举例:
package demo3;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
Class c1=Class.forName("java.lang.String");
Method ms[]=c1.getDeclaredMethods();
for (Method m : ms) {
System.out.println(m.getName());
}
}
}
14.面试考点
垃圾回收机制、gc()、finalize()
15.垃圾回收机制意义
垃圾回收能自动释放内存空间,减轻编程的负担
保护程序的完整性
垃圾回收是Java语言安全性策略的一个重要部分
16.垃圾回收算法
Java语言规范没有明确地说明JVM使用哪种垃圾回收算法,但是任何一种垃圾回收算法一般要做2件基本的事情:
(1)发现无用信息对象;
(2)回收被无用对象占用的内存空间,使该空间可被程序再次使用。
17.垃圾回收gc()方法
命令行参数透视垃圾收集器的运行
使用System.gc()可以不管JVM使用的是哪一种垃圾回收的算法,都可以请求Java的垃圾回收。
18.垃圾回收finalize()方法
在JVM垃圾回收器收集一个对象之前,一般要求程序调用适当的方法释放资源,但在没有明确释放资源的情况下,Java提供了缺省机制来终止该对象心释放资源,这个方法就是finalize()。