第三周设计模式总结
简单工厂模式
又叫做静态工厂方法(Static Factory Method)
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
Spring 中的 BeanFactory
就是简单工厂模式的体现,根据传入一个唯一的标识来获得 bean 对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。如下配置,就是在 HelloItxxz
类中创建一个 itxxzBean
。
单例模式
懒汉式
线程不安全实现
双重检查模式实现
饿汉式
枚举实现
策略模式 ( Strategy Pattern )
定义
该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。
优点
使用策略模式可以避免使用多重条件语句
策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码
策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的
策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法
策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离
缺点
客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类
策略模式造成很多的策略类
实现
继承实现
定义一个抽象类,强制子类实现该方法
这种实现,对父类对子类不一定是透明的,如果父类提供了默认的实现,子类需要了解实现的细节,再决定是否重写
组合实现
这种实现是透明的,只需要改变对象的引用就可以改变其行为。
最后通过工厂类,根据运行的参数选择出对应的实现
只有在策略选择里有条件选择语句,其他地方不出现。
如上述的
createAction()
方法
适配器模式 ( Adapter Pattern )
定义
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。分为两种模式:
类适配器模式:适配器与适配者之间是继承(或实现)关系
对象适配器模式:适配器与适配者之间是关联关系
前者的耦合度比后者高,且要求开发了解现有组件库中的相关组件的内部结构,应用相对较少些。
优点
将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
类适配器模式优点:
由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
对象适配器模式优点:
同一个适配器可以把适配者类和它的子类都适配到目标接口。
缺点
类适配器模式缺点:
对于 Java 等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
对象适配器模式缺点:
与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。
实现
角色
Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对 Adaptee 和 Target 进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承 Target 并关联一个 Adaptee 对象使二者产生联系。
Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
类适配器
首先有一个已存在的将被适配的类:
定义一个目标接口:
如果通过一个适配器类,实现 Target
接口,同时继承了 Adaptee
类,然后在实现的 request()
方法中调用父类的 adapteeRequest()
即可实现
对象适配器
对象适配器与类适配器不同之处在于,类适配器通过继承来完成适配,对象适配器则是通过关联来完成,这里稍微修改一下 Adapter
类即可将转变为对象适配器
装饰器模式
在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。我们以往在 spring 和 hibernate 框架中总是配置一个数据源,因而sessionFactory
的dataSource
属性总是指向这个数据源并且恒定不变,所有 DAO 在使用sessionFactory
的时候都是通过这个数据源访问数据库。
但是现在,由于项目的需要,我们的 DAO 在访问sessionFactory
的时候都不得不在多个数据源中不断切换,问题就出现了:如何让sessionFactory
在执行数据持久化的时候,根据客户的需求能够动态切换不同的数据源?我们能不能在 spring 的框架下通过少量修改得到解决?是否有什么设计模式可以利用呢?
首先想到在 spring 的applicationContext
中配置所有的dataSource
。这些dataSource
可能是各种不同类型的,比如不同的数据库:Oracle、SQL Server、MySQL 等,也可能是不同的数据源:比如 apache 提供的org.apache.commons.dbcp.BasicDataSource
、spring 提供的org.springframework.jndi.JndiObjectFactoryBean
等。然后sessionFactory
根据客户的每次请求,将dataSource
属性设置成不同的数据源,以到达切换数据源的目的。
spring 中用到的包装器模式在类名上有两种表现:一种是类名中含有 Wrapper,另一种是类名中含有 Decorator。
基本上都是动态地给一个对象添加一些额外的职责。
模板方法模式
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
Template Method 模式一般是需要继承的。这里想要探讨另一种对 Template Method 的理解。spring 中的JdbcTemplate
,在用这个类时并不想去继承这个类,因为这个类的方法太多,但是我们还是想用到JdbcTemplate
已有的稳定的、公用的数据库连接,那么我们怎么办呢?我们可以把变化的东西抽出来作为一个参数传入JdbcTemplate
的方法中。但是变化的东西是一段代码,而且这段代码会用到JdbcTemplate
中的变量。怎么办?那我们就用回调对象吧。
在这个回调对象中定义一个操纵JdbcTemplate
中变量的方法,我们去实现这个方法,就把变化的东西集中到这里了。然后我们再传入这个回调对象到JdbcTemplate
,从而完成了调用。这可能是 Template Method 不需要继承的另一种实现方式。
以下是一个具体的例子:
JdbcTemplate
中的 execute 方法
版权声明: 本文为 InfoQ 作者【leo】的原创文章。
原文链接:【http://xie.infoq.cn/article/f37a520d922053c935fece883】。
本文遵守【CC BY-ND】协议,转载请保留原文出处及本版权声明。
评论