设计模式工厂模式

 

1、设计模式之工厂

 

工厂模式是我们最常用的设计模式,学好这个模式当然可以事半功倍,不用关心如何创建,只需要根据相应的需求去获取相应的对象。

假如我们现在需要得到一个Ipod对象和Mac对象,可能在之前,我们的Ipod和Mac都是new出来了,相当于我们的程序依赖了Ipod类和Mac,但是使用了工厂我们就可以部分解耦,将创建和使用分离。

设计模式有一条原则,对象要么构造其他对象,要么使用其他对象,绝对不要两者兼顾。如果遵守这一约束,最终可以降低耦合度。

例如,之前的demo的类图如下:

 

新依赖关系:

 

 

 

对于使用者的角度来说只需要得到这些对象即可,并不需要这些对象是如何创建的。对于创建者AppleFactory来说,只需要创建并且实例化对象即可,并不需要知道如何使用。这种关注点的分离既加强了内聚性,又降低了耦合度。

 

2、基础的简单工厂

 

简单工厂是最基本的工厂模式的应用,其实在很多场合简单工厂就已经很适用了。

大致代码如下:

 

代码
1
2
3  package factory;
4
5
6
7  import java.util.HashMap;
8
9  import java.util.Map;
10
11
12
13  /**
14
15 * User: <a href="mailto:czy88840616@163.com">czy</a>
16
17 * Date: 2010-1-23
18
19 * Time: 20:28:13
20
21 * To change this template use File | Settings | File Templates.
22
23 */
24
25  public class AppleSimpleFactory {
26
27
28
29 private static Map<String, Object> beanMap = new HashMap<String, Object>();
30
31
32
33 /**
34
35 * Method getBean ...
36
37 *
38
39 * @param beanName of type String
40
41 * @return Object
42
43 */
44
45 public Object getBean(String beanName) {
46
47 if(beanMap.containsKey(beanName)) {
48
49 return beanMap.get(beanName);
50
51 }
52
53
54
55 return null;
56
57 }
58
59
60
61 /**
62
63 * Method init ...
64
65 */
66
67
68
69 public void init() {
70
71 beanMap.put("Ipod", new Ipod());
72
73 beanMap.put("Mac", new Mac());
74
75 }
76
77
78
79 }
80
81  

 

 

我们创建了一个简单的apple工厂,里面创建了两个对象ipod和mac,当我们需要ipod对象的时候就可以直接get出来使用,不需要通过new来新建。

 

3、抽象了的工厂—抽象工厂abstract factory

 

 

抽象工厂类似于将工厂再抽象一层,让关注点不在于怎么创建,而在于创建不同的方式。

例如,A工厂生产ipod的时候需要打印A的牌子,而B工厂生产的时候需要打B的牌子,生产的产品都是一样的,都是ipod,但是其中的工序和方式不同。

 

例如:

 

代码
package factory;



import java.util.HashMap;

import java.util.Map;



/**

*
@author <a href="mailto:czy88840616@gmail.com">czy</a>

*
@since 2010-2-28 22:03:50

*/

public abstract class MyAbstractFactory {



protected static Map<String, Object> beanMap = new HashMap<String, Object>();



public abstract void create();



public abstract Product getProduct(String className);



}

 

 

A工厂的方法:

 

 

代码
package factory;



/**

*
@author <a href="mailto:czy88840616@gmail.com">czy</a>

*
@since 2010-2-28 22:16:05

*/

public class MyAbstractFactoryImpl extends MyAbstractFactory {



@Override
public void create() {

Ipod iPod
= new Ipod();

iPod.pasteSign(
"made by A factory");

beanMap.put(
"Ipod", new Ipod());

beanMap.put(
"Mac", new Mac());

}



@Override
public Product getProduct(String className) {

if(beanMap.containsKey(className)) {

return (Product) beanMap.get(className);

}



return null;

}

}



 

B工厂方法类似,其中最主要的就是贴牌的不同。

抽象工厂用于创建相同的产品但是方式不同的地方。

 

4、singleton模式

 

单例模式主要为了控制对象的数目,在使用过程中,只有一个对象存在。

单例模式的工作原理是,用一个特殊的方法来实例化所需的对象:调用这个方法,检查对象是否已经实例化,如果已经实例化,就返回该对象的一个引用,如果尚未实例化,该方法实例化对象并返回新实例的引用。为了确保这是实例化这个对象的唯一方法,需要将这个类的构造函数定义为保护或者私有的。

 

一般Singleton模式通常有几种形式:

 

 

代码
public class Singleton {



private Singleton(){}



  
private static Singleton instance = new Singleton();



  
//这里提供了一个供外部访问本class的静态方法,可以直接访问  

  
public static Singleton getInstance() {

    
return instance;   

   }

}

 

 

 

 

第二种形式:

 

 

代码
public class Singleton {

  
private static Singleton instance = null;



  
public static Singleton getInstance() {



  
if (instance==null)

    instance=
new Singleton();

return instance;   

}

}

 

 

两种的区别是:第二种是lazy加载方式,只有第一次会被初始化,而之后的都可以直接调用。但是第二种会有并发的问题,没有使用synchronized的时候会出现多个实例并存的问题。

 

Singleton是邪恶的

http://www.jdon.com/jivejdon/thread/17578

 

深入singleton可能会演变成double-checked locking (DCL) 模式,比较使用于多线程的情况。

 

5、spring 的beanFactory

 

现在工厂模式基本上都可以被spring的core取代,DI的方式已经大量应用于项目。

Spring创建工厂的接口为beanFactory,默认的像applicationContext都是继承于此接口。

 

 

Spring提供了一些标志接口,用来改变BeanFactory中的bean的行为。它们包括InitializingBean和DisposableBean。实现这些接口将会导致BeanFactory调用前一个接口的afterPropertiesSet()方法,调用后一个接口destroy()方法,从而使得bean可以在初始化和析构后做一些特定的动作。 

Debug了spring的源码后,发现spring在创建bean前进行了许多的操作。

在org.springframework.context.support.AbstractApplicationContext的refresh()方法中。

 

代码
public void refresh() throws BeansException, IllegalStateException {

synchronized (this.startupShutdownMonitor) {

// Prepare this context for refreshing.

prepareRefresh();



// Tell the subclass to refresh the internal bean factory.

ConfigurableListableBeanFactory beanFactory
= obtainFreshBeanFactory();



// Prepare the bean factory for use in this context.

prepareBeanFactory(beanFactory);



try {

// Allows post-processing of the bean factory in context subclasses.

postProcessBeanFactory(beanFactory);



// Invoke factory processors registered as beans in the context.

invokeBeanFactoryPostProcessors(beanFactory);



// Register bean processors that intercept bean creation.

registerBeanPostProcessors(beanFactory);



// Initialize message source for this context.

initMessageSource();



// Initialize event multicaster for this context.

initApplicationEventMulticaster();



// Initialize other special beans in specific context subclasses.

onRefresh();



// Check for listener beans and register them.

registerListeners();



// Instantiate all remaining (non-lazy-init) singletons.

finishBeanFactoryInitialization(beanFactory);



// Last step: publish corresponding event.

finishRefresh();

}



catch (BeansException ex) {

// Destroy already created singletons to avoid dangling resources.

beanFactory.destroySingletons();



// Reset 'active' flag.

cancelRefresh(ex);



// Propagate exception to caller.

throw ex;

}

}

}

 

红色部分代码为spring创建和放入beanfacoty的主要代码。

 

跟踪spring的初始化过程来看,最终进行的初始化类的工作在org.springframework.beans.BeanUtils类的instantiateClass方法中。

 

 

代码
public static Object instantiateClass(Class clazz) throws BeanInstantiationException {

Assert.notNull(clazz,
"Class must not be null");

if (clazz.isInterface()) {

throw new BeanInstantiationException(clazz, "Specified class is an interface");

}

try {

return instantiateClass(clazz.getDeclaredConstructor((Class[]) null), null);

}

catch (NoSuchMethodException ex) {

throw new BeanInstantiationException(clazz, "No default constructor found", ex);

}

}

 

 

最底层的实现一定是为jdk的反射方式。

代码
public static Object instantiateClass(Constructor ctor, Object[] args) throws BeanInstantiationException {

Assert.notNull(ctor,
"Constructor must not be null");

try {

ReflectionUtils.makeAccessible(ctor);

return ctor.newInstance(args);

}

catch (InstantiationException ex) {

throw new BeanInstantiationException(ctor.getDeclaringClass(),

"Is it an abstract class?", ex);

}

catch (IllegalAccessException ex) {

throw new BeanInstantiationException(ctor.getDeclaringClass(),

"Has the class definition changed? Is the constructor accessible?", ex);

}

catch (IllegalArgumentException ex) {

throw new BeanInstantiationException(ctor.getDeclaringClass(),

"Illegal arguments for constructor", ex);

}

catch (InvocationTargetException ex) {

throw new BeanInstantiationException(ctor.getDeclaringClass(),

"Constructor threw exception", ex.getTargetException());

}

}
原文地址:https://www.cnblogs.com/xiziyin/p/1676021.html