??xml version="1.0" encoding="utf-8" standalone="yes"?>
SRP(Single Responsible Principle), 单一职责原则Q这是面对的最基本原则Q也是实现弹性设计的最基本原则?/font>
每个cL接口定义应该只包含一U明的职责Q同时仅有一U原因会Dq种定义的修攏V一个复杂的cL接口的定义包含多个责任,很容易你的设计失去Ҏ,很多因素都会Dq个cL接口的变_׃它含有多U职责,q就意味着它是多种服务的提供者,会有多种依赖于它的客LQ他的变更可能会D大范围的变更?/span>
在作者看来,优先U最高的是你首先要保证接口的单一职责及方法的单一职责Q接口通常意味可以更换不同的实玎ͼZ个接口定义过多的职责意味着每个实现都会涉及多个职责Q这导致无法实现更粒度的实现的复用?/span>
2 面向抽象~成
如果你已l读q?font face="Times New Roman">GOF的《设计模式》,你便知道其中每一个模式都是基于此原则的,抽象Q或接口Q有效的解除了服务调用者和服务提供者间的耦合?/font>
3 使用配置
通过修改配置文g便可以改变系l的某些Ҏ,q种修改的区别于修改代码Q对?font face="Times New Roman">Java,C++而言q种修改是不需要编译,有的修改甚至可以在运行时生效?/font>DSL地运用可以配置更加h可读性及更强的描q能力。在设计时将实现分ؓ配置及框枉分是非常灉|的结构?/font>
蔡超
HP 软g架构?br />
软g架构N
SCEA
IBM Certified Solution Designer for OOA&D vUML2
Chaocai2001@yahoo.com.cn
?/span>OO中可以用抽象方法及接口来完成文中通过函数指针和结构体来实现的间接层?br />
Client.java
AppInterface app=new AppImpl();
AppInterface app1=new AppProxy(app);
AppProxy.java
public class AppProxy implements AppInterface{
private AppInterface appRef;
public AppProxy(AppInterface appRef){
this.appRef=appRef
}
public void doSomething(){
/*some codes*/
}
}
通过Proxy来实现间接层Q相互嵌套可以实现多个间接层Qƈ且可以通过一?/span>AppBuilder来创个对象,l合多个间接层。间接层中可以实现文中提及的对参数的预处理?/span>
同时Q我也认为文中提及的间接层也可以?/span>Adapter?/span>
1 Ҏ对象来选择行ؓ问题
public interface Event {
}
public class BlueEvent implements Event {
}
public class RedEvent implements Event {
}
public class Handler {
public void handle(Event event){
System.out.println("It is event");
}
public void handle(RedEvent event){
System.out.println("It is RedEvent");
}
public void handle(BlueEvent event){
System.out.println("It is BlueEvent");
}
}
public class Main {
public static void main(String[] args) {
Event evt=new BlueEvent();
new Handler().handle(evt);
}
}
你认行结果是什么呢Q?/font>
l果Q?/font>It is event
是不是有点出乎意料,不是It is BlueEventQ这是应为Overloadq不支持在运行时Ҏ参数的运行时cd来帮定方法,所以要执行哪个Ҏ是在~译时就选定了的?/font>
2 Double Dispatch Pattern
׃Java,C++及C#都具有上q局限,通常我们只能通过Switch或ifl构来实玎ͼ当然q种实现方式既不优雅而且影响代码的可l护性?/font>
通过以下的Double Dispatch Pattern便可以优雅的实现?/font>
public interface Event {
public void injectHandler(EventHandler v);
}
public class BlueEvent implements Event {
public void injectHandler(EventHandler v) {
v.handle(this);
}
}
public class RedEvent implements Event {
public void injectHandler(EventHandler v) {
v.handle(this);
}
}
public class EventHandler {
public void handle(BlueEvent e){
System.out.println("It is BlueEvent");
}
public void handle(RedEvent e){
System.out.println("It is RedEvent");
}
}
public class Main {
public static void main(String[] args) {
Event evt=new BlueEvent();
evt.injectHandler(new EventHandler());
}
}
其实设计模式QGoF)中的Visitor模式是Double Dispatch的一U应用?br />
蔡超
HP
软g架构?br />
软g架构N
SCEA,SCBCD,MCSD
IBM Certified Solution Designer for
OOA&D vUML2
Chaocai2001@yahoo.com.cn,chao.cai@hp.com
首先我们分析OSGi的特点及可以l我们应用带来的好处
1 良好的动态特?/span>
2 更细_度的类装蝲控制Q多个版本组件在同一q行环境中共同运?/span>
3 ?/span>JVM内部实现SOAQ我个h倒是认ؓOSGi所涉及的仅仅是SOA思想的一部分)
4 DS提供?/span>IoC支持
h考你的应用程序真的需要这些吗Q?/span>
很多设计和开发h员都会在设计和实现时忽略应用的真正需要和OSGi的复杂性,应用的所有内部细划分都采用Bundle实现?/span>
而我们除了应该注意采?/span>OSGi开发和调试带来的复杂性;同时也要明白动态特性的支持q不是仅仅采?/span>OSGiq_可以搞定的Q要真正实现动态特性必L意模块的启动序无关性及对其所依赖服务的监听等Q这些都会大大增加系l实现和调试的复杂性?/span>
其实我们应该认真分析应用是否需要这?/span>OSGi的特性及q些Ҏ应该在应用的那些部分体玎ͼ例如我们可以在扩展方面采?/span>Bundle实现扩展插gQ至于其它部分则不必采用q多?/span>BundlesQ甚臛_以采用一个大?/span>BundleQ而其内部则可以采用如Spring来帮助我们实现模块化Q?/span>
同时Q不要忘记其他的framework同样提供了很好的lg化的基础架构?/span>SpringQ?/span>Pico-ContainerQ在OSGi与其它技术合时SCA同样是很好的选择?/span>
保持应用的简单性,不要针对特定技术进行设计,而要计选择适合的技术?/span>
蔡超
Chaocai2001@yahoo.com.cn
因此大家在设计过E中不要仅仅分层结构留于Ş式,而要时刻注意设计是否W合q种架构模式Q这h能真正发挥这U架构模式的优势?/span>
北京天融信,软g架构?/span>
SUN certified Enterprise Architect
Microsoft certified Solution Developer
IBM certified RUP Specialist
联系方式
:cai_chao@topsec.com.cn,chaocai2001@yahoo.com.cn
010-82776427
在基于异步通信方式的系l中Q实现模块的同步调用?/span>
消息队列已经成ؓ目前很多软g选用的通讯方式Q消息模式得不同分布式lg间的耦合性较为松散,提高了系l的可维护性和可扩充性。但是有时我们希望在q种情况下能够模拟同步的调用方式Q希望能够通过一个组仉明的帮我们实现q种异步和同步调用的转换?/span>
图表
1
Z消息的分布式pȝ
上图是一U常见的Z消息的分布系l结构,pȝ中包含两条队列。命令队列用于传送模块间怺调用的命令对象,响应队列用于传送命令处理后的响应结果对象?/span>
在通常情况下消息队列上的模块会以异步的方式工作Q这U情况下模块通常不关心命令执行后的状况,常常是不返回值的?/span>
Z模拟同步调用我们通过一?/span> SynProxy lg来帮助我们完成由异步到同步调用的模拟。?/span> Client 对其他模块的调好像是同步的一栗?/span>
SynProxy lg的结构如下:
图表
2
SynProxy
的静态结?/span>
SynProxy: l织完成异步到同步调用的转换
WaitingQueue: 存放q未获得执行q回值的 Command 对象
UIDCreator: 产生能够唯一标示每个 Command 对象?/span> UID
ResponseReceiver: 监听响应队列中的响应消息Q它在独立的U程中运?/span>
Command Q命令对?/span>
Response Q响应对?img height="769" alt="p3.jpg" src="http://www.tkk7.com/images/blogjava_net/chaocai/p3.jpg" width="860" border="0" />
图表 3 异同步调用转化成同步调用的q程
部分解释Q?/span> ( 以上以在 JAVA 环境中ؓ?/span> )
Wait 表示调用 Command ?/span> wait Ҏd住当前线E?/span>
Command 执行模块在执行了响应操作后生?/span> Response 对象用于攑֛l果Q?/span> Response 对象中的 UID 属性应该与处理?/span> Command ?/span> UID 的值相?/span>
Notify 表示调用 Command ?/span> notify Ҏ唤醒被阻塞的U程
上面q程中的 wait 讄了阻塞的时旉Q来自于 Command 对象的属性|
SCEA
Q?/span>
SCBCD
Q?/span>
MCSD
北京天融信Y件架构师
SUN,Microsoft培训中心牚w高端教师
常年提供架构咨询服务
chaocai2001@yahoo.com.cn
Q?/span>
010-82776427
软g架构设计已经逐渐成ؓC软g开发过E的核心Q然而能够清晰表明架构设计ƈ不是一件容易的事,面向对象开发而言Q?/span> RUP ?/span> 4+1 视图已在架构设计的撰写中得到了广泛的应用和认可?/span>
对于 4+1 view 的描q有几个不同版本Q或包含的视图不同,或视囄名称不同Q,文中?/span> Philippe Kruchten, November 1995 提出?/span> 4+1 视图为准?/span>
4+1 视图包括Q逻辑视图Q?/span> Logic View Q,开发视图( Develop View Q,q程视图Q?/span> Process View Q,物理视图Q?/span> Physical View Q和场景视图Q?/span> Scenarios Q?/span>
视图间的关系
4+1 视图不仅便于我们记录架构设计Q实际上它也指导了我们进行架构设计活动的部分q程?/span>
通常我们选择 UML 来表现各U视图,以下列出?/span> UML 和各视图的对应关p?/span>
4+1 视图 UML
场景视图 use case
逻辑视图 cd
开发视?/span> cdQ组件图
q程视图 无完全对?/span>
部v视图 部v?/span>
在架构设计稳定中通常不会l出较多的用例描qͼq些是在需求稳定中定义。但是往往架构文档会选择一些用例,列入文档中,q些用例和一些非功能性需求一L以证明架构的有效和正性。在逻辑视图中用例的实现是必不可的一节,管架构设计更关注非功能性需求?/span>
对于逻辑视图和开发视图所应包含的内容常常会觉得很隑分两者间的明昄限。逻辑视图包含更多的分析模型与实现技术本w相x应该较,如业务对象模型及其扩展。而开发视囑ֈ会与实现技术紧密相兟?/span>
随着 MDA 思想的推q,在架构设计文档的撰写斚w也生了影响Q我们不难把 MDA ?/span> PIM 和逻辑视图联系hQ而把 MDA 中的 PSM 和开发视图联pv来?/span>
在编写逻辑视图是我们应该描qC技术^台无关的模型Q而开发视囑ֈ描述与实现技术^台相关的模型?/span>
如在逻辑视图中表现的某些实体c,我们会在开发视图中转换?/span> EJB lgQ实?/span> Bean Q?/span>
q种做法不仅有利于我们编写架构设计文档,同时更是一U好的架构设计思考流E?/span>
一般应用中用户界面的变化相对较为频J?/span> , 有时需要支持多U表现模式(?/span> WEB 客户端和 GUI 客户端)Q但是数据和业务逻辑相对保持E_?/span>
MVC(Model-View-Controller) 模式是一U常用的设计模式 ,MVC 模?/span> , 昄和控制进行了分离Q可以得应用更加方便实现对多种表现模式的支持及降低表现形式修改Ҏ体系l的影响。由于本文重点讨论的?/span> MVC 中的通知机制Q至?/span> MVC 的其它内容可以参考其它相x档?/span>
图表 1 MVC 模式
上图是在 SUN ?/span> J2EE BluePrints 中关?/span> MVC 模式的描q?/span> , 在实?/span> MVC 模式旉先应该注意的是模型与视图之间的关pR在q些关系中尤其值得大家注意的是模型通知视图Q如果不能正的设计q个通知机制Q模型与视图之间兌实现通知Q便会完全违?/span> MVC 的设计初街?/span> MVC 模式的其中一个目的在于模式独立与视图,然而不正确的理解和设计通知机制会导致模型和试图的依赖性?/span>
既要实现模式到视囄通知机制Q同时有要确保实现模型与视图的分R通常我们可以通过Observer模式来实现这L通知机制?br />
图表2 Observer模式
视图实现 Observer 接口Qƈ向模型注册,模型通过调用所l护的观察者的实例调用 Update Ҏ来通知视图q行h。可见, Observer 接口有效的实C模型和视N的耦合性的分离?/span>
图表 3 Z MVC ?/span> J2EE 应用
在将 MVC 模式应用于的Ml构Ӟ常常会有是模型通知视图q是控制器通知视图的问题,其实我认个问题完全取决于对系l各个部分的划分和理解,如果我们把模型层更多划分为数据实?/span> ( 如: Entity Bean) 则可能会发现Q其实我们的通知机制是不能由模型部分来完成的Q而是由我们的控制器来完成的。这U划分好象有些违背了 MVC 模式Q但实事上特别是一些想要同时支?/span> B/S ?/span> C/S ?/span> J2EE 应用Q控制器和模式通知机制常常有较大的耦合性( C/S l构中,客户完全通过会话 Bean 来完成业务)Q可能有时在一起实现更好?/span>
MQ更好的内聚性和更松散的耦合性才是架构设计的重点Q应该做出适合自n应用?/span> MVC 架构?/span>
MVC 模式的关键在于分L变和不易变部分间的耦合性,所以在应用 MVC 模式时一定要注意解耦才是关键,同时一定要更据具体的用环境进行调_不要生搬套Q如 Microsoft ?/span> MFC 采用?/span> Document-view 是 MVC 的变体,它把控制器合q到视图中,q是因ؓ考虑了视图与控制器紧耦合的媄响?/span>
【参考文献?/span>
1Q?span style="font: 7pt 'Times New Roman'"> Sun Microsystem Q?/span> J2EE BluePrints
2Q?span style="font: 7pt 'Times New Roman'"> GOF,Design Patterns, 机械工业出版C, 2002
作者: 蔡超