首页 > 代码库 > spring中用到的设计模式
spring中用到的设计模式
http://www.cnblogs.com/pengmengnan/p/6717766.html
一 : 工厂模式
工厂模式主要是为创建对象提供过度接口,以便将创建对象的具体
过程屏蔽隔离起来,达到提高灵活性的目的.
工厂模式可以分为三类 :
(1)简单工厂模式(simple factory)
(2)工厂方法模式 (factory method)
(3)抽象工厂模式(abstract factory)
( 一 ): 简单工厂模式
又称为静态工厂方法模式用来生产统一登记结构中任意产品,通过
建立一个工厂(一个函数或一个类方法)来制造新的对象.
模式组成结构 :
抽象产品:他一般视具体产品继承的父类或实现的接口.在java代
码中由接口或者抽象类来实现.
具体产品: 工厂类所创建的对象就是此角色的实例.在java中有一
个具体类来实现.
工厂类 : 这是本模式的核心,含有一定的商业逻辑和判断逻辑.在
java中它往往由一个具体类实现.
示例代码:
抽象产品:
public interface Car{
void run();
}
具体产品 :
public class Audi implements Car {
public void run(){
System.out.println("奥迪车");
}
}
public class BenChi implements Car{
public void run(){
System.out.println("奔驰");
}
}
工厂类 :
public class SimpleFactory{
public Car createrCar(String type){
if("奥迪".equals(type)){
return new Audi();
}else if("奔驰".equals(type)){
return new BenChi ();
}else {
return null;
}
}
}
客户类(测试类) :
public class Customer {
public static void main(String [] args ) {
SimpleFactory factory = new SimpleFactory ();
Car car1 = factory .createrCar("奥迪");
Ca r car2 = factory .createrCar("奔驰");
}
}
这边是简单的工厂模式,但是工厂部分不太理想,因为每增加一种新
车型,都要在工厂中增加相应的创建业务逻辑,这显然是违背开闭原
则的.可想而知对于新的产品的加入,工厂类很是被动.
于是工厂方法模式出现了,工厂类定义成了接口,而每新增的车型种
类,就增加该车种类对应的工厂类的实现,这样工厂的设计就可以拓
展了,而不必去修改源代码.
(二) : 工厂方法模式
工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模
式里不在只由一个工厂类决定哪一个产品被实例化,这个决定交给
抽象工厂的子类去做.
模式组成结构 :
抽象产品: 他一般视具体产品集成的父类或者实现的接口.在java
中有接口或者抽象类来实现.
具体产品 : 工厂类所创建的对象就是此角色的实例..在java中有
一个具体类实现.
抽象工厂 : 这是工厂方法模式的核心,它与应用程序无关.是具体
工厂角色实现的接口或者必须继承的父类.在java由接口或者抽象
类来实现.
具体工厂 : 它含有和具体业务逻辑有关的代码.有应用程序调用
以创建对应的具体产品的对象.
示例代码 :
抽象产品:
public interface Car{
void run();
}
具体产品 :
public class Audi implements Car {
public void run(){
System.out.println("奥迪车");
}
}
public class BenChi implements Car{
public void run(){
System.out.println("奔驰");
}
}
抽象工厂 :
public interface CarFactory{
Car createCar();
}
具体工厂:
public class AuiFactory implements CarFactory{
publuic Car createCar(){
return new Audi();
}
}
public class BenChiFactory implements CarFactory{
publuic Car createCar(){
return new BenChi();
}
}
客户类:
public class Customer {
public static void main(String [] args ) {
Car car1 = new AuiFactory .createCar();
Car car2 = new .BenChiFactory .createCar();
}
}
简单工厂模式VS工厂方法模式
(1)结构复杂度:简单工厂模式更简单
(2)代码复杂度 : 简单工厂模式更少
(3)管理难度: 工厂方法模式的核心是一个抽象工厂类,而不是简单
工厂模式,把核心放在一个类上拓展性更好,易于管理
根据设计理念建议使用工厂方法模式,但是实际上,我们一般使用简
单工厂模式.
(三)抽象工厂模式:
抽象工厂模式提供一个创建一系列相关或相依赖对象的接口,而无
需指定他们的具体的类.他针对的是有多个产品的等级结构.
反射机制
根据上面的工厂模式可以看出,根据需求要写出不同的对象实例化
的方法,因此,spring引用了反射的思想:
根据类名可以找到其对应的类然后实例化对象,返回一个Object的
类.
示例代码 :
工厂类 :
public static Object getBean(String n){
if(n!=null&&!"".equals(n)){
try {
return
Class.forName(n).newInstance(); // 通过类名 反射 实例化
对象
} catch
(InstantiationException e) {
e.printStackTrace();
} catch
(IllegalAccessException e) {
e.printStackTrace();
} catch
(ClassNotFoundException e) {
e.printStackTrace();
}
}
return null;
}
客户类:
IdCard u = (IdCard)Factory.getBean
("com.jk.pojo.IdCard");
因为返回的是一个Object所以要强转
二 : 单例模式
一 : 饿汉模式
特点:
在类装载的时候就初始化Singleton,有时候不是调用getInstance
方法,调用别的静态方法,也会让类进行静态加载,但是,此时并不一
定想实例化Singleton,造成资源的浪费.
这种方式基于classloder机制避免了多线程的同步问题,不过,
instance在类装载时就实例化,虽然导致类装载的原因有很多种,
在单例模式中大多数都是调用getInstance方法, 但是也不能确
定有其他的方式(或者其他的静态方法)导致类装载,这时候初始
化instance显然没有达到lazy loading的效果。
代码示例:
1. public class Singleton {
2. private static Singleton instance = new
Singleton();
3. private Singleton (){} //私有化有参构造
4. public static Singleton getInstance() {
5. return instance;
6. }
7. }
二:饿汉模式变种
表面上看起来差别挺大,其实更第三种方式差不多,都是在类初始
化即实例化instance。只是将实例化的对象放到了静态代码块中
示例代码:
1. public class Singleton {
2. private Singleto+n instance = null;
3. static {
4. instance = new Singleton();
5. }
6. private Singleton (){}
7. public static Singleton getInstance() {
8. return this.instance;
9. }
10. }
三 : 懒汉模式(线程安全的)
(1)
特点 : 没有加ysnchronized的懒汉模式,是线程不安全的,比如说
一个线程来了判断instance是null,就去实例化Singleton了,在实
例化之前,这是另一个线程来判断这个instance,发现也是null所
以又去实例化一次,所以严格上来说不加synchronized懒汉模式,
不是单例模式.synchronized 是让访问的客户自动去排队因此即
使前面已经判断过不为空了,但后面的访问还是要一个一个的去排
队访问,所以效率低
示例代码:
1. public class Singleton {
2. private static Singleton instance;
3. private Singleton (){}
4. public static synchronized Singleton
getInstance() {
5. if (instance == null) {
6. instance = new Singleton();
7. }
8. return instance;
9. }
10. }
(2)双重校验锁(重点)
加了双重校验锁的懒汉模式既可以使线程安全又不会影响效率,因
为,第一次排队实例化第一个对象之后,下面在有访问的就直接被第
一个if拦截住了,所以不需要去排队访问
示例代码
public class Singleton {
private Singleton(){};//私有化构造器
private static volatile Singleton instance = null;
// volatile 不稳定
public static Singleton getInstance(){ //
synchronized 同步锁 线程锁
if(instance==null){ // 双重判定锁
synchronized (Singleton.class){
if(instance ==null){
instance = new Singleton ();
}
}
}
return instance ;
}
}
四 : 懒汉式(线程不安全)
这种写法lazy loading很明显,但是致命的是在多线程不能正常
工作。比如说一个线程来了判断instance是null,就去实例化
Singleton了,在实例化之前,这是另一个线程来判断这个
instance,发现也是null所以又去实例化一次,所以严格上来说不
加synchronized懒汉模式,不是单例模式.
1. public class Singleton {
2. private static Singleton instance;
3. private Singleton (){}
4.
5. public static Singleton getInstance() {
6. if (instance == null) {
7. instance = new Singleton();
8. }
9. return instance;
10. }
11. }
五 : (静态内部类)
1. public class Singleton {
2. private static class SingletonHolder {
3. private static final Singleton INSTANCE = new
Singleton();
4. }
5. private Singleton (){}
6. public static final Singleton getInstance() {
7. return SingletonHolder.INSTANCE;
8. }
9. }
这种方式同样利用了classloder的机制来保证初始化
instance时只有一个线程,它跟第三种和第四种方式不同的是(很
细微的差别):第三种和第四种方式是只要Singleton类被装载了
,那么instance就会被实例化(没有达到lazy loading效果),
而这种方式是Singleton类被装载了,instance不一定被初始化。
因为SingletonHolder类没有被主动使用,只有显示通过调用
getInstance方法时,才会显示装载SingletonHolder类,从而实
例化instance。想象一下,如果实例化instance很消耗资源,我
想让他延迟加载,另外一方面,我不希望在Singleton类加载时就
实例化,因为我不能确保Singleton类还可能在其他的地方被主动
使用从而被加载,那么这个时候实例化instance显然是不合适的。
这个时候,这种方式相比第三和第四种方式就显得很合理
六 : 枚举
1. public enum Singleton {
2. INSTANCE;
3. public void whateverMethod() {
4. }
5. }
这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅
能避免多线程同步问题,而且还能防止反序列化重新创建新的对象
,可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum
特性,用这种方式写不免让人感觉生疏,在实际工作中,我也很少
看见有人这么写过
spring中用到的设计模式