`
kakaluyi
  • 浏览: 438390 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

Design Pattern and FTPC

阅读更多

    声明:是基于rockwell公司的mes产品代码的设计模式分析。

    要谈Design Pattern就得从复用说起。我们每个人不管是使用经验,公式,工具大都从使用别人已经设计,发现了的东西开始的,而这便是复用的在我们生活中的具体表现。在软件开发中Design Pattern是为便于将来复用(直接或稍作改变使用)前人的成功设计而被提炼出的再经验(从经验中发现共有的部分后进行分类定义)。
Design Pattern这个名词最早是从Christopher Alexander的建筑学名著《A Pattern Language》中引入的。正如Christopher Alexander所说:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”。正是基于这样的目的GOF在其书中便是以面向对象设计为背景总结了23个Design Pattern。其各模式组织模板为:模式名和分类,意图,别名,动机,适用性,结构,参与者,协作,效果,实现,代码示例,已知应用,相关模式。
我是从GOF的书开始看的。因为其是以面向对象设计为背景的。故很有必要对面向对象中几个基本概念作一说明。
类:定义了一类活动对象的行为,属性的模板。
对象:封装了状态和行为的静态实体。
接口:仅定义需具体实现的规则集合,以便外部直接使用而屏蔽其具体实现部分从而最终实现了使用与实现的分离。
抽象类:为其子类定义公共接口,而将它的部分或全部的实现延迟到子类。不可实例化。
动态绑定:对象发送的请求所引起的具体操作既与请求本身有关又与接受对象有关,从而支持相同请求的不同对象可能对请求激发的操作有不同的实现。发送给对象的请求和它的相应操作直到运行时才连接起来。
多态:允许在运行时刻彼此替换有相同接口的对象,这种可替换性称为多态性。
继承(范化):类之间为共享部分操作而实现的一种“is a kind of”关系。
组合:类之间为共享部分操作而实现的一种“use a/ has a”关系。(可具体分:关联/聚集“has a”,依赖“use a”)。
     在正式进入主题前,还有必要提几条使用面向对象设计的重要原则:
① 针对接口编程,而不是针对实现编程。(尽量使用接口而非实际对象)
② 优先使用对象组合,而非类继承。(依赖于对象组合的设计有更好的复用性)
③ 接口优先于抽象类。(接口使我们可以构造出非层次结构的类型框架)
④ 尽量做到高内聚,低耦合。
⑤ 设计应支持变化,而我常常会遇到类似如下的问题而不得不重新设计。
1. 通过显式地指定一个类来创建对象。
2. 对特殊操作的依赖。
3. 对硬件和软件平台依赖。
4. 对对象表示或实现依赖。
5. 算法依赖。
6. 紧耦合。
7. 通过生成子类来扩充功能。
8. 不能方便的对类进行修改。
     现在已经出现了许多应用设计模式的工具(Eclipse,等 ),语言(Smalltalk, Java, C++STL, Python, Ruby等),框架(Structs, Spring, MFC等 )。而即使是C这样的结构化语言,其中的函数指针,变参函数,结构体,宏定义等,某种程度上也有设计模式的影子。

   下面我具体针对几个非常常见的设计模式使用实例结合FTPC进行探讨。
模式的基本概念:即增加一个抽象层。无论什么时候,当你想把某些东西抽象出来的时候,实际上你是在分离特定的细节,这么做的一个有说服力的动机就是把变化的东西从那些不变的东西里分离出来。 
    比喻:就是具体事情做得越多,越容易范错误.这每个做过具体工作的人都深有体会,相反,官做得越高,说出的话越抽象越笼统,犯错误可能性就越少。

现在结合我们的FTPC代码中模式的应用,先从开胃菜开始,

先看简单工厂模式

简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。 

 

(com.datasweep.compatibility.manager.ServerImpl):

 

public final ObjectManager getObjectManager(Class type, Keyed definition) { //8.0 Access Control if (type==RTBom.class) return getTBomManager(); if (type == AccessPrivilege.class) return getAccessPrivilegeManager(); else if (type == Account.class) return getAccountManager(); else if (type == ActivitySet.class) return getActivitySetManager(); else if (type == RuntimeActivitySet.class) return getRuntimeActivitySetManager(); else if (type == Application.class) ..... }


 

 

优缺点

 

  优点

  工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。

  缺点

  由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先教考虑到的,如果需要添加新的类,则就需要改变工厂类了。

  当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;

  这些缺点在

 

 

工厂方法模式中得到了一定的克服。

模板模式
1 定义

准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模版方法模式的用意。

模版方法模式需要开发抽象类和具体子类的设计师之间的协作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师则负责给出这个算法的各个逻辑步骤。代表这些具体逻辑步骤的方法称做基本方法(primitive method);而将这些基本法方法总汇起来的方法叫做模版方法(template method),这个设计模式的名字就是从此而来。


二、 模版方法模式的结构
这里涉及到两个角色:

抽象模版(AbstractClass)角色有如下的责任:
定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。

定义并实现了一个模版方法。这个模版方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。

具体模版(ConcreteClass)角色有如下的责任:
实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。

每一个抽象模版角色都可以有任意多个具体模版角色与之对应,而每一个具体模版角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。

可以看看,FTPC的模板模式的实现,具体看com.datasweep.compatibility.client。Categorical。java类

public abstract class Categorical extends Keyed implements IAuditInfo 
{
private void initialize(){ 
// perform any data object related initialization/refreshing here.
}
            。
        。
 protected abstract void refresh_() 

            。
        。
        。
 protected abstract void save_(Time time, String comment, AccessPrivilege accessPrivilege) 
throws DatasweepException; 

            。
        。
        。
}

 

 

 

 

 

 

Categorical类在FTPC是被许多类继承的,比如account,activityset,这些类都是上面提到模板模式中的具体模板,其实这个类是一个很典型的模板模式的应用,可以看到Categorical类的这三个方法一个是空实现,两个都是抽象方法,需要强制子类实现的。
在account,activityset中可以看到空实现的initialize()方法都被子类重写了,但其实我们也可以不实现它们。
我们一般称呼这种模板类空实现的方法叫做钩子,什么是钩子?就是你可以在必要情况下去复写空实现,也可以继续保持空实现,忽略它。这样就可以比较灵活的决定某些方法是否一定要被执行或者实现。
剩下两个方法refresh_(),save_(。。。)是模板方法的抽象方法,推迟到子类实现,对比钩子的不同,是所有模板类Categorical.java的子类都必须实现这两个方法,这两个方法也就是模板方法的骨架。钩子和抽象方法共同实现了模板模式的应用,
大家有兴趣还可以对比一下struts,servelt中init(),destory(),execute()等方法在各自框架中基于模板模式的应用,肯定能够体会模板模式对于规范约定的重要作用。

 

 


 

 

未完待续

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics