??xml version="1.0" encoding="utf-8" standalone="yes"?> UML的类囑օpd为:(x) 兌、聚?l合、依赖、泛化(l承Q。而其中关联又分ؓ(f)双向兌、单向关联、自w关联;下面p我们一h看看q些关系I竟是什么,以及(qing)它们的区别在哪里?/p>
1、关?/strong> 双向兌Q?/font> C1-C2Q指双方都知道对方的存在Q都可以调用Ҏ(gu)的公共属性和Ҏ(gu)?/font> 在GOF的设计模式书上是q样描述的:(x)虽然在分析阶D这U关pL适用的,但我们觉得它对于描述设计模式内的cdpL说显得太抽象了,因ؓ(f)在设计阶D关联关pd被映射为对象引用或指针。对象引用本w就是有向的Q更适合表达我们所讨论的那U关pR所以这U关pd设计的时候比较少用到Q关联一般都是有向的?/font> 使用ROSE 生成的代码是q样的:(x) 双向兌在代码的表现为双斚w拥有Ҏ(gu)的一个指针,当然也可以是引用或者是倹{?/font> 单向兌: C3->C4Q表C相识关p,指C3知道C4QC3可以调用C4的公共属性和Ҏ(gu)。没有生命期的依赖。一般是表示ZU引用?/font> 生成代码如下Q?/font> 单向兌的代码就表现为C3有C4的指针,而C4对C3一无所知?/font> 自n兌Q反w关联)Q?/font> 自己引用自己Q带着一个自q引用?/font> 代码如下Q?/font> 是在自q内部有着一个自w的引用?/font> 2、聚?l合 当类之间有整?部分关系的时候,我们可以用组合或者聚合?/p>
聚合Q表CC9聚合C10Q但是C10可以dC9而独立存在(独立存在的意思是在某个应用的问题域中q个cȝ存在有意义。这句话怎么解,L(fng)下面l合里的解释Q?/font> 代码如下Q?/font> l合Q也有hUCؓ(f)包容Q:(x)一般是实心菱Ş加实U箭头表C,如上图所C,表示的是C8被C7包容Q而且C8不能dC7而独立存在。但q是视问题域而定的,例如在关心汽车的领域里,轮胎是一定要l合在汽车类中的Q因为它d了汽车就没有意义了。但是在卖轮胎的店铺业务里,q轮胎d了汽车,它也是有意义的,q就可以用聚合了。在《敏捷开发》中q说刎ͼAl合BQ则A需要知道B的生存周期,卛_能A负责生成或者释放BQ或者A通过某种途径知道B的生成和释放?/font> 他们的代码如下:(x) 可以看到Q代码和聚合是一L(fng)。具体如何区别,可能只能用语义来区分了?/p>
3、依?/strong> 依赖: 指C5可能要用到C6的一些方法,也可以这栯Q要完成C5里的所有功能,一定要有C6的方法协助才行。C5依赖于C6的定义,一般是在C5cȝ头文件中包含了C6的头文g。ROSE对依赖关pM产生属性?/font> 注意Q要避免双向依赖。一般来_(d)不应该存在双向依赖?/font> ROSE生成的代码如下:(x) 虽然ROSE不生成属性,但在形式上一般是A中的某个Ҏ(gu)把B的对象作为参C?假设A依赖于B)。如下:(x) 那依赖和聚合\l合、关联等有什么不同呢Q?/font> 兌是类之间的一U关p,例如老师教学生,老公和老婆Q水壶装水等是一U关pR这U关pL非常明显的,在问题领域中通过分析直接p得出?/font> 依赖是一U弱兌Q只要一个类用到另一个类Q但是和另一个类的关pM是太明显的时候(可以说是“uses”了那个类Q,可以把q种关系看成是依赖,依赖也可说是一U偶然的关系Q而不是必然的关系Q就?#8220;我在某个Ҏ(gu)中偶然用C它,但在现实中我和它q没多大关系”。例如我和锤子,我和锤子本来是没关系的,但在有一ơ要钉钉子的时候,我用C它,q就是一U依赖,依赖锤子完成钉钉子这件事情?/font> l合是一U整?部分的关p,在问题域中这U关pd明显Q直接分析就可以得出的。例如轮胎是车的一部分Q树(wi)叶是?wi)的一部分Q手脚是w体的一部分q种的关p,非常明显的整?部分关系?/font> 上述的几U关p(兌、聚?l合、依赖)在代码中可能以指针、引用、值等的方式在另一个类中出玎ͼ不拘于Ş式,但在逻辑上他们就有以上的区别?/font> q里q要说明一下,所谓的q些关系只是在某个问题域才有效,d了这个问题域Q可能这些关pd不成立了Q例如可能在某个问题域中Q我是一个木匠,需要拿着锤子dz,可能整个问题的描q就是我拿着锤子怎么钉桌子,钉椅子,钉柜子;既然整个问题是描述q个Q我和锤子就不仅是偶然的依赖关系了,我和锤子的关pd得非常的紧密Q可能就上升为组合关p(让我H然惌v武侠说的剑不离w,剑亡Z...Q。这个例子可能有点荒谬,但也是ؓ(f)了说明一个道理,是关系和类一P它们都是在一个问题领域中才成立的Q离开了这个问题域Q他们可能就不复存在了?/font> 4、泛化(l承Q?/strong> 泛化关系Q如果两个类存在泛化的关pL׃用,例如父和子,动物和老虎Q植物和q?/font> ROSE生成的代码很单,如下Q?/font> 5、这里顺便提一下模?/font> 上面的图对应的代码如下:(x) q里再说一下重复度Q其实看完了上面的描qC后,我们应该清楚了各个关p间的关pM?qing)具体对应到代码是怎么L(fng)Q所谓的重复度,也只不过是上面的扩展Q例如A和B有着“1对多”的重复度Q那在A中就有一个列表,保存着B对象的N个引用,是q样而已?/font> package com.semovy.bean; public class Person { private String name; private String note; public String getId() { public void setId(String id) { public String getName() { public void setName(String name) { public String getNote() { public void setNote(String note) { public Person(String id, String name, String note) { @Override } package com.semovy.service; import java.util.ArrayList; import com.semovy.bean.Person; public interface PersonService { public List<Person> persons = new ArrayList<Person>(); public abstract void addPerson(Person person); public abstract Person getPersonById(String id); public abstract void deletePersonById(String id); //public abstract void updatePerson(Person person); public abstract void displayPersonById(String id); public abstract void displayAllPersons(); package com.semovy.service.impl; import java.util.Iterator; import com.semovy.bean.Person; public class PersonServiceImpl implements PersonService { public void addPerson(Person person) { public void deletePersonById(String id) { public void displayAllPersons() { public void displayPersonById(String id) { public Person getPersonById(String id) { /*public void updatePerson(Strin) { } 4.写日志的代理cLogProxy 它实CInvocationHandler接口 package com.semovy.bean; import java.lang.reflect.InvocationHandler; import org.apache.log4j.Level; public void setDelegate(Object delegate) { public Object bind(Object delegate) { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 5.在eclipse中添加log4j.properties package com.semovy.test; import java.io.File; import com.semovy.bean.LogProxy; public class Test { /** LogProxy logProxy = new LogProxy();
1000){this.resized=true;this.style.width=1000;}">
1000){this.resized=true;this.style.width=1000;}" align=top>class C1
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>public:
1000){this.resized=true;this.style.width=1000;}" align=top> C2* theC2;
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>class C2
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>public:
1000){this.resized=true;this.style.width=1000;}" align=top> C1* theC1;
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}">
1000){this.resized=true;this.style.width=1000;}" align=top>class C3
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>public:
1000){this.resized=true;this.style.width=1000;}" align=top> C4* theC4;
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>class C4
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}">
1000){this.resized=true;this.style.width=1000;}" align=top>class C14
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>public:
1000){this.resized=true;this.style.width=1000;}" align=top> C14* theC14;
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}">
1000){this.resized=true;this.style.width=1000;}" align=top>class C9
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>public:
1000){this.resized=true;this.style.width=1000;}" align=top> C10 theC10;
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>class C10
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}">
1000){this.resized=true;this.style.width=1000;}" align=top>class C7
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>public:
1000){this.resized=true;this.style.width=1000;}" align=top> C8 theC8;
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>class C8
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}">
1000){this.resized=true;this.style.width=1000;}" align=top>// C5.h
1000){this.resized=true;this.style.width=1000;}" align=top>Qi nclude "C6.h"
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>class C5
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>// C6.h
1000){this.resized=true;this.style.width=1000;}" align=top>Qi nclude "C5.h"
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>class C6
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>Qi nclude "B.h"
1000){this.resized=true;this.style.width=1000;}" align=top>class A
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top> void Func(B &b);
1000){this.resized=true;this.style.width=1000;}" align=top>}
1000){this.resized=true;this.style.width=1000;}">
1000){this.resized=true;this.style.width=1000;}" align=top>Qi nclude "C11.h"
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>class C12 : public C11
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}">
1000){this.resized=true;this.style.width=1000;}" align=top>template<int>
1000){this.resized=true;this.style.width=1000;}" align=top>class C13
1000){this.resized=true;this.style.width=1000;}" align=top>
1000){this.resized=true;this.style.width=1000;}" align=top>...{
1000){this.resized=true;this.style.width=1000;}" align=top>};
1000){this.resized=true;this.style.width=1000;}" align=top>
]]>
Person.java
private String id;
return id;
}
this.id = id;
}
return name;
}
this.name = name;
}
return note;
}
this.note = note;
}
super();
this.id = id;
this.name = name;
this.note = note;
}
public String toString() {
// TODO Auto-generated method stub
return "id: " + id + " name: " + name + " note: " + note;
}
2.操作Person实体cȝ接口PersonService
PersonService.java
import java.util.List;
}
3.实现PersonService接口的PersonServiceImpl
PersonServiceImpl.java
import com.semovy.service.PersonService;
persons.add(person);
}
Iterator it = persons.iterator();
while(it.hasNext())
{
Person person = (Person)it.next();
if(person.getId().equals(id))
{
it.remove();
break;
}
}
}
Iterator it = persons.iterator();
while(it.hasNext())
{
Person person = (Person)it.next();
System.out.println(person.toString());
}
}
Iterator it = persons.iterator();
while(it.hasNext())
{
Person person = (Person)it.next();
if(person.getId().equals(id))
{
System.out.println(person.toString());
break;
}
}
}
Iterator it = persons.iterator();
while(it.hasNext())
{
Person person = (Person)it.next();
if(person.getId().equals(id))
{
return person;
}
}
return null;
}
Iterator it = persons.iterator();
while(it.hasNext())
{
Person person = (Person)it.next();
if(person == aperson)
{
persons.set(arg0, arg1)
}
}
}*/
LogProxy.java
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.apache.log4j.Logger;
public class LogProxy implements InvocationHandler {
Logger logger = Logger.getLogger(this.getClass().getName());
private Object delegate = null;
public Object getDelegate() {
return delegate;
}
this.delegate = delegate;
}
this.delegate = delegate;
return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(),this);
}
Object result = null;
try
{
logger.log(Level.INFO,method.getName() + " 开始处?..");
result = method.invoke(this.delegate, args);
logger.log(Level.INFO,method.getName() + " l束处理...");
}catch(Exception e)
{
logger.log(Level.ERROR,e.getLocalizedMessage());
}
return result;
}
}
log4j.properties
log4j.rootLogger=DEBUG,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %5p (%F:%L) - %m%n
5.写测试类Test.java
Test.java
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import com.semovy.bean.Person;
import com.semovy.service.PersonService;
import com.semovy.service.impl.PersonServiceImpl;
* @param args
*/
public static void main(String[] args) {
PersonService personService = (PersonService)logProxy.bind(new PersonServiceImpl());
personService.addPerson(new Person("1","name1","note1"));
personService.addPerson(new Person("2","name2","note2"));
personService.addPerson(new Person("3","name3","note3"));
personService.addPerson(new Person("4","name4","note4"));
personService.displayPersonById("3");
personService.displayAllPersons();
Person person = personService.getPersonById("2");
person.setName("名称2");
person.setNote("注脚2");
personService.displayAllPersons();
personService.deletePersonById("2");
personService.displayAllPersons();
//saveToFile(persons,"c:/persons.txt");
}
public static void saveToFile(List list,String path)
{
System.out.println("开始写入文?..");
try
{
PrintWriter out = new PrintWriter(new File(path));
Iterator it = list.iterator();
while(it.hasNext())
{
Person person = (Person)it.next();
out.println(person.toString());
}
out.flush();
out.close();
System.out.println("l束写入文g...");
}catch(IOException e)
{
System.out.println(e.getLocalizedMessage());
}
}
}
6.q行试l果:
2008-02-05 02:55:28,926 INFO (LogProxy.java:34) - addPerson 开始处?..
2008-02-05 02:55:28,926 INFO (LogProxy.java:36) - addPerson l束处理...
2008-02-05 02:55:28,926 INFO (LogProxy.java:34) - addPerson 开始处?..
2008-02-05 02:55:28,926 INFO (LogProxy.java:36) - addPerson l束处理...
2008-02-05 02:55:28,926 INFO (LogProxy.java:34) - addPerson 开始处?..
2008-02-05 02:55:28,936 INFO (LogProxy.java:36) - addPerson l束处理...
2008-02-05 02:55:28,936 INFO (LogProxy.java:34) - addPerson 开始处?..
2008-02-05 02:55:29,036 INFO (LogProxy.java:36) - addPerson l束处理...
2008-02-05 02:55:29,036 INFO (LogProxy.java:34) - displayPersonById 开始处?..
id: 3 name: name3 note: note3
2008-02-05 02:55:29,036 INFO (LogProxy.java:36) - displayPersonById l束处理...
2008-02-05 02:55:29,036 INFO (LogProxy.java:34) - displayAllPersons 开始处?..
id: 1 name: name1 note: note1
id: 2 name: name2 note: note2
id: 3 name: name3 note: note3
id: 4 name: name4 note: note4
2008-02-05 02:55:29,046 INFO (LogProxy.java:36) - displayAllPersons l束处理...
2008-02-05 02:55:29,046 INFO (LogProxy.java:34) - getPersonById 开始处?..
2008-02-05 02:55:29,046 INFO (LogProxy.java:36) - getPersonById l束处理...
2008-02-05 02:55:29,046 INFO (LogProxy.java:34) - displayAllPersons 开始处?..
id: 1 name: name1 note: note1
id: 2 name: 名称2 note: 注脚2
id: 3 name: name3 note: note3
id: 4 name: name4 note: note4
2008-02-05 02:55:29,046 INFO (LogProxy.java:36) - displayAllPersons l束处理...
2008-02-05 02:55:29,046 INFO (LogProxy.java:34) - deletePersonById 开始处?..
2008-02-05 02:55:29,046 INFO (LogProxy.java:36) - deletePersonById l束处理...
2008-02-05 02:55:29,046 INFO (LogProxy.java:34) - displayAllPersons 开始处?..
id: 1 name: name1 note: note1
id: 3 name: name3 note: note3
id: 4 name: name4 note: note4
2008-02-05 02:55:29,046 INFO (LogProxy.java:36) - displayAllPersons l束处理...
]]>
q两天又在接触一个新目Q对于如何设计一个项目的框架有了Ҏ(gu)念,关于web目Q对于oapȝ来说Q的M感觉比较需要设计的几部分ؓ(f)Q?/span>
1Q?nbsp;面模板定义Q关于view层展C,无论对于topQ顶层菜单)+leftQ左Ҏ(gu)(wi)状菜单)+rightQ主体内容)l构q是left+rightl构Q都需要首先定制一些模板,如struts中可使用tiles定义?/span>
2Q?nbsp;分页标签Q自定义一个比较通用的分|{或者用一些框架中自带的(如struts-menu或者JSF中的t:dataScrollerQ,不过比较好的做法是基于其源码~写自己的分|{?/span>
3Q?nbsp;DB 设计Q可使用Power Deisign{设计数据库表结构,产生相关的表?/span>
4Q?nbsp;代码自动生成Q编写代码生成脚本如build.xml文g的编写(Ҏ(gu)DB生成代码Q也可以忽略3Q先建modelQ再从model生成代码和数据库schemaQ,生成Struts、Spring、Hibernate相关文g?/span>
关于代码的整体架构如下:(x)
action 层:(x)处理从view层传递过来的数据?/span>
service 层:(x)装业务逻辑Q一般同时在spring中声明事务代理?/span>
dao 层:(x)q行事务中的原子操作Q同时在spring中注入相应的sessionFactory?/span>
Spring + Struts 取得spring的bean的两U常用方法:(x)
1. DelegatingActionProxy Q将所有action标签中type属性设为org.springframework.web.struts.DelegatingActionProxy 也就是将action委托l了springQ同时在 action-servlets.xml 中配|一个于action标签path属性对应的bean(也就是bean的name值等于action的path?Q如Q?/span>
struts-config.xml 中,以struts的plugin的方?让spring接管struts的actionQ?/span>
< action name = "portalForm" parameter = "method" path = "/portalAction" type = "org.springframework.web.struts.DelegatingActionProxy" scope = "request" >
< forward name = "portalEdit" path = " pages/portalEdit.jsp" />
< forward name = "portalList" path = " pages/portalList.jsp " />
</ action >
< plug-in className = "org.springframework.web.struts.ContextLoaderPlugIn" >
< set-property property = "contextConfigLocation"
value = "/WEB-INF/action-servlets.xml" />
</ plug-in >
action-servlets.xml Q配|文件格式和spring配置一P中:(x)
< beans >
< bean name = "/portalAction"
class = "com.cn.lively.action.PortalMainAction" >
< property name = "portalService" >
< ref bean = "portalService" />
</ property >
</ bean >
</ beans >
2. WebApplicationContextUtils.getRequiredWebApplicationContext Q在action中获得spring的beanQ?/span>
public Object getService (String name) {
ApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servlet.getServletContext());
return wac .getBean(name);
}
q种方式没有在struts里边加入spring的pluginQ实际上是用了依赖查找来获得对象,q且在servlet代码中硬~码了应用对象的bean名字?/span>
附:(x)
感觉一个国内小型项目(周期半年左右Q的开发,完美的团队大概四个h左右够了,
A Q前期框架设?+ 开发过E中不断改进完美整个框架Q角艜y—架构师
B Q前期需求调?+ 开发过E中负责技术难度比较大的模块开发,角色——程序员
C Q前期需求调研负责h + 开发过E中负责业务逻辑复杂的模块开发,角色——项目负责h
D Q前期需求调?+ 开发过E中负责模块开发,角色——程序员
同时B、C负责共同解决开发中出现的技术和业务问题QC负责控制目q度Q?/span>
目后期QB、C、Dq行交叉试QA负责review代码?/span>
如果公司已经比较成熟的框Ӟ卛_本系l管理模?+ 代码自动生成Q,那么角色A可以省略Q只需要B、C、D三个人即可进行项目开发,其中角色B在开发中担当一部分A的角艌Ӏ?/span>
甚至可以只由B、C两个行开发,把角色D的工作分担到B、Cw上QB侧重技术,C侧重业务逻辑?/span>
cMcM间的关系对于理解面向对象h很重要的作用Q以前在面试的时候也l常被问到这个问题,在这里我׃l一下?br>cMcM间存在以下关p? UML图与应用代码例子:
2.依赖(Dependency) [依赖] 对于两个相对独立的对象,当一个对象负责构造另一个对象的实例Q或者依赖另一个对象的服务Ӟq两个对象之间主要体Cؓ(f)依赖关系?br>[具体表现] 依赖关系表现?font color=#ff0000>局部变?/font>Q?font color=#ff0000>Ҏ(gu)的参?/font>Q以?qing)?font color=#ff0000>静态方法的调用 [现实例子] 比如说你要去拧螺丝,你是不是要借助(也就是依?Z刀(Screwdriver)来帮助你完成拧螺?screw)的工?br>[UML表现](?.2)
3.兌(Association) [兌] 对于两个相对独立的对象,当一个对象的实例与另一个对象的一些特定实例存在固定的对应关系Ӟq两个对象之间ؓ(f)兌关系?br>[具体表现] 兌关系是?font color=#ff0000>实例变量来实?br>[现实例子] 比如客户和订单,每个订单对应特定的客P每个客户对应一些特定的订单Q再例如公司和员工,每个公司对应一些特定的员工Q每个员工对应一特定的公?br>[UML图] (?.3) ![]() ?.3 公司和员工的兌关系 [代码表现]
[聚合] 当对象A被加入到对象B中,成ؓ(f)对象B的组成部分时Q对象B和对象A之间集关pR聚合是兌关系的一U,是较强的兌关系Q强调的?font color=#ff0000>整体?font color=#ff0000>部分之间的关pR?font color=#ff0000>cM于将本职的工作委托给其他c?/font> [具体表现] 与关联关pMP聚合关系也是通过实例变量来实现这样关pȝ。关联关pd聚合关系来语法上是没办法区分的,?font color=#ff0000>语义上才?font color=#ff0000>更好的区?/font>两者的区别?br>[兌与聚合的区别] (1)兌关系所涉及(qing)的两个对象是处在同一个层ơ上的。比如h和自行R是一U关联关p,而不是聚合关p,因ؓ(f)Z是由自行车组成的?br>聚合关系涉及(qing)的两个对象处于不q等的层ơ上Q一个代表整体,一个代表部分。比如电(sh)脑和它的昄器、键盘、主板以?qing)内存就是聚集关p,因ؓ(f)L是电(sh)脑的l成部分?br>(2)对于h聚集关系Q尤其是集关p)的两个对象,整体对象?x)制U它的组成对象的生命周期。部分类的对象不能单独存在,它的生命周期依赖于整体类?对象的生命周期,当整体消失,部分也就随之消失。比如张三的?sh)脑被偷了,那么电(sh)脑的所有组件也不存在了Q除非张三事先把一些电(sh)脑的lgQ比如硬盘和内存Q?拆了下来?br>[UML图](?.4) ![]() ?.3 ?sh)脑和组件的聚合关?/font> [代码表现]
[参考资料] 1.《Java与模式?阎宏 ~著) W??l一建模语言UML?br> 最l的判别可以以内存结构ؓ(f)区分Q比如关联与依赖比较隑ֈ别,那么Q你可以判断Q某个对象是在当前类里被实例的还是,只传了引用!如果是引用,则关联,否则是依赖Q比?br>public class Test { private B b; private A a; public void exec() { A a = new A(); b.exec(); } //a , b 的getter,setter省略 } 其中Acd象a是依赖Q因为a对象的内存空间被创徏在Test q个 c里 而Bcȝb对象则是引用Q?br> |
1. 软g工程?/span>5个阶D:(x)需求分?/strong>(Requirements Capture)Q?strong style="mso-bidi-font-weight: normal">pȝ分析与设?/strong>(System Analysis and Design)Q?strong style="mso-bidi-font-weight: normal">实现(Implement)Q?strong style="mso-bidi-font-weight: normal">试(Test)Q?strong style="mso-bidi-font-weight: normal">l护(Maintenance)?/span>
2. UML的定义包?/span>UML语义?/span>UML表示?/span>两个部分?/span>UML语义描述ZUML的精?strong style="mso-bidi-font-weight: normal">元模型定?/strong>。元模型?/span>UML的所有元素在语法和语义上提供了简单、一致和通用的定义性说明?/span>UML表示法,为开发者或开发工具用图形工具和文本语法为系l徏模提供了标准?/span>
3. UML(Unified Modeling Language)?strong style="mso-bidi-font-weight: normal">视图(View)Q?strong style="mso-bidi-font-weight: normal">?/strong>(Diagram)Q?strong style="mso-bidi-font-weight: normal">模型元素(Model Element)Q?strong style="mso-bidi-font-weight: normal">通用机制(General Mechanism){组成,q提供了扩展机制(Extension Mechanism)Q?/span>UML语言能够适应一个特D的Ҏ(gu)或者扩充到一个组l或用户?/span>
a) 视图是表辄l的某一斚w特征?/span>UML建模元素的子集,由多?strong style="mso-bidi-font-weight: normal">?/strong>构成Q是在某一个抽象层上,对系l的抽象表示?/span>
b) ?/span>是模型元素集?strong style="mso-bidi-font-weight: normal">囑Ş表示Q通常?strong style="mso-bidi-font-weight: normal">?/strong>(关系)?strong style="mso-bidi-font-weight: normal">点(其他模型元素)怺q接构成?/span>
c) 模型元素代表面向对象中的cR对象、消息和关系{概念,是构成图的基本概c(din)?/span>
d) 通用机制用于表示其他信息Q比如注释、模型元素的语义{?/span>
4. UML用模型来描述pȝ的结构或静态特征,以及(qing)行ؓ(f)或动态特征,从不同的视角为系l架构徏模,形成不同视角Q?/span>
a) 用例视图(Use Case View)Q强调从用户角度看到的或需要的pȝ功能Q是被称为参与者的外部用户所能观察到的系l功能的模型图?/span>
b) 逻辑视图(Logical View)Q展现系l的静态或l构l成?qing)特征,也被UCؓ(f)l构模型视图(Structural Model View)或?strong style="mso-bidi-font-weight: normal">静态视?/strong>(Static View)?/span>
c) q发视图(Concurrent View)Q体Cpȝ的动态或者行为特征,也称?strong style="mso-bidi-font-weight: normal">行ؓ(f)模型视图(Behavioral Model View)?strong style="mso-bidi-font-weight: normal">动态视?/strong>(Dynamic View)?/span>
d) lg视图(Component View)Q体Cpȝ实现的结构和行ؓ(f)特征Q也UCؓ(f)实现模型视图(Implementation Model View)?/span>
e) 配置视图(Deployment View)Q体Cpȝ实现环境的结构和行ؓ(f)特征Q也被称?strong style="mso-bidi-font-weight: normal">环境模型视图(Environment Model View)或?strong style="mso-bidi-font-weight: normal">物理视图(Physical View)?/span>
5. 视图由图构成Q?/span>UML提供?/span>9U不同的图:(x)
a) 用例?/span>(Use Case Diagram)Q描q系l功能;
b) cd(Class Diagram)Q描q系l的静态结构;
c) 对象?/span>(Object Diagram)Q描q系l在某个时刻的静态结构;
d) 时序?/span>(Sequence Diagram)Q按旉序描述pȝ元素间的交互Q?/span>
e) 协作?/span>(Collaboration Diagram)Q按照时间和I间序描述pȝ元素间的交互和他们之间的关系Q?/span>
f) 状态图(State Diagram)Q描qCpȝ元素的状态条件和响应Q?/span>
g) zd?/span>(Activity Diagram)Q描qCpȝ元素的活动;
h) lg?/span>(Component Diagram)Q描qC实现pȝ的元素的l织Q?/span>
i) 配置?/span>(Deployment Diagram)Q描qC环境元素的配|,q把实现pȝ的元素映到配置上?/span>
6. 囑֒视图之间的对应关p:(x)
用户模型视图Q用例图
l构模型视图Q类囑֒对象?/font>
行ؓ(f)模型视图Q时序图、协作图、状态图和活动图
实现模型视图Q组件图
环境模型视图Q配|图
7. UML的两套徏模机Ӟ静态徏模机?/strong>?strong style="mso-bidi-font-weight: normal">动态徏模机?/strong>。静态徏模机制包括用例图、类图、对象图、包、组件图和配|图Q动态徏模机制包括消息、状态图、时序图、协作图、活动图?/span>
1997q_(d)OMGl织Q?/span>Object Management Group对象理l织Q发布了l一建模语言Q?/span>Unified Modeling LanguageQ?/span>UMLQ?/span>UML的主要创始h?/span>Jim Rumbaugh?/span>Ivar Jacobson?/span>Grady Booch ,UML的目标之一是为开发团队提供标准通用的设计语a来开发和构徏计算机应用?/span>UML提出了一?/span>IT专业人员期待多年的统 一的标准徏模符受通过使用UMLQ这些h员能够阅d交流pȝ架构和设计规?/span>, UMLW号集只是一U语a而不是一U方法学. 2003q_(d)UML已经获得了业界的认同.
2.q?/span>
UML捕捉了Y件系l有兛_{和理解,用来理解、设计、浏览、配|、维护以?qing)控制系l得信息.UML包括语义概念、标记符号和指南,据有静态、动态、环境上和组l性的部分.
<!--[if !supportLists]-->IQ?span> <!--[endif]-->UML捕捉静态结构和动态行为的信息。系l徏模成独立对象的集合以?qing)它们交互和实现。静态结构定义各U对象和实现已经它们的关p,动态行为定义了对象间的通讯。可以从不同视角q行建模Q以不同视角理解pȝ?/span>
<!--[if !supportLists]-->IIQ?span> <!--[endif]-->UML可以用包来组l模型结?/span>
3Q目?/span>
UML不是完整的开发方法,它不包括逐步的开发流E。但UML包括了所有必要的概念来解决现代P代过E中解决用例驱动的需求?/span>
4Q?/span>UML概念范围
IQ?/span> 静态结?/span>
IIQ?/span> 动态行?/span>
<!--[if !supportLists]-->IIIQ?span> <!--[endif]--> 实现构?/span>
<!--[if !supportLists]-->IVQ?span> <!--[endif]--> 模型l织
<!--[if !supportLists]-->VQ?span> <!--[endif]--> 扩展机制
5. UML视图
UML视图可以分ؓ(f)三个领域Q?span>l构型分cR动态行为和模型理
IQ结构性分cd括静态视图、用例视囑֒实现视图。它描述了系l中事物和事物之间的关系Q包括类、用例、构件和节点Qؓ(f)构徏动态行为提供了基础?/span>
IIQ动态行为包括状态机视图、活动图和交互图。它描述了系l时间上的行?/span>
IIIQ模型管理,用包来组l模型,Ҏ(gu)的包包括模型和子pȝQ模型视囑֒其它视图交PQؓ(f)团队工作和配|控制把它们l织h?/span>
IVQ扩展,包括U束、版型和标签倹{?/span>
摘自 chenkaituo 的BLOG