Spring框架中的设计模式(三)
来源:互联网 发布:打车软件涨价 编辑:程序博客网 时间:2024/05/21 22:26
原型模式
这篇文章的第一个设计模式是原型。可以通过官方文档查找有关Spring作用域中的bean作用域的文章中介绍了类似的概念(prototype)。原型设计模式与有用相同名称的(prototype)作用域有点相似。此设计模式允许通过复制已存在的对象来创建一个对象的实例。副本应该是真正的副本。这意味着新对象的所有属性应与复制对象的属性相同。如果不清楚,比一个简单的JUnit
案例更好的说明:
public class PrototypeTest {public void test() {Robot firstRobot = new Robot("Droid#1");Robot secondRobot = (Robot) firstRobot.clone();assertTrue("Cloned robot's instance can't be the same as the"+" source robot instance",firstRobot != secondRobot);assertTrue("Cloned robot's name should be '"+firstRobot.getName()+"'"+" but was '"+secondRobot.getName()+"'",secondRobot.getName().equals(firstRobot.getName()));}}class Robot implements Cloneable {private String name;public Robot(String name) {this.name = name;}public String getName() {return this.name;}protected Object clone() throws CloneNotSupportedException {return super.clone();}}
在Spring
中,在org.springframework.beans.factory.support.AbstractBeanFactory中使用一种特定的原型设计模式,它将初始化bean原型作用域
。新对象基于配置文件中的bean定义。我们可以看到,在给定的例子中:
<bean id="shoppingCart" class="com.waitingforcode.data.ShoppingCart" scope="prototype"><property name="id" value="9"></property></bean>
(SpringJUnit4ClassRunner.class)"applicationContext-test.xml"})(locations={public class SpringPrototypeTest {private BeanFactory beanFactory;public void test() {ShoppingCart cart1 = (ShoppingCart) beanFactory.getBean("shoppingCart");assertTrue("Id of cart1 should be 9 but was "+cart1.getId(),cart1.getId() == 9);cart1.setId(100);ShoppingCart cart2 = (ShoppingCart) beanFactory.getBean("shoppingCart");assertTrue("Id of cart2 should be 9 but was "+cart2.getId(),cart2.getId() == 9);assertTrue("Id of second cart ("+cart2.getId()+") shouldn't be the same as the first one: "+cart1.getId(),cart1.getId() != cart2.getId());cart2.setId(cart1.getId());assertTrue("Now (after cart2.setId(cart1.getId())), the id of second cart ("+cart2.getId()+") should be the same as the first one: "+cart1.getId(), cart1.getId() == cart2.getId());assertTrue("Both instance shouldn't be the same", cart1 != cart2);}}
从前面的例子可以看出,ShoppingCart
实例是直接从bean定义创建的。最初,cart1
和cart2
对象的id
值为9
.它在测试结束时被修改,以证明两个引用都属于两个不同的对象。
对象池
Spring
中使用的另一个模型是对象池设计模式。其主要目的在于在一个池中保存特定数量的对象,并根据需要重新使用。通过它,我们可以改善我们想要使用巨型对象
的响应时间。巨型
意味着这些对象的构造需要很多时间(例如:持有数据库连接的对象),最好重用已经存在的和未获取的对象,而不是创建新对象。
Spring还使用线程池来管理其调度部分。一些示例位于org.springframework.scheduling.concurrent中。我们检索数据库(Spring JDBC
)项目中的对象池的想法。数据库连接池不是由Spring
直接实现的,而是适用于Spring
工作方式的项目,如C3P0
或Jakarta Commons DBCP
连接池。
观察者
这里呈现的最后一个设计模式是观察者。当一个或几个课程正在等待具体事件时可以使用它。观察者模式由一个科目和观察员名单组成。一个很好的例子就是GUI界面
,其中点击按钮(按钮是主题)会引起听众(观察者)启动的一些操作(再说的直白点就是电影院一场电影这个subject
,需要观众
(也就是观察者咯),电影产生的一些画面产生的事件,比如恐怖 电影给男人女人带来的不同的感官的感受,传播到观察者也就是观众的眼里所带来的不一样的反应,这个中间一般会添加一个事件传播者
,在后面解释Spring
的例子的时候会说到),例如:打开一个新页面这个动作。可以参考下面的例子:
public class ObserverTest {public void test() {Observer pageOpener = new PageOpener();Observer register = new Register();Button btn = new Button();btn.addListener(pageOpener);btn.addListener(register);btn.clickOn();assertTrue("Button should be clicked but it wasn't",btn.wasClicked());assertTrue("Page opener should be informed about click but it wasn't",pageOpener.wasInformed());assertTrue("Register should be informed about click but it wasn't",register.wasInformed());}}class Button {private boolean clicked;private List<observer> listeners;public List<observer> getListeners() {if (this.listeners == null) {this.listeners = new ArrayList<observer>();}return this.listeners;}public void addListener(Observer observer) {getListeners().add(observer);}public boolean wasClicked() {return this.clicked;}public void clickOn() {this.clicked = true;informAll();}private void informAll() {for (Observer observer : getListeners()) {observer.informAboutEvent();}}}abstract class Observer {protected boolean informed;public void informAboutEvent() {this.informed = true;}public boolean wasInformed() {return this.informed;}}class PageOpener extends Observer {public void informAboutEvent() {System.out.println("Preparing download of new page");super.informAboutEvent();}}class Register extends Observer {public void informAboutEvent() {System.out.println("Adding the action to register");super.informAboutEvent();}}
可以看到,关于我们的Button
实例点击的事件被发送到所有的观察者对象。从这些对象开始下载页面内容,第二个将在事件的信息保存在注册表中。在Spring
中,观察者设计模式用于将与应用程序上下文相关的事件传输到org.springframework.context.ApplicationListener的实现。要了解它们的实现方法,我们来看一下AbstractApplicationContext
类(老版本的代码,新版本的请自行对照):
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext, DisposableBean {/** Statically specified listeners */private Set<applicationlistener<?>> applicationListeners = new LinkedHashSet<applicationlistener<?>>();// some other fields and methodspublic void addApplicationListener(ApplicationListener<?> listener) {if (this.applicationEventMulticaster != null) {this.applicationEventMulticaster.addApplicationListener(listener);}else {//新版本这里直接咔嚓掉,上面的applicationEventMulticaster一旦为空,就会报错的this.applicationListeners.add(listener);}}/*** Return the list of statically specified ApplicationListeners.*/public Collection<applicationlistener<?>> getApplicationListeners() {return this.applicationListeners;}/*** Add beans that implement ApplicationListener as listeners.* Doesn't affect other listeners, which can be added without being beans.*/protected void registerListeners() {// Register statically specified listeners first.for (ApplicationListener<?> listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let post-processors apply to them!String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);for (String lisName : listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(lisName);}}}
在提供的代码中,监听器在内部添加到应用程序上下文类中,并且在registerListeners()
方法之后,它们被注册到由接口org.springframework.context.event.ApplicationEventMulticaster表示的适当的事件多路广播器(因为有很多listeners)。EventMulticaster
负责管理不同的listener
和向他们发布事件。
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {private Executor taskExecutor;private ErrorHandler errorHandler;public SimpleApplicationEventMulticaster() {}public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {this.setBeanFactory(beanFactory);}public void setTaskExecutor(Executor taskExecutor) {this.taskExecutor = taskExecutor;}protected Executor getTaskExecutor() {return this.taskExecutor;}public void setErrorHandler(ErrorHandler errorHandler) {this.errorHandler = errorHandler;}protected ErrorHandler getErrorHandler() {return this.errorHandler;}public void multicastEvent(ApplicationEvent event) {this.multicastEvent(event, this.resolveDefaultEventType(event));}//发布事件:通过池执行任务的方式来做并发处理,这样就把之前的对象池模式给利用上了public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {ResolvableType type = eventType != null?eventType:this.resolveDefaultEventType(event);Iterator var4 = this.getApplicationListeners(event, type).iterator();while(var4.hasNext()) {final ApplicationListener<?> listener = (ApplicationListener)var4.next();Executor executor = this.getTaskExecutor();if(executor != null) {executor.execute(new Runnable() {public void run() {SimpleApplicationEventMulticaster.this.invokeListener(listener, event);}});} else {this.invokeListener(listener, event);}}}...}
这次我们讲3种设计模式:用于在同一个调用作用域内创建bean的原型
,避免重新创建巨型对象的对象池,以及将应用程序的上下文事件分派给适当的监听器的观察者。
- Spring框架中的设计模式(三)
- Spring框架中的设计模式(三)
- Spring框架中的设计模式(一)
- Spring框架中的设计模式(一)
- Spring框架中的设计模式(二)
- Spring框架中的设计模式(四)
- Spring框架中的设计模式(五)
- spring中的设计模式(三)
- Spring框架中的设计模式(一)
- Spring框架中的设计模式(二)
- spring中的设计模式
- spring中的设计模式
- spring中的设计模式
- Spring中的设计模式
- Spring中的设计模式
- Spring中的设计模式
- Spring中的设计模式
- Spring中的设计模式
- 通过事件,对选中的的单选框提交,弹窗提示选中的第几个单选框
- Intellij IDEA 断点不可用 No executable code found
- ns2仿真学习(六)-自定义协议
- 国内外无人驾驶技术相关调研
- PostgreSQL 创建数据库 (二)
- Spring框架中的设计模式(三)
- LeetCode——Move Zeroes
- 做网站经常会用到的一些js效果
- OC 中的比较
- 精选机器学习&深度学习视频资源合集 !(附下载链接)
- Ubuntu 14.04下NFS安装配置
- C++矩阵库 Eigen 快速入门
- 五大基础算法
- composer 使用说明笔记