UML之轻松入门(1)-类图

     曾经看到过一篇blog,上面探讨了学习UML和学习设计模式的区别,同时提出了学习UML还不如学习设计模式的观点。自我感受是,UML和设计模式在本质上属于完全不同的两个方向。设计模式是一种被反复使用、多数人知晓的、代码设计经验的总结。它可以更容易让人理解而且保证了代码的可靠性,而UML则是一种模型化和可视化的一种语言。可以这么说,设计模式是一种方法,它让我们的代码更有层次感 。而UML则是一种表达,它让我们的代码更加形象化。通过UML我们不必太过关注代码,不必担心客户是否了解相关的语言知识,整体的架构和功能的分析和实现成为我们的主要任务。应此,学习UML和设计模式都是很必要的。
     UML是标准建模语言的简称,它是一个支持模型化和软件系统开发的图形化语言。为原件开发的所有阶段提供模型化和可视化支持。一般来说,软件开发可以分为5个阶段1.需求分析阶段,主要是根据客户的需求进行系统功能建模,每一个客户需求都是一个用例。2.分析,主要是考虑需要解决的问题,利用逻辑图和动态图等方式描述系统特征。3.设计,主要是将分析阶段扩展为解决方案。4.构造,主要是吧设计阶段的类转化为相应的代码。5.测试,对系统进行单元和协同测试,以验证系统是否符合要求。
     UML有3类主要的图,分别是静态图,动态图和物理图。其中静态图主要表示类、对象的结构和之间的关系。动态图表示在运行期间软件实体的变化。物理图则表示软件实体的不变物理结构,如源文件、2进制文件等。
     现在通过实例观察类图的用法:

     1.类的表示


     例如在java中我们定义了一个Person类
     
   public   class   Person {
      private   String   name ;
      private   int   age ;
      public   int   publicId ;
      protected   int   className ;
      public   void   setName(String name){
              this .   name   = name;
     }
      public   String getName(){
              return   this .   name ;
     }
   }

     这个类在UML图中的表示是

    

     从这个实例中我们看出:
1.类的组成:类名称写在第一排,类的属性写在第二排,类的方法写在第三排。 +代表public-代表private#代表protected
2.类的属性:其格式为     (+|-|#)?(yourClassName):(type)     
3.类的方法:其格式为     (+|-|#)?(yourClassName/((params)?/)):(type)     和类属性稍有不同的是,可以传入参数,“:”后代表的是传参的类型

     2.类的关联


     类的关联大致包括3个方面继承包含另一个类的引用 接口

     继承:


     在java中定义一个Man类,让它继承Person类

     public   class   Man   extends   Person {
      private   int   money ;
      public   int   getMoney() {
              return   money ;
     }
      public   void   setMoney(   int   money) {
              this .   money   = money;
     }
   }

     在UML图中可以这么表示

    

     从这张图可以看出:我们可以用一个带空心三角形的符号来表示继承的关系。同时,箭头指向的类为超类箭头的源头为子类

     包含另一个类的引用


     在这里我们创建一个Woman类,它包含Man的一个引用。在实际生活中很多家庭主妇的钱都是老公赚的(除了女强人,哈哈)。因此,在Woman类中money属性的值是由Man的一个引用来决定的。代码实现如下:
    
    public   class   Woman {
      private   Man   myMan ;
      private   int   money ;
      public   int   getMoney(){
              this .   money   =   myMan .getMoney();
              return   this .   money ;
     }
      public   void   setMyMan(Man man){
              this .   myMan   = man;
     }
  }

    用UML图我们可以这么表示:

    

     从图中我们可以看到:当一个类拥有另一个类的引用时,应用带箭头的线表示,箭头指向为被引用的对象源头为引用者
     这里要注意箭头的不同,继承为三角形,而引用则不是。

     接口


     java中接口是实现多态的重要一环,也是封装不可缺少的一部分。在UML中对接口的使用也有特殊的表示:

    

     从图可以看出:UML中的接口用一个圆圈和一条直线表示。

     3.创建特殊的类


     在java中我们常需要创建一个接口来实现封装。我们也常需要创建一个抽象类来实现多态。有时候,我们也要用一个静态类作为一个静态常量的容器。下面我们一起学习如何在UML中表示这些特殊的类。
     

     接口类


     在java中我们定义一个Student接口,这个接口要实现write()和read()方法。

      public   interface   Student {
      public   void   write();
      public   void   read();
   }      

     这个接口在UML中的表示方法如下:

    

     从图中我们可以看出:可以用<<interface>>来表示一个接口类

     静态类


     我们在java中定义一个Math的静态类,其中定义PI的属性:     

      public   class   MathParams {
      static   class   Math {
              public   static   final   double   PI   = 3.141592654;
     }
   }

     这个静态类,我们在UML中可以这么表示:

    

     从图中可以看出:可以用<<utility>>来表示一个静态类。

     抽象类


     在java中我们定义一个抽象Person类,这个Person类有两个方法,抽象的write()方法和具体的eat()方法(因为每个人都会吃,但不是每个人都会写字,呃...)。

      public   abstract   class   PersonAbstract {
      public   abstract   void   write();
      public   void   eat(){
              //...
     }
   }
 
     这个抽象类在UML中的表达方式是:

    

     从图中可以看出,抽象的类和方法都用斜体 表示。因为本人用的是VISIO开发工具,其默认是用斜体表示。还有另一种表示方法是在抽象的类和方法后加上{abstract}约束。而且这个“{}”不仅可以加"abstract",还可以添加自己的属性,如{name = "Lee",age = 13}。

     4.类图中的一些常用标记


    

     这三种表示方法差别并不大,所以在大多数时候只采用第一种方式就行了。最后一种方式可以表示:两个类是组合在一起的,即Woman的一个对象复制后,它对应的那个Man对象也会复制。当Woman的一个对象清空时,那么它对应的那个Man对象也会被清空。

     内部类是用一个圆圈中含有十字架加上一条线段组成(在VISIO中并未找到,还请了解的人相告)。

     在包含类的引用时,当包含的引用不止一条时,我们就需要用一个容器装载包含的引用,可能是Vector,也可能是其他的。这时,我们可以用关联类的表示:

    

     5.一个简单的应用


     这里是一个简单的二元树算法:
     首先,为了更加容易的理解算法,我们回顾一下Comparable接口Comparator接口。
     Comparable和Comparator都实现了比较的功能,不能的是:1.Comparable是java.lang包,而Comparator是java.util包中。2.Comparable接口需要绑定到一个指定的类上,而Comparator则不需要。因此,comparator更加灵活。3.Comparable需要重写comparaTo方法,且只需传入绑定的对象一个参数,而Comparator需要重写compare方法,需要传入比较的两个对象,两个参数。下面我们用比较两个字符串的长度来看看两中方法的差别:
     
     使用Comparable来比较两个字符串的长度:
   
   //通过实现Comparable接口来自定义比较的规则,实现compareTo方法
 public   class   MyComparable   implements   Comparable<MyComparable> {

      //这个例子实现比较两个字符串的长度
      private   String   compareString ;
     MyComparable(String compareString){
              this .   compareString   = compareString;
     }
     
      //这里重写两个比较的规则
      @Override
      public   int   compareTo(MyComparable o) {
              //   TODO   Auto-generated method stub
              return   this .   compareString .length() - o. compareString .length();
     }
  }

     使用Comparator来比较两个字符串的长度:

      import   java.util.Comparator;

   //实现Comparator接口无需绑定类,可实现动态排序
   public   class   Mycomparator   implements   Comparator<String> {

      @Override
      public   int   compare(String o1, String o2) {
              //   TODO   Auto-generated method stub
              return   o1.length() - o2.length();
     }
   }

     了解了Comparable接口的用法后,我们来看简单的二元树的算法:

      public   class   TreeMap {

     TreeMapNode   topNode   =   null ;
      public   void   add(Comparable key,Object value){
              if (   topNode   ==   null )
                   topNode   =   new   TreeMapNode(key,value);
              else
                   topNode .add(key,value);
     }
     
      public   Object get(Comparable key){
              return   topNode   ==   null ?   null :   topNode .get(key);
     }
   }

   class   TreeMapNode {

      public   static   final   int   LESS   = 0;
      public   static   final   int   GREATER   = 1;
      private   Comparable   itsKey   ;
      private   Object   itsValue ;
      private   TreeMapNode   nodes [] =   new   TreeMapNode[2];
     
      public   TreeMapNode(Comparable key,Object value) {
              //   TODO   Auto-generated constructor stub
              this .   itsKey   = key;
              this .   itsValue   = value;
     }
      public   void   add(Comparable key, Object value) {
              //   TODO   Auto-generated method stub
              if (   itsKey .compareTo(key) == 0)
                   itsValue   = value;
              else
                addSubNode(selectSubNode(key),key,value);
     }

      private   void   addSubNode(   int   node, Comparable key, Object value) {
              //   TODO   Auto-generated method stub
              if   (   nodes [node] ==   null )
                   nodes [node] =   new   TreeMapNode(key, value);
              else
                   nodes [node].add(key, value);
     }
      private   int   selectSubNode(Comparable key) {
              //   TODO   Auto-generated method stub
              return   ( key.compareTo( itsKey ) < 0)?   LESS :   GREATER ;
     }
      public   Object get(Comparable key) {
              //   TODO   Auto-generated method stub
              if ( key.compareTo( itsKey ) == 0)
                   return   itsValue ;
              return   getSub(selectSubNode(key),key);
     }
      private   Object getSub(   int   node, Comparable key) {
              //   TODO   Auto-generated method stub
              return   nodes [node] ==   null ?   null :   nodes [node].get(key);
     }
     
   }

     下面我们用UML图来表示这个类:

    

     6.总结

     
     UML本来就是一个让代码更加形象的东东,应此不需要太过复杂。所以UML的内容最好比较简洁明朗,达到言简意赅的效果才是最好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值