设计模式

设计模式之单例模式
基本概念
单例模式是一种生产对象型的设计模式。

单例模式指的是某个类的对象在同一时间只允许存在1个实例(对象)。

实现
假设存在类King:

public class King {
}
普通的类可以随意的创建对象:

King k1 = new King();
King k2 = new King();
King k3 = new King();
因为当创建一个类,并且没有显式的指定构造方法时,等效于:

public class King {
public King() {
}
}
要实现单例模式,首先,就必须不允许随意创建对象!则:

public class King {
private King() {
}
}
一旦将构造方法私有化,则在类的外部是不允许调用构造方法的!此时,只有类的内部才可以调用构造方法创建对象:

public class King {
private King king = new King();

private King() {
}

}
在以上代码中,创建的king对象就是唯一被创建出来的对象!那么,当类的外部需要时,提供匹配的get方法即可!

public class King {
private King k = new King();

private King() {
}

public King getInstance() {
    return k;
}

}
虽然以上代码看似可行,但是,实际使用时,getInstance()方法是无法被调用的!为了保证在没有King类的对象之前就可以调用getInstance()方法,必须使用static进行修饰:

public class King {
private King k = new King();

private King() {
}

public static King getInstance() {
    return k;
}

}
由于被static修饰的成员,只能访问其它static成员(不可以访问其它非static成员),因为一旦使用static后,该成员将会最优先加载到内存中!而其它没有被static修饰的数据此时还没有加载到内存中,所以不可以访问!最终,还需要使用static修饰King的对象:

public class King {
private static King k = new King();

private King() {
}

public static King getInstance() {
    return k;
}

}
设计模式之工厂模式
基本概念
工厂模式也是一种生产对象型的设计模式。

有了工厂模式后,当需要某个类的对象时,就不再需要去new指定的类,而是调用工厂中的方法即可。

实现
假设存在某个类Phone:

public class MiPhone {
}
普通的使用:

MiPhone p = new MiPhone();
p.xx = xx;
但是,出于某些原因,也许不希望在使用时调用构造方法来创建对象,则专门创建一个生产对象的工厂类,并且由这个类中的某个方法来创建对象:

public class PhoneFactory {
public static Phone newInstance() {
MiPhone p = new MiPhone();
p.xx = xx;
return p;
}
}
则:

MiPhone phone = PhoneFactory.newInstance();
在以上实现效果中,当需要Phone类的对象时,直接调用工厂中的方法即可,也就不需要关心对象的创建过程!

甚至,有的时候,也许你需要的对象只要是某种大分类的类型的就可以,而不必是某个指定的类型:

public interface Phone {
void dial();
void call();
}

public class MiPhone implements Phone {
}
一旦存在这样的实现关系后,如果需要的对象能做到是接口中已经定义方法,则:

Phone phone = PhoneFactory.newInstance();
phone.dial();
phone.call();
或者,当MiPhone类已经不足以满足你的需求时,还可以:

public class HuaWeiPhone implements Phone {
}
然后:

public class PhoneFactory {
public static Phone newInstance() {
HuaWeiPhone p = new HuaWeiPhone();
return p;
}
}
然而,经过这些调整,原有具体执行的代码却不需要改变!即:

Phone phone = PhoneFactory.newInstance();
phone.dial();
phone.call();
以上代码是不需要调整的!所以,工厂模式还有一个特点就是:你可能不会过度的依赖于某个MiPhone或者HuaWeiPhone这样的类,这些类都是可以易于被替换的!以提高了整个项目的可维护性!

另外提一点,这些类可以放在同一个包中:

cn.tedu.factory_demo.Phone
cn.tedu.factory_demo.MiPhone
cn.tedu.factory_demo.HuaWeiPhone
cn.tedu.factory_demo.PhoneFactory
然后,具体使用的类,例如MiPhone或者HuaWeiPhone的类本身可以使用默认的权限修饰符,例如:

class MiPhone implements Phone {
}
其实,这也是一种封装,是对类的封装!

MVC
什么是MVC
MVC具体指的是Model(模型)、View(视图)、Controller(控制器)。

MVC是一种设计程序的理念,帮助我们为一个项目中的多个类明确它们的分工和任务。

MVC也是OOP思想的具体表现之一!

一个项目中的多个类应该是高内聚、低耦合的!

Spring基础
什么是Spring?解决了什么问题?
再说。

怎么用Spring,有什么效果?
1 从FTP上下载applicationContext.zip并解压,得到applicationContext.xml文件,将该文件放在任何你找得到的位置即可。

2 创建Maven Project,并通过Eclipse自动添加web.xml文件。

3 在Maven的配置文件中添加依赖,操作方式可以是:

3.1 打开pom.xml,选择dependencies选项卡,然后点击add按钮,输入spring-webmvc进行搜索,在搜索结果中,找到Group为org.springframework且Artifact为spring-webmvc的结果(搜索结果中区分大小写),展开,推荐选择3.2.8版,如果没有,则选择任何高于或等于3.2且低于5.0的版本,最终确认保存即可。

3.2 在浏览器中打开maven.tedu.cn如果在家中则打开maven.aliyun.com,注意还需要替换配置文件),搜索spring-webmvc,在搜索结果中,找到Group为org.springframework且Artifact为spring-webmvc的结果(搜索结果中区分大小写),展开,推荐选择3.2.8版,如果没有,则选择任何高于或等于3.2且低于5.0的版本,当选择了版本号,在右下角的XML处会显示配置的源代码,复制这些源代码,回到Eclipse的pom.xml文件中,选择最后一个选项卡,以打开该文件的源代码,在根节点中添加节点,并把刚才从网页中复制的源代码粘贴到该节点之下。

以上无论哪种操作方式,都是为了在pom.xml的源代码的根节点下添加:

org.springframework spring-webmvc 3.2.8.RELEASE 检验以上操作成功的标准就是在Libraries下的Maven Dependencies下会有9个jar包,如果失败,可以对项目点击鼠标右键,在Maven菜单中选择Update选项,以重新更新!

4 将从FTP上下载的applicationContext.xml复制到项目的src\main\resouces下。

如果编辑该文件时,使用alt + /的组合无法提示,可以访问http://schema.tedu.cn/proxy/进行设置(仅限于在公司内部)。

5 假定目前需要Spring帮助我们创建java.util.Date类的对象,则在applicationContext.xml文件的根节点下添加子级节点:

以上代码中,class的值是需要创建对象的类的全名(包括package),而id的值是自由命名,要求唯一。

6 然后,在程序中:

// 1. 确定配置文件:文件名区分大小写
String fileName
= “applicationContext.xml”;
// 2. 加载配置文件,并获取Spring容器
ApplicationContext ac
= new ClassPathXmlApplicationContext(
fileName);
// 3. 根据XML配置中的id名称
// 从Spring容器中获取对象
Date d = (Date) ac.getBean(“date”);
// 4. 测试
System.out.println(
“从Spring容器中获取id=date的对象:”
+ d);
7 通过以上演示,可以发现:Spring就是一个帮助我们创建对象的工具,使得我们在编写程序时,不需要再使用new关键字来创建对象!以实现“解耦”!

为什么叫“Spring容器”
因为Spring会帮助我们创建对象,并且把这些对象管理起来,当我们需要的时候,通过Spring直接获取就可以,所以,Spring就是很多个对象的容器。

使用Spring管理对象
【重点】 情况1
需要创建对象的类存在无参数的构造方法:


【仅了解】 情况2
需要创建对象的类没有无参数的构造方法,但是,在这个类中,有静态的工厂方法:


【仅了解】 情况3
需要创建对象的类没有无参数的构造方法,并且,这个类中也没有静态工厂方法,工厂方法是在另一个类中的,先模拟情景:

public class Phone {
public Phone(String name) {
}
}

public class PhoneFactory {
public Phone newInstance() {
return new Phone(“XiaoMi”);
}
}
如果希望通过工厂生产对象:

// 先创建工厂的对象
PhoneFactory factory = new PhoneFactory();
// 再通过工厂对象的方法创建对象
Phone phone = factory.newInstance();
所以,在配置Spring时,也需要先配置工厂:


然后,再配置所需的类:


使用Spring的细节问题
调用getBean()时的强制转换
在ApplicationContext中,将getBean()重载了几次,其中,有一个getBean(String, Class)方法,可以使得获取对象时不必再强制转换:

Date d = ac.getBean(“date”, Date.class);
关于提示Resource leak: ac is never closed
使用的ApplicationContext对象在使用完毕后,应该调用close()方法以关闭,释放资源。

在ApplicationContext接口中并没有声明close()方法,而AbstractApplicationContext抽象类中是有声明这个方法的,所以,将对象声明为抽象类的类型,即可调用close()方法。

Spring管理的对象的作用域
在默认情况下,Spring管理对象的模式使用的是单例模式,也就是说,通过Spring反复获取同一个id的对象,都会是同一个对象!

在配置Spring时,为节点添加scope属性可以调整作用域,该属性的取值有:singleton(单例的,默认值),prototype(非单例的)。

一般情况下,使用Spring配置的都会是单例的!

关于Spring的单例
关于单例模式,可以区分为“饿汉式”和“懒汉式”,其中,“饿汉式”是:

public class King {
private static King k = new King();

private King() {
}

public static King getInstance() {
    return k;
}

}
而“懒汉式”的是:

public class King {
private static King k;

private King() {
}

public static King getInstance() {
    if (k == null) {
        k = new King();
    }
    return k;
}

}
在Spring中的单例对象,也可以分区为这2种模式,默认情况下是饿汉式,当加载配置文件时就已经创建了对象!

在Spring配置中,为节点添加lazy-init属性的配置,取值为true表示“懒汉式”,取值为false表示“饿汉式”,当然,如果需要是“饿汉式”,根本就不需要配置这个属性!

关于这项配置,仅当这个是单例时才有效!

Spring中的bean的生命周期
由于将类交给Spring管理,由Spring创建对象后,可能不便于确定类在创建时或销毁时应该做什么,可以自行在类中创建相关的方法,用于确定创建时和销毁时需要执行的任何,然后在Spring中将它们配置为初始化方法和销毁方法,例如:

public class Person {
// 初始化方法
public void init() {
}

// 销毁方法
public void destroy() {
}

}
然后,在Spring的配置文件中:


Maven异常错误
Maven的工作机制是从Maven服务器中下载对应的jar包到指定的位置,后续使用时,某项目中如果需要对应的jar包,就会从本机的位置中复制到项目中。

如果出现Maven下载的jar包出错(通常是下载的文件出了错,与服务器的不一致),则删除本地缓存的所有jar包文件,然后关闭eclipse,重新启动,并更新项目。

1 找到缓存文件夹:在eclipse的设置中,找到Maven -> User Settings,找到Local Respository,对应的路径就是缓存文件夹

2 删除缓存文件夹,即删除整个.m2文件夹

3 重启eclipse

4 对项目名称点击右键,选择Maven -> Update Project -> Force …

【复习】 异常
异常的体系结构:

Throwable
– Error
– -- OutOfMemoryError:使用的内存超出了限制
– Exception
– -- RuntimeException
– -- – NullPointerException
– -- – ClassCastException
– -- – ClassNotFoundException
– -- – ArithmeticException
– -- – IndexOutOfBoundsException
– -- – -- ArrayIndexOutOfBoundsException
– -- IOException
– -- – FileNotFoundException
内存溢出与内存泄露(Leak)
内存泄露出现在:当需要释放某个对象占用的内存资源时,它仍处于引用(使用)状态,导致释放失败,但是,由于已经执行了释放代码,例如变量的作用域已经消失,以后也无法再使用这个对象了,这个对象就是垃圾数据,也称之为内存泄露的表现。

其实,少量的内存泄露是没有危害的!如果这样的数据特别多,会导致可用内存空间越来越少,如果到了极端表现,就会出现内存溢出!

如何看待hashCode
hashCode()方法是Object类中已经完成的方法。

hashCode()方法的返回值是int类型,默认情况下,可以理解为是创建出来的对象在内存中的地址。

hashCode()毕竟只是一个很普通的方法,是可以被重写的,如果被重写,则不可以用于判断多个变量指向的是否是同一个对象!事实上,许多常用类都已经重写了hashCode()方法,例如String、包装类、Date等,只要字面值相同,则hashCode()方法的返回值就是相同的!

哪些对象最终需要释放资源
连接型资源需要释放资源!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值