1.模板模式
参考:https://www.cnblogs.com/betterboyz/p/9377881.html
(1).概念:父类定义骨架,即需要的方法和方法调用的顺序,由子类去实现,除了子类必须实现的方法外,其他方法以及方法调用的顺序在父类中得写好
(2)父类中有两种方法:模板方法和基本方法:
1)模板方法是把基本操作方法组合在一起形成一个总算法或一个总行为的方法,主要是定义调用的方法已经调用顺序
2)基本方法:包括钩子方法,具体方法和抽象方法
3)基本示例:
//父类定义模板方法
abstract class CalculateTemplate{
//模板方法中定调用
protected void calculate(double rate,String mode){
beforeCalculate();//钩子
getMode();//抽象
getRate();//抽象
doCalculate(rate, mode);//公用方法一般在父类中实现
}
//钩子方法
protected void beforeCalculate(){}
protected abstract String getMode();
protected abstract double getRate();
private double doCalculate(double rate,String mode){
System.out.println("模板:"+mode+"的比率为:"+rate);
return rate*10;
}
//钩子
void afterCalculate(){};
}
//实现A
class calculateA extends CalculateTemplate {
@Override
protected String getMode() {
return "A";
}
@Override
protected double getRate() {
return 0.23;
}
}
//实现B
class calculateB extends CalculateTemplate {
@Override
protected String getMode() {
return "B";
}
@Override
protected double getRate() {
return 0.45;
}
}
public static void main(String[] args) {
//具体使用时确定使用哪个模板实现类
CalculateTemplate calculateTemplate = new TemplateTest().new calculateA();
//调用模板方法 calculateTemplate.calculate(calculateTemplate.getRate(),calculateTemplate.getMode());
}
4)spring中具体应用: defaultbeandefinitionDocumentReader类中
doRegisterBeanDefinitions方法将xml的Root元素转化为BeanDefinitions的过程是典型的模板方法
/**
* Register each bean definition within the given root {@code <beans/>} element.
*/
//注册beandefinition的真正方法,模板方法
protected void doRegisterBeanDefinitions(Element root) {
//以下定义了执行顺序
preProcessXml(root); //钩子方法,留给子类重写
parseBeanDefinitions(root, this.delegate); //具体方法进行转换
postProcessXml(root);
this.delegate = parent;
}
protected void preProcessXml(Element root) { //钩子方法
}
protected void postProcessXml(Element root) { //钩子方法
}
如果子类继承以上方法,在注册beanDefinition之前和之后如果想做些什么,可以重写父类的两个钩子方法
2.https://blog.csdn.net/caoxiaohong1005/article/details/80039656
2 单例模式
(1)定义:保证一个类只有一个实例,并提供一个访问的全局访问点
注册表单例,提供一个getSingleton()的全局访问点,但是没有从构造器级别去控制单例,因为spring管理的是任意对象,不可能做到构造器级别的控制
(2)源码解析
defaultSingletonBeanRegistry类中
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//检查缓存中是否存在实例,一级缓存,保存的是已经初始化完全的bean和beanName的映射
Object singletonObject = this.singletonObjects.get(beanName); //Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { //如果还在创建中,只要没有完全初始化的都属于创建中
//如果为空,则锁定全局变量并进行处理。
synchronized (this.singletonObjects) {
//二级缓存,保存的是正在初始化的bean和beanName映射,从二级缓存中拿
singletonObject = this.earlySingletonObjects.get(beanName); //private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
if (singletonObject == null && allowEarlyReference) {
//当某些方法需要提前初始化的时候则会调用addSingleFactory 方法将对应的ObjectFactory初始化策略存储在singletonFactories,三级缓存缓存的是beanName和beanFactoy的映射,
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); //private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
if (singletonFactory != null) {
//调用预先设定的getObject方法
singletonObject = singletonFactory.getObject(); //前两级缓存没拿到对象后,三级缓存中的beanFactory开始创建bean
//记录在缓存中,earlysingletonObjects和singletonFactories互斥
this.earlySingletonObjects.put(beanName, singletonObject); //记录在缓存中
this.singletonFactories.remove(beanName); //去掉对应的beanFactory
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
(3)构造器级别的单例
i.线程安全单例1饿汉模式
//线程安全,一开始就初始化,所以性能稍微差
//私有属性
private static Singleton instance =new Singleton();
//私有构造器
private Singleton(){
}
//公有静态方法
public static Singleton getInstance(){
return instance;
}
}
ii 构造器单例2 双重判空锁模式
//线程安全,高效
//私有属性。volatile禁止指令重排序,原因见下
private static volatile Singleton instance ;
//私有构造器
private Singleton(){
}
//公有静态方法
public static Singleton getInstance(){
if (instance==null){ //第一次判空是检查是否为空
synchronized (Singleton.class){
if (instance==null){//第二次如果这里不判断的话,第二个线程结束阻塞后,会直接new一个实例,判断的话则能使得后面用到的都是第一个线程new的实例,
instance = new Singleton();
}
}
}
return instance;
}
ps:使用volatile的原因:new一个对象分三步:
分配对象内存 1
调用构造器方法,执行初始化 2
将对象引用赋值给变量。 3
2和3可能重排序,如果线程A发生了重排序,执行了132,而线程B恰好第一次判空,此时判断并不为空,则直接returninstance,则会发生错误
3.简单工厂模式(静态工厂)
(1)简单案例
通过所有的实例都继承同一个父类,传入相应的唯一标示来获得实例
/**
* 简单工厂
*/
public class SimpleFactory {
public Object getObject(String name){
Object object;
switch (name.toLowerCase()){
case "book":
object = new Book();
break;
case "todo":
object = new ToDo();
break;
case "testuser":
object = new TestUser();
break;
default:
object= new Object();
}
return object;
}
//使用
SimpleFactory simpleFactory = new SimpleFactory();
Object book =simpleFactory.getObject("book");
System.out.println(book.toString());
(2)spring中简单工厂的使用
BeanFactory的getBean方法就是一个,使用getBean(“beanName”),通过传入一个唯一的beanName来获得一个唯一的实例,
提前会将所有实例存储在容器中,思想与上面的简单demo是一样的,只是spring在工厂内部的实现比较复杂
(3)通过工厂获取bean的优势是能够控制对象是否单例,是否被代理等等
4.工厂模式
(1)实现方式
参考:https://www.cnblogs.com/wujc/p/10585387.html
i.定义顶级Factory;ii.各种产品类型的Factory实现顶级factory中的公共方法;iii.不同产品的factory去生产实例
举例:
public interface Factory{ //顶级工厂
void Object prduce();
}
public bicycleFactory implements Factory{ //各自工厂
Object prduce(){
return new Bicycle(); //生产不同对象
}
}
public carFactory implements Factory{
Object prduce(){
return new Car();
}
}
(2)spring中工厂模式的体现在FactoryBean这个接口上
源码:
public interface FactoryBean<T> {
T getObject() throws Exception; //获得该方法返回的实例
Class<?> getObjectType(); //实例class
boolean isSingleton(); //是否单例
}
应用:
public class BookFactory implements FactoryBean { //顶级工厂类被具体工厂所实现
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test.xml");
Book book = (Book) applicationContext.getBean("bookFactory"); //这里获得的是getObject中返回的类型,而不是BookFactory这个bean本身
System.out.println(book.toString());
}
@Override
public Object getObject() throws Exception {
System.out.println("获取单例的book");
return Book.getInstance();//这里嵌套了一个单例的bean
}
@Override
public Class<?> getObjectType() {
return Book.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
设计模式中的开闭原则 – 对扩展开放,对修改关闭
5.适配器模式
(1)原理
i.分类为:类适配器和对象适配器
ii.适配器模式角色有:目标类,即想要调用适配者方法的类;适配器类,对目标类和适配者类进行适配的类;适配者类,即被适配被调用的老的角色,一般是包含想被使用,但没有合适的调用方法的类
iii.适用场景:
系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。
想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作
(2)类适配器举例
//目标接口
interface target{
void request();
}
//实现类
class targetImple implements target{
@Override
public void request() {
}
}
//适配者即已经存在的老的类
static class handle{
void dispach(){
System.out.println("开始转发=====");
}
}
//如何在targetImpi中调用dispach是个问题,targetImple可以直接继承handle,但没必要,
// 适配器就是适用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作
static class HandleAdapter extends handle implements target {
@Override
public void request() {
System.out.println("开始请求=====");
this.dispach();
}
}
(3)对象适配器,将被适配的类作为适配器的一个属性或者方法参数传入
//其他都不变,改下适配器,将原本对于被适配类的继承改为属性
static class HandleAdapter implements target {
handle handle = new handle();
@Override
public void request() {
System.out.println("开始请求=====");
handle.dispach();
}
}
(4)spring中AOP中适配器模式的使用,此处是对象适配器
spring AOP中的适配器模式
在Spring的Aop中,使用的 Advice(通知) 来增强被代理类的功能。
Advice的类型有:MethodBeforeAdvice、AfterReturningAdvice、ThrowsAdvice
在每个类型 Advice 都有对应的拦截器,MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor
Spring需要将每个 Advice 都封装成对应的拦截器类型,返回给容器,所以需要使用适配器模式对 Advice 进行转换
这里只举例BeforeAdvice
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method var1, Object[] var2, @Nullable Object var3) throws Throwable;
}
目标接口 Target,有两个方法,一个判断 Advice 类型是否匹配,一个是工厂方法,创建对应类型的 Advice 对应的拦截器
public interface AdvisorAdapter {
boolean supportsAdvice(Advice var1);
MethodInterceptor getInterceptor(Advisor var1);
}
//适配器实现类中
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {//这里将需要适配的适配类接口MethodBeforeAdvice作为参数传入,用的也是对象适配器
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice); //将需要适配的类封装成一个适配器类
}
}
6.装饰器模式
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活,避免子类太多
(1)例子
//装饰类与目标类要有同一个接口
class WrapperLogger implements Logger {
Logger logger ; //目标类是包装类的一个属性
public WrapperLogger(Logger logger){
this.logger = logger;
}//构造器实例时设置值
@Override //进行装饰
public void info(String s) {
s = new StringBuffer().append(new Date().toString()).append("=====").append(s).toString();
logger.info(s); //装饰完调用目标类的方法
}
}
class WrapperLoggerFactory {
public Logger getLogger(Class clz){
return new WrapperLogger(LoggerFactory.getLogger(clz));
}
}
//使用
public static void main(String[] args) {
Logger logger =new WrapperTest().new WrapperLoggerFactory().getLogger(WrapperTest.class);
logger.info("开始打印");
}
(2)spring中装饰者模式是的类都是以wrapper或者Decorator命名
BeanWrapperImpl中
public void setWrappedInstance(Object object, String nestedPath, Object rootObject) {
super.setWrappedInstance(object, nestedPath, rootObject);
setIntrospectionClass(getWrappedClass());
}
在AbstractAutoWireCpableBeanFactory中的doCreateBean方法中调用了createBeanInstance其中调用instantiateBean
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
final BeanFactory parent = this;
.......
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
BeanWrapper bw = new BeanWrapperImpl(beanInstance);//这里是一个对bean进行包装
initBeanWrapper(bw);
return bw;//返回
}
}
(3)装饰器模式类图
6、观察者模式(发布订阅模式)
(1)主题中通维护所有的观察者的对象持有,当主题中信息发生变化时 及时给每个观察者通知到
(2)主题中有注册和删除观察者的方法
(3)简单示例
abstract class Subject{
//维护所有观察者即订阅者
Map<Class,Observer> observerMap = new HashMap<>();
void registryObserver(Class clz,Observer observer){// 注册观察者
observerMap.put(clz,observer);
}
void deleteObserver(Class clz){ //删除注册者
observerMap.remove(clz);
}
abstract void notify(String msg); //通知
}
class ConcreteSubject extends Subject{ //实现类
String msg ;
//改变并通知
public void setMsg(String msg) {
this.msg = msg;
notify(this.msg);
}
@Override
void notify(String msg) {
//通知所有的观察者,循环通知
for (Observer observer:observerMap.values()){
observer.change(msg);
}
}
}
interface Observer{// 观察者接口
void change(String msg);
}
class ObserverImplA implements Observer{//观察者实现A
@Override
public void change(String msg) {
System.out.println(this.getClass().getName()+msg);
}
}
class ObserverImplB implements Observer{// 观察者实现B
@Override
public void change(String msg) {
System.out.println(this.getClass().getName()+msg);
}
}
public static void main(String[] args) {
Observer observerA = new ObserverTest().new ObserverImplA();
Observer observerB = new ObserverTest().new ObserverImplB();
//注册观察者
ConcreteSubject subject = new ObserverTest().new ConcreteSubject();
subject.registryObserver(ObserverImplA.class,observerA);
subject.registryObserver(ObserverImplB.class,observerB);
//改变值
subject.setMsg("msg已经发生变化了,特此通知====");
}
(4)spring中观察者模式
1)spring事件:ApplicationEvent,该抽象类继承了EventObject类,
2)spring监听器:ApplicationListener ,继承EventListener
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { //继承了jdk事件监听器
void onApplicationEvent(E event);
}
以下步骤总结:监听器注册到事件中,当事件有改变,通过调用 ApplicationEventPublisher.publishEvent(实现类是AbstractapplicationContext,但是由子类ApplicationContext进行调用)进行发布;委托给ApplicationEventMulticater,调用multicastEvent方法for循环所有的监听者进行广播;调用所有监听器实现类的onApplicationEvent
3)spring事件发布
public interface ApplicationEventPublisher {
/**
* Notify all <strong>matching</strong> listeners registered with this
* application of an application event.
void publishEvent(ApplicationEvent event);
void publishEvent(Object event);
}
AbstractApplicationContext实现了该接口
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, ResolvableType eventType) {
......
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {//这里将事件的发布委托给了ApplicationEventMulticaster类,是abstractApplicationContext的一个属性
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}.....
}
ApplicationEventMulticater 中进行事件广播,即观察者中事件改变后的通知操作,通知给每个监听者
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
doInvokeListener(listener, event);
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event); //调用实现了ApplicationListener接口的方法
}
}
4)spring如何找到事件监听器?
refresh()方法中提前注册进去
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test.xml");
初始化方法中调用了refresh
public void refresh() throws BeansException, IllegalStateException {
.....//这里初始化一个ApplicationEventMulticater,查找xml文件中是否配置,如果没有配置,则new一个默认的实例,并注册到工厂 this.initApplicationEventMulticaster();
this.registerListeners(); //通过反射获得ApplicationListener所有的
}
initApplicationEventMulticaster(){
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster)
};
protected void registerListeners() {//注册监听器
Iterator var1 = this.getApplicationListeners().iterator(); //获得所有监听器
while(var1.hasNext()) {
ApplicationListener<?> listener = (ApplicationListener)var1.next();
this.getApplicationEventMulticaster().addApplicationListener(listener); //注册到广播器
}//getBeansOfType和下面的方法都是通过反射获得ApplicationListener所有的的实现类
String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
String[] var7 = listenerBeanNames;
int var3 = listenerBeanNames.length;
for(int var4 = 0; var4 < var3; ++var4) {
String listenerBeanName = var7[var4]; this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
}
5)spring监听器的使用:
public class springListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
this.print();
Object o= applicationEvent.getSource();
}
//自定义监听器
class myEvent extends ApplicationEvent{
public myEvent(Object source) {
super(source);
}
}
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test.xml");
applicationContext.publishEvent(new springListener().new myEvent(new Book()));
}
}