精华内容
下载资源
问答
  • java 中几种常用数据结构

    万次阅读 多人点赞 2016-07-11 09:11:27
    java中有几种常用的数据结构,主要分为Collection和map两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类。其主要的关系(继承关系): (----详细参见java...

    JAVA中常用的数据结构(java.util. 中)

    java中有几种常用的数据结构,主要分为Collection和map两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类。其主要的关系(继承关系)有:  (----详细参见java api文档!)

    Collection---->Collections                                                                                                          Map----->SortedMap------>TreeMap

    Collection---->List----->(Vector \ ArryList \ LinkedList)                                                          Map------>HashMap

    Collection---->Set------>(HashSet \ LinkedHashSet \ SortedSet)

    --------------Collection----------------

    1、Collections

        API----This class consists exclusively of static methods that operate on or return collections. It contains polymorphic algorithms that operate on collections, "wrappers", which return a new collection backed by a specified collection, and a few other odds and ends.

    The methods of this class all throw a NullPointerException if the collections or class objects provided to them are null. 

    2、List

        API----This class consists exclusively of static methods that operate on or return collections. It contains polymorphic algorithms that operate on collections, "wrappers", which return a new collection backed by a specified collection, and a few other odds and ends.

    The methods of this class all throw a NullPointerException if the collections or class objects provided to them are null. 

    List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下 >标)来访问List中的元素,这类似于Java的数组。

    3、Vector

         API----The Vector class implements a growable array of objects. Like an array, it contains components that can be accessed using an integer index. However, the size of aVector can grow or shrink as needed to accommodate adding and removing items after theVector has been created. 

    基于数组(Array)的List,其实就是封装了数组所不具备的一些功能方便我们使用,所以它难易避免数组的限制,同时性能也不可能超越数组。所以,在可能的情况下,我们要多运用数组。另外很重要的一点就是Vector是线程同步的(sychronized)的,这也是Vector和ArrayList 的一个的重要区别。 

    4、ArrayList

         API----Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, includingnull. In addition to implementing theList interface, this class provides methods to manipulate the size of the array that is used internally to store the list. (This class is roughly equivalent toVector, except that it is unsynchronized.)

    同Vector一样是一个基于数组上的链表,但是不同的是ArrayList不是同步的。所以在性能上要比Vector好一些,但是当运行到多线程环境中时,可需要自己在管理线程的同步问题。

    5、LinkedList

         API----Linked list implementation of the List interface. Implements all optional list operations, and permits all elements (includingnull). In addition to implementing theList interface, the LinkedList class provides uniformly named methods toget, remove andinsert an element at the beginning and end of the list. These operations allow linked lists to be used as a stack,queue, ordouble-ended queue

    LinkedList不同于前面两种List,它不是基于数组的,所以不受数组性能的限制。 
    它每一个节点(Node)都包含两方面的内容: 
    1.节点本身的数据(data); 
    2.下一个节点的信息(nextNode)。 
    所以当对LinkedList做添加,删除动作的时候就不用像基于数组的ArrayList一样,必须进行大量的数据移动。只要更改nextNode的相关信息就可以实现了,这是LinkedList的优势。

    List总结:

    • 所有的List中只能容纳单个不同类型的对象组成的表,而不是Key-Value键值对。例如:[ tom,1,c ]
    • 所有的List中可以有相同的元素,例如Vector中可以有 [ tom,koo,too,koo ]
    • 所有的List中可以有null元素,例如[ tom,null,1 ]
         基于Array的List(Vector,ArrayList)适合查询,而LinkedList 适合添加,删除操作

    6、Set(接口)

         API-----A collection that contains no duplicate elements. More formally, sets contain no pair of elementse1 ande2 such that e1.equals(e2), and at most one null element. As implied by its name, this interface models the mathematicalset abstraction. 
    Set是不包含重复元素的Collection

    7、HashSet

       API-----This class implements theSet interface, backed by a hash table (actually aHashMap instance). It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time. This class permits thenull element. 

    虽然Set同List都实现了Collection接口,但是他们的实现方式却大不一样。List基本上都是以Array为基础。但是Set则是在 HashMap的基础上来实现的,这个就是Set和List的根本区别。HashSet的存储方式是把HashMap中的Key作为Set的对应存储项。看看 HashSet的add(Object obj)方法的实现就可以一目了然了。

    8、LinkedHashSet

        API----Linked list implementation of the List interface. Implements all optional list operations, and permits all elements (includingnull). In addition to implementing theList interface, the LinkedList class provides uniformly named methods toget, remove andinsert an element at the beginning and end of the list. These operations allow linked lists to be used as a stack,queue, ordouble-ended queue
    HashSet的一个子类,一个链表。

    9、SortedSet

       API---ASet that further provides atotal ordering on its elements. The elements are ordered using theirnatural ordering, or by aComparator typically provided at sorted set creation time. The set's iterator will traverse the set in ascending element order. Several additional operations are provided to take advantage of the ordering. (This interface is the set analogue ofSortedMap.)  

    有序的Set,通过SortedMap来实现的。

    Set总结:

    (1)Set实现的基础是Map(HashMap)(2)Set中的元素是不能重复的,如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象

    -------------Map-----------------

    Map 是一种把键对象和值对象进行关联的容器,而一个值对象又可以是一个Map,依次类推,这样就可形成一个多级映射。对于键对象来说,像Set一样,一个 Map容器中的键对象不允许重复,这是为了保持查找结果的一致性;如果有两个键对象一样,那你想得到那个键对象所对应的值对象时就有问题了,可能你得到的并不是你想的那个值对象,结果会造成混乱,所以键的唯一性很重要,也是符合集合的性质的。当然在使用过程中,某个键所对应的值对象可能会发生变化,这时会按照最后一次修改的值对象与键对应。对于值对象则没有唯一性的要求,你可以将任意多个键都映射到一个值对象上,这不会发生任何问题(不过对你的使用却可能会造成不便,你不知道你得到的到底是那一个键所对应的值对象)。

    1、HashMap

       API----Hash table based implementation of theMap interface. This implementation provides all of the optional map operations, and permitsnull values and the null key. (The HashMap class is roughly equivalent toHashtable, except that it is unsynchronized and permits nulls.) This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.  

    2、TreeMap

       API----A Red-Black tree basedNavigableMap implementation. The map is sorted according to thenatural ordering of its keys, or by aComparator provided at map creation time, depending on which constructor is used. 
    TreeMap则是对键按序存放,因此它便有一些扩展的方法,比如firstKey(),lastKey()等,你还可以从TreeMap中指定一个范围以取得其子Map。 
    键和值的关联很简单,用put(Object key,Object value)方法即可将一个键与一个值对象相关联。用get(Object key)可得到与此key对象所对应的值对象。 

    ------------说明-----------

    一、几个常用类的区别 
    1.ArrayList: 元素单个,效率高,多用于查询 
    2.Vector: 元素单个,线程安全,多用于查询 
    3.LinkedList:元素单个,多用于插入和删除 
    4.HashMap: 元素成对,元素可为空 
    5.HashTable: 元素成对,线程安全,元素不可为空 
    二、Vector、ArrayList和LinkedList 
    大多数情况下,从性能上来说ArrayList最好,但是当集合内的元素需要频繁插入、删除时LinkedList会有比较好的表现,但是它们三个性能都比不上数组,另外Vector是线程同步的。所以: 
    如果能用数组的时候(元素类型固定,数组长度固定),请尽量使用数组来代替List; 
    如果没有频繁的删除插入操作,又不用考虑多线程问题,优先选择ArrayList; 
    如果在多线程条件下使用,可以考虑Vector; 
    如果需要频繁地删除插入,LinkedList就有了用武之地; 
    如果你什么都不知道,用ArrayList没错。 
    三、Collections和Arrays 
    在 Java集合类框架里有两个类叫做Collections(注意,不是Collection!)和Arrays,这是JCF里面功能强大的工具,但初学者往往会忽视。按JCF文档的说法,这两个类提供了封装器实现(Wrapper Implementations)、数据结构算法和数组相关的应用。 
    想必大家不会忘记上面谈到的“折半查找”、“排序”等经典算法吧,Collections类提供了丰富的静态方法帮助我们轻松完成这些在数据结构课上烦人的工作: 
    binarySearch:折半查找。 
    sort:排序,这里是一种类似于快速排序的方法,效率仍然是O(n * log n),但却是一种稳定的排序方法。 
    reverse:将线性表进行逆序操作,这个可是从前数据结构的经典考题哦! 
    rotate:以某个元素为轴心将线性表“旋转”。 
    swap:交换一个线性表中两个元素的位置。 
    …… 
    Collections还有一个重要功能就是“封装器”(Wrapper),它提供了一些方法可以把一个集合转换成一个特殊的集合,如下: 
    unmodifiableXXX:转换成只读集合,这里XXX代表六种基本集合接口:Collection、List、Map、Set、SortedMap和SortedSet。如果你对只读集合进行插入删除操作,将会抛出UnsupportedOperationException异常。 
    synchronizedXXX:转换成同步集合。 
    singleton:创建一个仅有一个元素的集合,这里singleton生成的是单元素Set, 
    singletonList和singletonMap分别生成单元素的List和Map。 
    空集:由Collections的静态属性EMPTY_SET、EMPTY_LIST和EMPTY_MAP表示。 


    展开全文
  • 那么,到底有哪几种基本结构呢? 1,集合:集合中的每一个数据元素都是相互独立的,这跟数学里的集合是一致的。(还记得数学里集合的三要素呢,无序性,互异性,确定性) 2,线性结构:数据之间是一对一的关系...

    今天参加一个小考试,就是考的这一题,我竟然忘得很干净,拿出来数据结构书,再看一下。

    数据结构----书上给的概念是:相互之间存在一种或多种特定关系的数据元素的集合。简单的就是:数据及数据之间的关系。

    那么,到底有哪几种基本结构呢?

    1,集合:集合中的每一个数据元素都是相互独立的,这跟数学里的集合是一致的。(还记得数学里集合的三要素呢,无序性,互异性,确定性)

    2,线性结构:数据之间是一对一的关系,我感觉就像是有一条线把数据元素穿了起来。不知道这样子理解对不对·····

    3,树形结构:数据之间存在一对多的关系。是不是像一个大家庭,我们都有一个祖宗,然后生啊生啊,就有了很多下一代,下一代又生啊生,就又有很多下下一代······

    4,图状结构或者网状结构:数据元素间是多对多的关系。这像什么呢?同学之间的关系,大家都是互相交织的感觉。怎么感觉网状结构这么纠结呢??

    第一次写博客呢?觉得总结得不自然····看来以后要常写啊!


    展开全文
  • XML文档定义分为DTD和Schema两形式,二者都是对XML语法的约束,其本质区别在于Schema本身也是一个XML文件,可以被XML解析器解析,而且可以为XML承载的数据定义类型,约束能力较之DTD更强大。 对XML的解析主要...

    分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net

    XML文档定义分为DTD和Schema两种形式,二者都是对XML语法的约束,其本质区别在于Schema本身也是一个XML文件,可以被XML解析器解析,而且可以为XML承载的数据定义类型,约束能力较之DTD更强大。

    对XML的解析主要有DOM(文档对象模型,Document Object Model)、SAX(Simple API for XML)和StAX(Java 6中引入的新的解析XML的方式,Streaming API for XML),其中DOM处理大型文件时其性能下降的非常厉害,这个问题是由DOM树结构占用的内存较多造成的,而且DOM解析方式必须在解析文件之前把整个文档装入内存,适合对XML的随机访问(典型的用空间换取时间的策略);SAX是事件驱动型的XML解析方式,它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文档开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过事件回调代码来处理XML文件,适合对XML的顺序访问;顾名思义,StAX把重点放在流上,实际上StAX与其他解析方式的本质区别就在于应用程序能够把XML作为一个事件流来处理。将XML作为一组事件来处理的想法并不新颖(SAX就是这样做的),但不同之处在于StAX允许应用程序代码把这些事件逐个拉出来,而不用提供在解析器方便时从解析器中接收事件的处理程序。

    展开全文
  • 几种常用的设计模式介绍

    万次阅读 多人点赞 2013-11-16 18:17:27
    几种常用的设计模式介绍 1.  设计模式的起源 最早提出“设计模式”概念的是建筑设计大师亚力山大Alexander。在1970年他的《建筑的永恒之道》里描述了投计模式的发现,因为它已经存在了千百年之久,而现代才被...

     

    几种常用的设计模式介绍

    1.    设计模式的起源

    最早提出“设计模式”概念的是建筑设计大师亚力山大Alexander。在1970他的《建筑的永恒之道》里描述了投计模式的发现,因为它已经存在了千百年之久,而现代才被通过大量的研究而被发现。

    在《建筑的永恒之道》里这样描述:模式是一条由三个部分组成的通用规则:它表示了一个特定环境一类问题一个解决方案之间的关系。每一个模式描述了一个不断重复发生的问题,以及该问题解决方案的核心设计

     

    在他的另一本书《建筑模式语言》中提到了现在已经定义了253种模式。比如:

    说明城市主要的结构:亚文化区的镶嵌、分散的工作点、城市的魅力、地方交通区

    住宅团组:户型混合、公共性的程度、住宅团组、联排式住宅、丘状住宅、老人天地室内环境和室外环境、阴和阳总是一气呵成

    针对住宅:夫妻的领域、儿童的领域、朝东的卧室、农家的厨房、私家的沿街露台、个人居室、起居空间的序列、多床卧室、浴室、大储藏室

    针对办公室、车间和公共建筑物:灵活办公空间、共同进餐、共同小组、宾至如归、等候场所、小会议室、半私密办公室

     

    尽管亚力山大的著作是针对建筑领域的,但他的观点实际上适用于所有的工程设计领域,其中也包括软件设计领域。“软件设计模式”,这个术语是在1990年代由Erich Gamma等人从建筑设计领域引入到计算机科学中来的。目前主要有23种。

     

    2.    软件设计模式的分类

    2.1.  创建型

    创建对象时,不再由我们直接实例化对象;而是根据特定场景,由程序来确定创建对象的方式,从而保证更大的性能、更好的架构优势。创建型模式主要有简单工厂模式(并不是23种设计模式之一)、工厂方法、抽象工厂模式单例模式、生成器模式和原型模式

    2.2.  结构型

    用于帮助将多个对象组织成更大的结构。结构型模式主要有适配器模式adapter桥接模式bridge、组合器模式component、装饰器模式decorator门面模式、亨元模式flyweight代理模式proxy

    2.3.  行为型

    用于帮助系统间各对象的通信,以及如何控制复杂系统中流程。行为型模式主要有命令模式command、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式state策略模式、模板模式和访问者模式

    3.    常见设计模式介绍

    3.1.  单例模式(singleton)

    有些时候,允许自由创建某个类的实例没有意义,还可能造成系统性能下降。如果一个类始终只能创建一个实例,则这个类被称为单例类,这种模式就被称为单例模式。

        一般建议单例模式的方法命名为:getInstance(),这个方法的返回类型肯定是单例类的类型了。getInstance方法可以有参数,这些参数可能是创建类实例所需要的参数,当然,大多数情况下是不需要的

    publicclass Singleton {

       

        publicstaticvoid main(String[] args)

        {

           //创建Singleton对象不能通过构造器,只能通过getInstance方法

           Singleton s1 = Singleton.getInstance();

           Singleton s2 = Singleton.getInstance();

           //将输出true

           System.out.println(s1 == s2);

        }

       

        //使用一个变量来缓存曾经创建的实例

        privatestatic Singleton instance;

        //将构造器使用private修饰,隐藏该构造器

        private Singleton(){

           System.out.println("Singleton被构造!");

        }

       

        //提供一个静态方法,用于返回Singleton实例

        //该方法可以加入自定义的控制,保证只产生一个Singleton对象

        publicstatic Singleton getInstance()

        {

           //如果instancenull,表明还不曾创建Singleton对象

           //如果instance不为null,则表明已经创建了Singleton对象,将不会执行该方法

           if (instance == null)

           {

               //创建一个Singleton对象,并将其缓存起来

               instance = new Singleton();

           }

           returninstance;

        }

    }

    单例模式主要有如下两个优势:

    1)      减少创建Java实例所带来的系统开销

    2)      便于系统跟踪单个Java实例的生命周期、实例状态等。

     

    3.2.  简单工厂(StaticFactory Method)

    简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

    A实例调用B实例的方法,称为A依赖于B。如果使用new关键字来创建一个B实例(硬编码耦合),然后调用B实例的方法。一旦系统需要重构:需要使用C类来代替B类时,程序不得不改写A类代码。而用工厂模式则不需要关心B对象的实现、创建过程。

    Output,接口

    publicinterface Output

    {

        //接口里定义的属性只能是常量

        intMAX_CACHE_LINE = 50;

        //接口里定义的只能是public的抽象实例方法

        void out();

        void getData(String msg);

    }

    PrinterOutput的一个实现

    //Printer类实现Output

    publicclass Printer implements Output

    {

        private String[] printData = new String[MAX_CACHE_LINE];

        //用以记录当前需打印的作业数

        privateintdataNum = 0;

        publicvoid out()

        {

           //只要还有作业,继续打印

           while(dataNum > 0)

           {

               System.out.println("打印机打印:" + printData[0]);

               //把作业队列整体前移一位,并将剩下的作业数减1

               System.arraycopy(printData , 1, printData, 0, --dataNum);

           }

        }

        publicvoid getData(String msg)

        {

           if (dataNum >= MAX_CACHE_LINE)

           {

               System.out.println("输出队列已满,添加失败");

           }

           else

           {

               //把打印数据添加到队列里,已保存数据的数量加1

               printData[dataNum++] = msg;

           }

        }

    }

    BetterPrinterOutput的一个实现

    publicclass BetterPrinter implements Output

    {

        private String[] printData = new String[MAX_CACHE_LINE * 2];

        //用以记录当前需打印的作业数

        privateintdataNum = 0;

        publicvoid out()

        {

           //只要还有作业,继续打印

           while(dataNum > 0)

           {

               System.out.println("高速打印机正在打印:" + printData[0]);

               //把作业队列整体前移一位,并将剩下的作业数减1

               System.arraycopy(printData , 1, printData, 0, --dataNum);

           }

        }

        publicvoid getData(String msg)

        {

           if (dataNum >= MAX_CACHE_LINE * 2)

           {

               System.out.println("输出队列已满,添加失败");

           }

           else

           {

               //把打印数据添加到队列里,已保存数据的数量加1

               printData[dataNum++] = msg;

           }

        }

    }

    OutputFactory,简单工厂类

        public Output getPrinterOutput(String type) {

           if (type.equalsIgnoreCase("better")) {

               returnnew BetterPrinter();

           } else {

               returnnew Printer();

           }

        }

    Computer

    publicclass Computer

    {

        private Output out;

     

        public Computer(Output out)

        {

           this.out = out;

        }

        //定义一个模拟获取字符串输入的方法

        publicvoid keyIn(String msg)

        {

           out.getData(msg);

        }

        //定义一个模拟打印的方法

        publicvoid print()

        {

           out.out();

        }

        publicstaticvoid main(String[] args)

        {

           //创建OutputFactory

           OutputFactory of = new OutputFactory();

           //Output对象传入,创建Computer对象

           Computer c = new Computer(of.getPrinterOutput("normal"));

           c.keyIn("建筑永恒之道");

           c.keyIn("建筑模式语言");

           c.print();

          

     

           c = new Computer(of.getPrinterOutput("better"));

           c.keyIn("建筑永恒之道");

           c.keyIn("建筑模式语言");

           c.print();

        }

     

    使用简单工厂模式的优势:让对象的调用者和对象创建过程分离,当对象调用者需要对象时,直接向工厂请求即可。从而避免了对象的调用者与对象的实现类以硬编码方式耦合,以提高系统的可维护性、可扩展性。工厂模式也有一个小小的缺陷:当产品修改时,工厂类也要做相应的修改。

    3.3.  工厂方法(Factory Method)和抽象工厂(Abstract Factory)

    如果我们不想在工厂类中进行逻辑判断,程序可以为不同产品类提供不同的工厂,不同的工厂类和产不同的产品。

    当使用工厂方法设计模式时,对象调用者需要与具体的工厂类耦合,如:

    //工厂类的定义1

    publicclass BetterPrinterFactory

        implements OutputFactory

    {

        public Output getOutput()

        {

           //该工厂只负责产生BetterPrinter对象

           returnnew BetterPrinter();

        }

    }

    //工厂类的定义2

    publicclass PrinterFactory

        implements OutputFactory

    {

        public Output getOutput()

        {

           //该工厂只负责产生Printer对象

           returnnew Printer();

        }

    }

    //工厂类的调用

    //OutputFactory of = new BetterPrinterFactory();

    OutputFactory of = new PrinterFactory();

    Computer c = new Computer(of.getOutput());

     

    使用简单工厂类,需要在工厂类里做逻辑判断。而工厂类虽然不用在工厂类做判断。但是带来了另一种耦合:客户端代码与不同的工厂类耦合。

     

    为了解决客户端代码与不同工厂类耦合的问题。在工厂类的基础上再增加一个工厂类,该工厂类不制造具体的被调用对象,而是制造不同工厂对象。如:

    //抽象工厂类的定义,在工厂类的基础上再建一个工厂类

    publicclass OutputFactoryFactory

    {

        //仅定义一个方法用于返回输出设备。

        publicstatic OutputFactory getOutputFactory(

           String type)

        {

           if (type.equalsIgnoreCase("better"))

           {

               returnnew BetterPrinterFactory();

           }

           else

           {

               returnnew PrinterFactory();

           }

        }

    }

     

    //抽象工厂类的调用

    OutputFactory of = OutputFactoryFactory.getOutputFactory("better");

    Computer c = new Computer(of.getOutput());

     

    3.4.  代理模式(Proxy)

    代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象时,客户端实际上不关心是否准确得到该对象,它只要一个能提供该功能的对象即可,此时我们就可返回该对象的代理(Proxy)。

    代理就是一个Java对象代表另一个Java对象来采取行动。如:

    publicclass ImageProxy implements Image

    {

        //组合一个image实例,作为被代理的对象

        private Image image;

        //使用抽象实体来初始化代理对象

        public ImageProxy(Image image)

        {

           this.image = image;

        }

        /**

         * 重写Image接口的show()方法

         * 该方法用于控制对被代理对象的访问,

         * 并根据需要负责创建和删除被代理对象

         */

        publicvoid show()

        {

           //只有当真正需要调用imageshow方法时才创建被代理对象

           if (image == null)

           {

               image = new BigImage();

           }

           image.show();

        }

    }

    调用时,先不创建:

    Image image = new ImageProxy(null);

     

    Hibernate默认启用延迟加载,当系统加载A实体时,A实体关联的B实体并未被加载出来,A实体所关联的B实体全部是代理对象——只有等到A实体真正需要访问B实体时,系统才会去数据库里抓取B实体所对应的记录。

    借助于Java提供的ProxyInvocationHandler,可以实现在运行时生成动态代理的功能,而动态代理对象就可以作为目标对象使用,而且增强了目标对象的功能。如:

    Panther

    publicinterface Panther

    {

        //info方法声明

        publicvoid info();

        //run方法声明

        publicvoid run();

    }

    GunPanther

    publicclass GunPanther implements Panther

    {

        //info方法实现,仅仅打印一个字符串

        publicvoid info()

        {

           System.out.println("我是一只猎豹!");

        }

        //run方法实现,仅仅打印一个字符串

        publicvoid run()

        {

           System.out.println("我奔跑迅速");

        }

    }

    MyProxyFactory,创建代理对象

    publicclass MyProxyFactory

    {

        //为指定target生成动态代理对象

        publicstatic Object getProxy(Object target)

           throws Exception

        {

           //创建一个MyInvokationHandler对象

           MyInvokationHandler handler =

               new MyInvokationHandler();

           //MyInvokationHandler设置target对象

           handler.setTarget(target);

           //创建、并返回一个动态代理

           return Proxy.newProxyInstance(target.getClass().getClassLoader()

               , target.getClass().getInterfaces(), handler);

        }

    }

    MyInvokationHandler,增强代理的功能

    publicclass MyInvokationHandler implements InvocationHandler

    {

        //需要被代理的对象

        private Object target;

        publicvoid setTarget(Object target)

        {

           this.target = target;

        }

        //执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法

        public Object invoke(Object proxy, Method method, Object[] args)

           throws Exception

        {

           TxUtil tx = new TxUtil();

           //执行TxUtil对象中的beginTx

           tx.beginTx();

           //target作为主调来执行method方法

           Object result = method.invoke(target , args);

           //执行TxUtil对象中的endTx

           tx.endTx();

           return result;

        }

    }

    TxUtil

    publicclass TxUtil

    {

        //第一个拦截器方法:模拟事务开始

        publicvoid beginTx()

        {

           System.out.println("=====模拟开始事务=====");

        }

        //第二个拦截器方法:模拟事务结束

        publicvoid endTx()

        {

           System.out.println("=====模拟结束事务=====");

        }

    }

    测试

        publicstaticvoid main(String[] args)

           throws Exception

        {

           //创建一个原始的GunDog对象,作为target

           Panther target = new GunPanther();

           //以指定的target来创建动态代理

           Panther panther = (Panther)MyProxyFactory.getProxy(target);

           //调用代理对象的info()run()方法

           panther.info();

           panther.run();

        }

    Spring所创建的AOP代理就是这种动态代理。但是Spring AOP更灵活。

    3.5.  命令模式(Command)

    某个方法需要完成某一个功能,完成这个功能的大部分步骤已经确定了,但可能有少量具体步骤无法确定,必须等到执行该方法时才可以确定。(在某些编程语言如RubyPerl里,允许传入一个代码块作为参数。但Jara暂时还不支持代码块作为参数)。在Java中,传入该方法的是一个对象,该对象通常是某个接口的匿名实现类的实例,该接口通常被称为命令接口,这种设计方式也被称为命令模式。

    如:

    Command

    publicinterface Command

    {

        //接口里定义的process方法用于封装处理行为

        void process(int[] target);

    }

    ProcessArray

    publicclass ProcessArray

    {

        //定义一个each()方法,用于处理数组,

        publicvoid each(int[] target , Command cmd)

        {

           cmd.process(target);

        }

    }

    TestCommand

    publicclass TestCommand

    {

        publicstaticvoid main(String[] args)

        {

           ProcessArray pa = new ProcessArray();

           int[] target = {3, -4, 6, 4};

           //第一次处理数组,具体处理行为取决于Command对象

           pa.each(target , new Command()

           {

               //重写process()方法,决定具体的处理行为

               publicvoid process(int[] target)

               {

                  for (int tmp : target )

                  {

                      System.out.println("迭代输出目标数组的元素:" + tmp);

                  }

               }

           });

           System.out.println("------------------");

           //第二次处理数组,具体处理行为取决于Command对象

           pa.each(target , new Command()

           {

               //重写process方法,决定具体的处理行为

               publicvoid process(int[] target)

               {

                  int sum = 0;

                  for (int tmp : target )

                  {

                      sum += tmp;         

                  }

                  System.out.println("数组元素的总和是:" + sum);

               }

           });

        }

    }

     

    HibernateTemplate使用了executeXxx()方法弥补了HibernateTemplate的不足,该方法需要接受一个HibernateCallback接口,该接口的代码如下:

    public interface HibernateCallback

    {

           Object doInHibernate(Session session);

    }

     

    3.6.  策略模式(Strategy)

    策略模式用于封装系列的算法,这些算法通常被封装在一个被称为Context的类中,客户端程序可以自由选择其中一种算法,或让Context为客户端选择一种最佳算法——使用策略模式的优势是为了支持算法的自由切换。

    DiscountStrategy,折扣方法接口

    publicinterface DiscountStrategy

    {

        //定义一个用于计算打折价的方法

        double getDiscount(double originPrice);

    }

    OldDiscount,旧书打折算法

    publicclass OldDiscount implements DiscountStrategy {

        // 重写getDiscount()方法,提供旧书打折算法

        publicdouble getDiscount(double originPrice) {

           System.out.println("使用旧书折扣...");

           return originPrice * 0.7;

        }

    }

    VipDiscountVIP打折算法

    //实现DiscountStrategy接口,实现对VIP打折的算法

    publicclass VipDiscount implements DiscountStrategy {

        // 重写getDiscount()方法,提供VIP打折算法

        publicdouble getDiscount(double originPrice) {

           System.out.println("使用VIP折扣...");

           return originPrice * 0.5;

        }

    }

    策略定义

    publicclass DiscountContext

    {

        //组合一个DiscountStrategy对象

        private DiscountStrategy strategy;

        //构造器,传入一个DiscountStrategy对象

        public DiscountContext(DiscountStrategy strategy)

        {

           this.strategy  = strategy;

        }

        //根据实际所使用的DiscountStrategy对象得到折扣价

        publicdouble getDiscountPrice(double price)

        {

           //如果strategynull,系统自动选择OldDiscount

           if (strategy == null)

           {

               strategy = new OldDiscount();

           }

           returnthis.strategy.getDiscount(price);

        }

        //提供切换算法的方法

        publicvoid setDiscount(DiscountStrategy strategy)

        {

           this.strategy = strategy;

        }

    }

    测试

        publicstaticvoid main(String[] args)

        {

           //客户端没有选择打折策略类

           DiscountContext dc = new DiscountContext(null);

           double price1 = 79;

           //使用默认的打折策略

           System.out.println("79元的书默认打折后的价格是:"

               + dc.getDiscountPrice(price1));

           //客户端选择合适的VIP打折策略

           dc.setDiscount(new VipDiscount());

           double price2 = 89;

           //使用VIP打折得到打折价格

           System.out.println("89元的书对VIP用户的价格是:"

               + dc.getDiscountPrice(price2));

        }

    使用策略模式可以让客户端代码在不同的打折策略之间切换,但也有一个小小的遗憾:客户端代码需要和不同的策略耦合。为了弥补这个不足,我们可以考虑使用配置文件来指定DiscountContext使用哪种打折策略——这就彻底分离客户端代码和具体打折策略类。

    3.7.  门面模式(Facade)

    随着系统的不断改进和开发,它们会变得越来越复杂,系统会生成大量的类,这使得程序流程更难被理解。门面模式可为这些类提供一个简化的接口,从而简化访问这些类的复杂性。

           门面模式(Facade)也被称为正面模式、外观模式,这种模式用于将一组复杂的类包装到一个简单的外部接口中。

     

    原来的方式

           // 依次创建三个部门实例

           Payment pay = new PaymentImpl();

           Cook cook = new CookImpl();

           Waiter waiter = new WaiterImpl();

           // 依次调用三个部门实例的方法来实现用餐功能

           String food = pay.pay();

           food = cook.cook(food);

           waiter.serve(food);

    门面模式

    publicclass Facade {

        // 定义被Facade封装的三个部门

        Payment pay;

        Cook cook;

        Waiter waiter;

     

        // 构造器

        public Facade() {

           this.pay = new PaymentImpl();

           this.cook = new CookImpl();

           this.waiter = new WaiterImpl();

        }

     

        publicvoid serveFood() {

           // 依次调用三个部门的方法,封装成一个serveFood()方法

           String food = pay.pay();

           food = cook.cook(food);

           waiter.serve(food);

        }

    }

    门面模式调用

           Facade f = new Facade();

           f.serveFood();

    3.8.  桥接模式(Bridge)

    由于实际的需要,某个类具有两个以上的维度变化,如果只是使用继承将无法实现这种需要,或者使得设计变得相当臃肿。而桥接模式的做法是把变化部分抽象出来,使变化部分与主类分离开来,从而将多个的变化彻底分离。最后提供一个管理类来组合不同维度上的变化,通过这种组合来满足业务的需要。

    Peppery口味风格接口:

    publicinterface Peppery

    {

        String style();

    }

    口味之一

    publicclass PepperySytle implements Peppery

    {

        //实现"辣味"风格的方法

        public String style()

        {

           return"辣味很重,很过瘾...";

        }

    }

    口味之二

    publicclass PlainStyle implements Peppery

    {

        //实现"不辣"风格的方法

        public String style()

        {

           return"味道清淡,很养胃...";

        }

    }

    口味的桥梁

    publicabstractclass AbstractNoodle

    {

        //组合一个Peppery变量,用于将该维度的变化独立出来

        protected Peppery style;

        //每份Noodle必须组合一个Peppery对象

        public AbstractNoodle(Peppery style)

        {

           this.style = style;

        }

        publicabstractvoid eat();

    }

    材料之一,继承口味

    publicclass PorkyNoodle extends AbstractNoodle

    {

        public PorkyNoodle(Peppery style)

        {

           super(style);

        }

        //实现eat()抽象方法

        publicvoid eat()

        {

           System.out.println("这是一碗稍嫌油腻的猪肉面条。"

               + super.style.style());

        }

    }

    材料之二,继承口味

    publicclass BeefMoodle extends AbstractNoodle

    {

        public BeefMoodle(Peppery style)

        {

           super(style);

        }

        //实现eat()抽象方法

        publicvoid eat()

        {

           System.out.println("这是一碗美味的牛肉面条。"

               + super.style.style());

        }

    }

    主程序

    publicclass Test

    {

        publicstaticvoid main(String[] args)

        {

           //下面将得到辣味的牛肉面

           AbstractNoodle noodle1 = new BeefMoodle(

               new PepperySytle());

           noodle1.eat();

           //下面将得到不辣的牛肉面

           AbstractNoodle noodle2 = new BeefMoodle(

               new PlainStyle());

           noodle2.eat();

           //下面将得到辣味的猪肉面

           AbstractNoodle noodle3 = new PorkyNoodle(

               new PepperySytle());

           noodle3.eat();

           //下面将得到不辣的猪肉面

           AbstractNoodle noodle4 = new PorkyNoodle(

               new PlainStyle());

           noodle4.eat();

        }

    }

    Java EE应用中常见的DAO模式正是桥接模式的应用。

    实际上,一个设计优良的项目,本身就是设计模式最好的教科书,例如Spring框架,当你深入阅读其源代码时,你会发现这个框架处处充满了设计模式的应用场景。

    http://www.cnblogs.com/liuling/archive/2013/04/20/observer.html

    3.9.  观察者模式(Observer)

     观察者模式结构中包括四种角色:

      一、主题:主题是一个接口,该接口规定了具体主题需要实现的方法,比如添加、删除观察者以及通知观察者更新数据的方法。

      二、观察者:观察者也是一个接口,该接口规定了具体观察者用来更新数据的方法。

      三、具体主题:具体主题是一个实现主题接口的类,该类包含了会经常发生变化的数据。而且还有一个集合,该集合存放的是观察者的引用。

      四:具体观察者:具体观察者是实现了观察者接口的一个类。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,让自己成为它的观察者,或者让这个具体主题将自己从具体主题的集合中删除,使自己不在时它的观察者。

     

    观察者模式定义了对象间的一对多依赖关系,让一个或多个观察者对象观察一个主题对象。当主题对象的状态发生变化时,系统能通知所有的依赖于此对象的观察者对象,从而使得观察者对象能够自动更新。

    在观察者模式中,被观察的对象常常也被称为目标或主题(Subject),依赖的对象被称为观察者(Observer)。

    Observer观察者接口:

    观察者:观察者也是一个接口,该接口规定了具体观察者用来更新数据的方法

    publicinterface Observer {

        void update(Observable o, Object arg);

    }

    Observable目标或主题:

    主题:主题是一个接口,该接口规定了具体主题需要实现的方法,比如添加、删除观察者以及通知观察者更新数据的方法

    import java.util.ArrayList;

    import java.util.List;

    import java.util.Iterator;

     

    publicabstractclass Observable {

        // 用一个List来保存该对象上所有绑定的事件监听器

        List<Observer> observers = new ArrayList<Observer>();

     

        // 定义一个方法,用于从该主题上注册观察者

        publicvoid registObserver(Observer o) {

           observers.add(o);

        }

     

        // 定义一个方法,用于从该主题中删除观察者

        publicvoid removeObserver(Observer o) {

           observers.add(o);

        }

     

        // 通知该主题上注册的所有观察者

        publicvoid notifyObservers(Object value) {

           // 遍历注册到该被观察者上的所有观察者

           for (Iterator it = observers.iterator(); it.hasNext();) {

               Observer o = (Observer) it.next();

               // 显式每个观察者的update方法

               o.update(this, value);

           }

        }

    }

    Product被观察类

    具体主题:具体主题是一个实现主题接口的类,该类包含了会经常发生变化的数据。而且还有一个集合,该集合存放的是观察者的引用。

    publicclass Product extends Observable {

        // 定义两个属性

        private String name;

        privatedoubleprice;

     

        // 无参数的构造器

        public Product() {

        }

     

        public Product(String name, double price) {

           this.name = name;

           this.price = price;

        }

     

        public String getName() {

           returnname;

        }

     

        // 当程序调用namesetter方法来修改Productname属性时

        // 程序自然触发该对象上注册的所有观察者

        publicvoid setName(String name) {

           this.name = name;

           notifyObservers(name);

        }

     

        publicdouble getPrice() {

           returnprice;

        }

     

        // 当程序调用pricesetter方法来修改Productprice属性时

        // 程序自然触发该对象上注册的所有观察者

        publicvoid setPrice(double price) {

           this.price = price;

           notifyObservers(price);

        }

    }

     

    具体观察者:具体观察者是实现了观察者接口的一个类。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,让自己成为它的观察者,或者让这个具体主题将自己从具体主题的集合中删除,使自己不在时它的观察者。

     

    NameObserver名称观察者

    import javax.swing.JFrame;

    import javax.swing.JLabel;

     

    publicclass NameObserver implements Observer {

        // 实现观察者必须实现的update方法

        publicvoid update(Observable o, Object arg) {

           if (arg instanceof String) {

               // 产品名称改变值在name

               String name = (String) arg;

               // 启动一个JFrame窗口来显示被观察对象的状态改变

               JFrame f = new JFrame("观察者");

               JLabel l = new JLabel("名称改变为:" + name);

               f.add(l);

               f.pack();

               f.setVisible(true);

               System.out.println("名称观察者:" + o + "物品名称已经改变为: " + name);

           }

        }

    }

    PriceObserver价格观察者:

    publicclass PriceObserver implements Observer {

        // 实现观察者必须实现的update方法

        publicvoid update(Observable o, Object arg) {

           if (arg instanceof Double) {

               System.out.println("价格观察者:" + o + "物品价格已经改变为: " + arg);

           }

        }

    }

    测试:

    publicclass Test {

        publicstaticvoid main(String[] args) {

           // 创建一个被观察者对象

           Product p = new Product("电视机", 176);

           // 创建两个观察者对象

           NameObserver no = new NameObserver();

           PriceObserver po = new PriceObserver();

           // 向被观察对象上注册两个观察者对象

           p.registObserver(no);

           p.registObserver(po);

           // 程序调用setter方法来改变Productnameprice属性

           p.setName("书桌");

           p.setPrice(345f);

        }

    }

     

    其中Java工具类提供了被观察者抽象基类:java.util.Observable。观察者接口:java.util.Observer

     

    我们可以把观察者接口理解成事件监听接口,而被观察者对象也可当成事件源处理——换个角度来思考:监听,观察,这两个词语之间有本质的区别吗?Java事件机制的底层实现,本身就是通过观察者模式来实现的。除此之外,主题/订阅模式下的JMS本身就是观察者模式的应用。

     

     

    展开全文
  • 常见的数据库有哪几种

    千次阅读 2020-06-01 10:58:29
    SQL(StructuredQueryLanguage,结构化查询语言)是一数据库查询语言和程序设计语言,主要用于管理数据库中的数据,如存取数据、查询数据、更新数据等。 SQL是IBM公司于1975—1979年之间开发出来的,在20世纪随着...
  • Java 中几种常用设计模式

    万次阅读 多人点赞 2018-08-09 16:50:32
    Java 中一般认为23种设计模式,当然暂时不需要所有的都会,但是其中常见的几种设计模式应该去掌握。 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、...
  • C语言的四种程序结构

    万次阅读 多人点赞 2018-01-02 12:13:59
    顺序结构程序设计是最简单的,只要按照解决问题的顺序写出相应的语句就行,它的执行顺序是自上而下,依次执行。例如;a = 3,b = 5,现交换a,b的值,这个问题就好像交换两个杯子水,这当然要用到第三个杯子,假如...
  • SQL优化常用几种方法

    万次阅读 2020-06-29 14:42:42
    在使用JPA时常常出现业务复杂不方便使用名称解析的情况,这时可采用原生SQL来实现,SQL在请求并发数量较多时效率会影响系统的整体效率,在此记录一下sql优化的常用几种方法。 二、优化方法 1、对查询进行优化,...
  •  直到20世纪80年代,一 些机器翻译系统采用了两方法:在这些方法中,源语言文本被分析转换成抽象表达形式,随后利用一些程序,通过识别词结构(词法分析)和句子结构(句法分析)解决歧义问...
  • java中几种常用的设计模式

    万次阅读 2015-11-30 13:07:13
    java中常用几种设计模式: 创建型:简单工厂模式(并不是23种设计模式之一)、工厂方法、抽象工厂模式、单例模式、生成器模式和原型模式结构型:适配器模式adapter、桥接模式bridge、组合器模式component、装饰...
  • 常用几种数据库介绍

    千次阅读 2015-12-12 18:47:54
    常用几种数据库介绍 1.Oracle数据库 是甲骨文公司的一款关系数据库管理系统。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好(最大的好处就是其跨平台的特点,如linux和Windows)...
  • 几种Java常用的通信协议比较

    万次阅读 2017-05-05 11:40:38
    几种Java常用的通信协议比较 本文比较了RMI,Hessian,Burlap,Httpinvoker,Web service等5种通讯协议的在不同的数据结构和不同数据量时的传输性能。   1. 简介 RMI是java语言本身提供的远程通讯协议...
  • Unity几种常用的设计模式

    万次阅读 多人点赞 2018-01-04 04:43:05
    1、单例模式:某个类只能一个实例,单例非常重要,比如我需要管理游戏的UI,现在我要关闭某个页面,页面上可能打开很多子窗口也需要一起关闭,这时候用一个单例来统一管理就很好解决这个问题。单例模式一般都是...
  • 作为助力企业经营决策的大数据可视化应用,对于的企业发展起着至关重要的作用,但是如何利用大数据可视化,如何做好大数据可视化,今天小编就给大家介绍款实用的工具,帮助大家在大数据的海洋里开发出一片宝藏。...
  • 常用几种java集合类总结

    万次阅读 多人点赞 2018-08-09 18:13:16
    一:直观框架图 简单版: ...Collection接口又3种子类型,List、Set和Queue,再下面是一些抽象类,最后是具体实现类,常用ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedH...
  • 常用几种大数据架构剖析

    万次阅读 多人点赞 2018-08-31 17:11:32
    随着大数据技术的发展,数据挖掘、数据探索等专有名词曝光度越来越高,但是在类似于Hadoop系列的大数据分析系统大行其道之前,数据分析工作已经经历了长足的发展,尤其是以BI系统为主的数据分析,已经了非常成熟和...
  • 它们还被用于巨量数据的自动化和应用程序提取非结构化数据。 这些技术的服务提供商和供应商Basis Technology, Coveo, Expert System, Indico, Knime, Lexalytics, Linguamatics, Mindbreeze, Sinequa, Stratifyd...
  • 汇编语言程序结构

    千次阅读 2019-10-23 17:47:15
    顺序结构程序是最简单的也是最基本的一种程序结构形式。这种结构的程序程序的开头顺序的执行直到程序结束为止,执行过程中没有任何分支。 例:用查表的方法将一位十六进制数转换为与它相应的ASCII码 DATA ...
  • 程序设计的最基本的三种结构

    千次阅读 2018-12-29 20:31:34
    这三种结构就被称为程序设计的三基本结构,也是结构程序设计必须采用的结构。 Java语言的方法体内同样是这三种结构组成的,换句话说,虽然Java是面向对象的,但Java的方法里则是 一种结构化的程序流。 ...
  • 几种常用数据库连接池的使用

    万次阅读 多人点赞 2019-02-14 12:38:38
    一、应用程序直接获取数据库连接的缺点  用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,... 数据库连接是一关键的有限的昂...
  • 介绍几种常用的监控工具

    万次阅读 2019-06-12 22:24:22
    将数据发送到Zipkin的仪器化应用程序中的组件称为Reporter,Reporter通过几种传输方式之一将追踪数据发送到Zipkin收集器(collector), 然后将跟踪数据进行存储(storage),由API查询存储以向UI提供数据。 架构图如下...
  • 都能对当前正在开发中的系统整体的认知,从而更好的熟悉和学习技术,这篇文章胖达就打算给大家介绍几款现阶段流行的框架组合,不管是在传统企业开发还是在互联网开发领域,这几种框架应该都是比较常用的。...
  • sql优化的几种方式

    万次阅读 多人点赞 2018-11-05 10:20:46
    我们开发项目上线初期,由于业务数据量相对较少,一些SQL的执行效率对程序运行效率的影响不太明显,而开发和运维人员也无法判断SQL对程序的运行效率多大,故很少针对SQL进行专门的优化,而随着时间的积累,业务...
  • UML常用图的几种关系的总结

    万次阅读 多人点赞 2012-09-24 01:28:41
    类图中,常见的以下几种关系: 泛化(Generalization), 实现(Realization), 关联(Association), 聚合(Aggregation), 组合(Composition), 依赖(Dependency) 1. 泛化(Generalization) 【泛化...
  • 几种常用开发语言的对比

    万次阅读 2018-07-17 22:17:16
    一直各种编程语言,开发工具拎不清的问题,所以趁有空做了一个小整理。 编程语言 javascript,c#,python,Ruby,PHP,Java,swift,basic 前端框架 vue.js,angular 2,bootstrap,less/sass,ember.js ...
  • 关于Android架构,因为手机的限制,目前我觉得也确实没什么大谈特谈的,但是从开发的角度,看到整齐的代码...本文先分析个当今比较流行的android软件包,最后我们汲取其中觉得优秀的部分,搭建我们自己的通用an

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 438,125
精华内容 175,250
关键字:

常用的程序结构有哪几种