设计模式

Head First设计模式学习

策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换。此模式让算法的变化独立于使用算法的客户。(P24,Spring中在实例化对象的时候用到Strategy模式)。

观察者模式:定义了对象间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。(P51,spring中Observer模式常用的地方是listener的实现。如ContextLoaderListener、ApplicationListener)

装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。(P91,100)Spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。基本上都是动态地给一个对象添加一些额外的职责,比如BeanWrapper,它的实现类BeanWrapperImpl的setPropertyValue(PropertyValue pv)方法可以为Bean的属性实现依赖注入。

工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。(P134)Spring中的FactoryBean就是典型的工厂方法模式,由其子类如ProxyFactoryBean、TransactionProxyFactoryBean的getObject()方法返回生成的具体类。

抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。(P156)

单例模式:保证一个类只有一个实例,并提供一个全局访问点。(P177)Spring中的TruePointcut、TrueMethodMatcher类实现了一个单例。

命令模式:将请求封装成对象,这可以让你使用不同的请求、队列,或者日志请求来参数化其他对象。命令模式也可以支持撤销操作。当需要将发出请求的对象和执行请求的对象解耦的时候,使用命令模式。(P206,230)

适配器模式:将一个类的接口,装换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。如Spring中的MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdapter(P243)

外观模式:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。(P264)

模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。如Spring中的AbstractPlatformTransactionManager的事务的生成getTransaction、事务的挂起suspend、事务的提交commit、事务的回滚rollback都是模板方法(P289)

迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。可实现java.util.Iterator接口。(P336)
组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象及对象组合。(P356)

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。(P410)

代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。Spring动态代理类JdkDynamicAopProxy和Cglib2AopProxy(P460)

MVC模式:一个复合模式,把一个应用分成三个截然不同的组件:模型、视图、控制器,实现系统解耦,保持设计干净又有弹性。控制器是视图的策略,视图可以使用不同的控制器实现,得到不同的行为。具体实现如Spring MVC(P532,560)

 

Spring中的设计模式:

 策略模式:Spring中在实例化对象的时候用到Strategy模式,下面是SimpleInstantiationStrategy的instantiate方法,要么使用JDK的反射功能根据构造器生成实例,要么使用Cglib来生成实例,Cglib实例化具体在类CglibSubclassingInstantiationStrategy的instantiate方法里。

public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
			final Constructor<?> ctor, Object[] args) {
                //判断Bean是否有方法被覆盖,如果没有则用JDK的构造器实例化,否则用Cglib来实例化
		if (beanDefinition.getMethodOverrides().isEmpty()) {
			if (System.getSecurityManager() != null) {
				// use own privileged to change accessibility (when security is on)
				AccessController.doPrivileged(new PrivilegedAction<Object>() {
					public Object run() {
						ReflectionUtils.makeAccessible(ctor);
						return null;
					}
				});
			}
			return BeanUtils.instantiateClass(ctor, args); //使用JDK的反射功能根据构造器生成实例:ctor.newInstance(args)
		} else { //使用Cglib来生成实例:enhancer.create()
			return instantiateWithMethodInjection(beanDefinition, beanName, owner, ctor, args);
		}
	}
 

模板方法模式

1.AbstractRefreshableApplicationContext的refreshBeanFactory方法里定义了一些流程,它自己的loadBeanDefinitions是一个protected abstract方法,其子类XmlWebApplicationContext和AnnotationConfigWebApplicationContext分别有自己的实现,这是一个模板方法模式。

@Override
	protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		} catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

 2.DefaultResourceLoader里定义了方法getResourceByPath,是为读取Resource服务的,在getResource(String location)里调用了这个方法,并定义了方法的处理流程:它先会处理带有classpath标识的Resource,再处理URL标识的资源定位,如果既不是classpath,也不是URL标识的资源定位,则把getResource的任务交给getResourceByPath方法,这个一个protected的方法,默认返回一个ClassPathContextResource。

public Resource getResource(String location) {
		Assert.notNull(location, "Location must not be null");
		if (location.startsWith(CLASSPATH_URL_PREFIX)) { //处理带有classpath标识的Resource
			return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
		} else {
			try {
				//再处理URL标识的资源定位
				URL url = new URL(location);
				return new UrlResource(url);
			} catch (MalformedURLException ex) {
				//如果既不是classpath,也不是URL标识的资源定位,则把getResource的任务交给getResourceByPath方法
				return getResourceByPath(location);
			}
		}
	}

protected Resource getResourceByPath(String path) {
	return new ClassPathContextResource(path, getClassLoader());
}

 子类FileSystemXmlApplicationContext覆盖了方法getResourceByPath(String path),返回FileSystemResource。

@Override
protected Resource getResourceByPath(String path) {
		if (path != null && path.startsWith("/")) {
			path = path.substring(1);
		}
		return new FileSystemResource(path);
}

 子类ServletContextResourceLoader覆盖了这个方法,返回ServletContextResource。

@Override
protected Resource getResourceByPath(String path) {
	return new ServletContextResource(this.servletContext, path);
}

子类重新定义了getResourceByPath方法,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

 3.AbstractPlatformTransactionManager的事务的生成方法getTransaction、事务的挂起suspend、事务的提交commit、事务的回滚rollback都是模板方法,由像DataSourceTransactionManager或HibernateTransactionManager这样的具体事务处理器来实现。

 

 单例模式:Spring中的TruePointcut类实现了一个单例,在接口Pointcut中持有这个引用,Pointcut TRUE = TruePointcut.INSTANCE;

类似的单例类还有TrueMethodMatcher.

package org.springframework.aop;

import java.io.Serializable;

class TruePointcut implements Pointcut, Serializable {
	
	public static final TruePointcut INSTANCE = new TruePointcut();
	
	/**
	 * Enforce Singleton pattern.
	 */
	private TruePointcut() {
	}

}

 

 

 

 

 

 

 

你可能感兴趣的:(设计模式)