Spring 实现两种设计模式

 在Spring 中大量使用的以下两种设计模式:
.工厂模式
·单态模式
工厂模式可将Java 对象的调用者从被调用者的实现逻辑中分离出来,调用者只需关
心被调用者必须满足的规则(接口) ,而不必关心实例的具体实现过程。这是面向接口编
程的优势,能提高程序的解稿,避免所有的类以硬编码方式糯合在一起。
如果所有的类直接祸合,极易形成"骨牌效应",假如B 类调用了A 类,一旦A 类需要
修改,则B 类也需要修改:假如C 类调用了B 类,则C 类也需要修改......依次类推,从而
导致整个系统都需要改写。造成"牵一发而动全身",而系统重构的代价是相当高的。
Spring 倡导"面向接口编程飞可以避免上述的问题,使设计良好的架构可保证系统
重构的工作被封闭在重构的层内,绝不会影响其他层,这可以在本书后面的示例中看到。
Spring 容器是实例化和管理全部bean 的工厂, Spring 默认将所有的bean 设置成单
态模式,无须自己完成单态模式,即对所有相同id 的bean 请求都将返回同一个共享实
例。因此,单态模式可大大降低Java 对象在创建和销毁时的系统开销。
5.3.1 单态模式的回顾
单态模式限制了类实例的创建,但采用这种模式设计的类,可以保证仅有一个实例,
并可提供访问该实例的全局访问点。J2 EE 应用的大量组件,都需要保证一个类只有一个
266
…E
实例。比如数据库引擎访问点只能有一个。
更多的时候,为了提高性能,程序应尽量减少Java 对象的创建和销毁时的开销。使
用单态模式可避免Java 类被多次实例化,让相同类的全部实例共享同一内存区。
为了防止单态模式的类被多次实例化,应将类的构造器设成私有,这样就保证了只
能通过静态方法获得类实例。而该静态方法则保证每次返回的实例都是同一个,这就需
将该类的实例设置成类属性,由于该属性需要被静态方法访问,因此该属性应设成静态
属性。
下面给出单态模式的示例代码:
II 单态模式测试类
public class SingletonTest
II 该类的一个普通属性。
int value
II使用静态属性类保存该类的一个实例。
private static SingletonTest instance;
II构造器私有化,避免该类被多次实例。
pr 工vate SingletonTest()
System.out.println("正在执行构造器...,,);
II 提供静态方法来返回该类的实例。
public stat 工c SingletonTest getInstance()
II 实例化类实例前,先检查该类的实例是否存在
if (instance -- null)
II如果不存在,则新建一个实例。
instance = new SingletonTest();
II 返回该类的成员变量:该类的实例。
return instance;
II 以下提供对普通属性value 的setter 和getter 方法
publ 工c int getValue ()
return value;
public void setValue(int values)
{
this.value = value;
}
public static void main(String[] args)
{
SingletonTest tl = SingletonTest .getInstance();
SingletonTest t2 = SingletonTest .getInstance();
t2.setValue(9);
System.out.println(tl == t2);
从程序最后的打印结果可以看出,该类的两个实例完全相同。这证明单态模式类的
全部实例是同一共享实例。程序里虽然获得了类的两个实例,但实际上只执行一次构造
267
轻量级J2EE 企业应用实战一-Struts+Spring+Hibernate 整合开发
器,因为对于单态模式的类,无论有多少次的创建实例请求,都只执行一次构造器。
5.3.2 工厂模式的回顾
工厂模式是根据调用数据返回某个类的一个实例,此类可以是多个类的某一个类。
通常,这些类满足共同的规则(接口)或父类。调用者只关心工厂生产的实例是否满足
某种规范,即实现的某个接口是否可供自己正常调用(调用者仅仅使用)。该模式给对象
之间作出了清晰的角色划分,降低程序的棋合。
接口产生的全部实例通常用于实现相同接口,接口里定义了全部实例共同拥有的方
法,这些方法在不同的实现类中实现的方式不同。从而使程序调用者无须关心方法的具
体实现,降低了系统异构的代价。
下面是工厂模式的示例代码:
//Person 接口定义
public interface Person
{
/**
* @param name 对name 打招呼
* @return 打招呼的字符串
*/
public String sayHello(String name);
/**
* @param name 对name 告别
* @return 告别的字符串
*/
public Str工口g sayGoodBye(String name);
该接口定义了Person 的规范,规范要求实现该接口的类必须具有这两个方法:能打
招呼,能告别。
//American 类实现Person 接口
public class American implements Person
{
/**
* @param name 对name 打招呼
* @return 打招呼的字符串
*/
public String sayHello(String name)
return name + ", Hello" ;
/**
* @param name 对name 告别
* @return 告别的字符串
*/
public String sayGoodBye(String name)
return name + ", Good Bye";
268
下面是实现Person 接口的另一个实现类: Chinese
public class Ch 工nese implements Perso口
1**
* @param name 对name 打招呼
* @return 打招呼的字符串
*1
public Str工ng sayHello(Str工ng name)
return name + "您好" ;
1**
* @param name 对name 告别
* @return 告别的字符串
*1
public String sayGoodBye(String name)
return name + II 下次再见n;
然后看Person 工厂的代码:
public class PersonFactory
{
1**
*获得Person 实例的实例工厂方法
* @ param ethnic 调用该实例工厂方法传入的参数
* @ return 返回Person 实例
*1
public Person getPerson(Str工ng ethn工c)
II根据参数返回Person 接口的实例。
if (ethnic.equals工gnoreCase( "chi 口") )
return new Chinese();
else
return new American();
以上是最简单的工厂模式框架,其主程序部分如下:
public class FactroyTest
public static void main(String[] args)
II创建PersonFactory的实例,获得工厂实例
PersonFactory pf = new PersonFactory();
II 定义接口Person 的实例,面向接口编程
Person p = null;
II 使用工厂获得Person 的实例
p = pf.getPerson("chin");
制ng介绍~
269
轻量级J2EE 企业应用实战-一-Struts+Spring+Hibernate 整合开发
II 下面调用Person 接口的方法
System. out. println (p. sayHello ( "wawa") ) ;
System. out. println (p. sayGoodBye ("wawa") ) ;
II 使用工厂获得Person 的另一个实例
p = p f. getPerson("ame");
II 再次调用Person 接口的方法
System .out .println (p. sayHello ("wawa") ) ;
System. out. println (p. sayGoodBye ("wawa" ) ) ;
由此可看出,主程序从Person 接口的具体类中解糯出来,而且程序调用者无须关心
Person 的实例化过程,主程序仅仅与工厂服务定位结合在一起,可获得所有工厂能产生
的实例。具体类的变化,接口无须发生任何改变,调用者程序代码部分也无须发生任何
改动。
下面是Spring 对这两种模式的实现。
5.3.3 Spring 对单态与王厂模式的实现
随着Spring 提供工厂模式的实现,在使用Spring 时,无须自己提供工厂类。因为Spring
容器是最大的工厂,而且是个功能超强的工厂。Spring 使用配置文件管理所有的bean ,其
配置文件中bean 由Spring 工厂负责生成和管理。下面是关于两个实例的配置文件:
<!一下面是xml 文件的文件头>
<?xml version="l.O" encoding="gb2312"?>
<!DOCTYPE beans PUBLIC "-IISPR工NGIIDTD BEANIIEN"
''http://www.springframework.org/dtd/spring-beans.dtd''>
<!一beans 是Spring 配置文件的根元素-->
<beans>
<!-- 定义第一个bea口,该bean 的id 为chinese->
<bean id="chinese" class="lee.Chinese"l>
<!一定义第二个bean ,该bean 的工d 为amerJ. can-->
<bea且id="american" class="lee. American"l>
</beans>
主程序部分如下:
public class SpringTest
{
public static void main(String[] args)
{
II 实例化Spring 容器
ApplicationContext ctx =
new FileSysternXmlAppl工cationContext "bean.xml");
II定义Person 接口的实例
Person p = null;
II通过Spring 上下文获得chinese 实例
p = (Person)ctx.getBean("chinese");
II执行chinese 实例的方法
System.out.println(p.sayHello("wawa"));
System. out .println (p. sayGoodBye ("wawa") ) ;
II通过Spring 上下文获得american 实例
270
…E
p = (Person)ctx.getBean("american");
II 执行american实例的方法
System.out.println(p.sayHello("wawa")) ;
System. out .println (p. sayGoodBye ("wawa") ) ;
使用Spring 时:即使没有工厂类PersonFactory ,程序一样可以使用工厂模式, Spring
完全可以提供所有工厂模式的功能。
下面对主程序部分进行简单的修改:
public class SpringTest
{
public static void main(String[] args)
{
II 实例化Spring 容器
ApplicationContext ctx =
new FileSystemXmlAppl工cationContext("bean.xml");
II 定义Person 接口的实例pl
Person pl = null;
II通过Spring 上下文获得chinese 实例
pl = (Person)ctx.getBean("chinese");
II 定义Person 接口的实例pl
Person p2 = null;
p2 = (Person)ctx.getBean("chinese");
System.out.printl口(pl -- p2);
程序执行的结果是:
true
表明Spring 对接受容器管理的全部bean,默认采用单态模式管理。笔者建议不要随
便更改bean 的行为方式。因为在性能上,单态的bean 比非单态的bean 更优秀。
仔细检查上面的代码,就会发现如下特点:
·除测试用的主程序部分外,代码并未出现Spring 特定的类和接口。
·调用者代码,也就是测试用的主程序部分,仅仅面向Person 接口编程,而无须知
道实现类的具体名称。同时,可以通过修改配置文件来切换底层的具体实现类。
.由于厂无须多个实例,因此工厂应该采用单态模式设计。其中Spring 的上下文,
也就是Spring 工厂,已被设计成单态的。
Spring 工厂模式,不仅提供了创建bean 的功能,还提供对bean 生命周期的管理。
最重要的是还可管理bean 与bean 之间的依赖关系。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值