为您推荐:
精华内容
最热下载
问答
  • 5星
    2KB qq_26403571 2021-06-06 18:18:34
  • 5星
    372.74MB dhyuan_88 2021-07-13 14:53:45
  • 5星
    14.06MB guoruibin123 2021-06-29 14:32:12
  • 5星
    21.17MB qc_id_01 2021-07-29 12:05:14
  • 5星
    206.62MB u013729183 2021-08-14 08:53:28
  • 5星
    48.61MB goodxianping 2021-09-23 09:41:55
  • 5星
    8.51MB GZXGYZ 2021-08-16 10:12:36
  • 5星
    353KB qq_41934573 2021-06-24 22:06:26
  • 5星
    372.8MB dhy1688 2021-06-28 23:09:16
  • 5星
    260.32MB dhyuan_88 2021-06-14 20:44:45
  • 第六步:做大数据项目和产品一定要挖掘和实现大数据能给我们带来的特殊价值,这是其它的方法或者是其它的数据做不到的,只有实现了这种特殊的价值,我们才能实现业务所需要的具体功能,不管是扩展市场的份额,...

    1.大数据落地的难处

    首先,难在大数据技术端和市场应用端的信息不对称。大数据技术端可能存储着海量的数据,可能掌握着先进的计算和分析挖掘技术,但是并不了解市场的需求痛点,或者无从发力,或者闭门造车。而市场应用端的专业人士则因为对大数据的工作原理和蕴含的高价值缺乏了解而空守金山不自知。解决这个困局的方法有二:一是从两端入手,大数据行业内人士必须深入到传统行业的业务流程中去学习、经历或体验;而传统行业的业内人士则要开放心态,主动学习和拥抱新事物。二是从中间入手,招聘寻找兼具一定大数据知识和传统企业行业知识的人才,作为沟通桥梁弥合两端的裂隙。

    其次,难在数据互联的成熟度。当前的大数据源虽然貌似纷繁多样,电信数据、银联数据、房产车辆数据、wifi数据、企业内部数据、网购数据、互联网数据等等都能获取到,但是数据源之间缺乏有效的关联,导致大数据对于分析目标无法进行全面的描摹和了解,因此大大限制了应用范围。眼下市场上虽然一夜之间冒出了各式的“数据交易所”,但是仍然不能有效解决数据互联的问题。数据源之间的相互信任与和合作是一个难点,数据信息的保密和披露法规不完善也是障碍之一,而落地变现场景的缺乏又使得这个问题的破局陷入了死循环。

    其三,难在应用者缺乏耐心和战略远见。一个企业的大数据战略布局是需要远见和时间成本的,战略远见不仅来源于核心领导层对于大数据知识的主动学习和思考,还要有敢于付出试错成本的决断力。同时,大数据项目投入的周期相对较长,前期繁复枯燥的整合内部数据孤岛、联合外部数据源的工作耗时费力而又障碍重重,如同万丈高楼的地基,虽然极为重要且时间金钱的代价不菲,却在表面上难以有显著成效可以彰显。另外,即便最终具备应用能力的大数据软件开发完成,往往也会因为受到数据源、分析技术、甚至是使用人员素质的限制使得短期内不能让企业领导者看到有亮点的投资回报率。但是,企业领导者应该认识到这是必要的学习成本,自己乃至整个企业经由这样的学习曲线获得了大数据领域的实操经验和能力,耐心而睿智的继续前行最终会令企业的竞争力在行业中脱颖而出。

    2.如何做一个成功的大数据项目

    先讲一个大数据的笑话。

    说有一个大数据分析师,他上了一架飞机,上飞机不久,广播里就传来机长的声音说,“对不起大家,我们飞机刚刚有一个引擎不工作了,但是不要着急,我们还可以用其它三个引擎飞,只是我们需要到达目的地的时间要比原来预计的晚一个小时”。又过了一会儿,机长开始播音了,对不起,我们刚才发现又有一个引擎坏了,但是没有问题,没有麻烦的,我们顶多到达目的地的时候会迟到两个小时。又过了不久,机长又说,现在有一个坏消息,现在只剩一个引擎了,但是不用担心,我们还是会安全到达目的地,只不过比原来预计的落地时间迟三个小时。然后这个大数据分析师就说,哇……,我希望不要再丢掉最后一个引擎,不然的话,我们就会永远在天上待着了。无法到达目的地就是这个意思了。

    1 失败大数据案例的特征

    根据在美国做了15年的大数据项目、产品研发和管理,以及其它一些相关的数据分析的工作经验,了解到的其它的做的比较成功的和失败的项目,跟大家做一个经验分享。基本上大数据项目失败的特征主要是五个:

    一是大数据项目与企业战略脱节,完全是领导或者是不知道那个部门的决策人突然脑子一热,就说别人在用,我们也做一个,根本没有把该做的项目和企业的商业战略、科技战略等各个方面结合起来。在项目无法与战略协调,无法在战略的指导下做一款产品或者是服务项目的时候,失败的可能性会非常大。

    二是大数据商业用例不是很明确。商业用例是说大数据项目怎么能够帮助各项业务达成所需要的功能和目标,或者叫目的,这个不是很清楚,怎么帮助我不是很清楚,这样的话,就直接影响到你选什么样的数据,怎么用这些数据,以至于用了以后怎么去支持你的业务,这一点是第二条,也是关键的。

    三是无法发掘出大数据特殊价值。如果你没有发掘出特殊价值,其实用小数据也可以做到,这个项目本身就失去了意义。

    四是企业内部对大数据项目无共识。财务部门、营销部门、研发部门之间的利益和工作重点是不一样的,没有共识就很难顺利推进一个项目,最后就很有可能是拖延或者是取消,甚至是失败,推出去了内部员工没人买单。

    五是缺乏项目所需核心技术。大数据不是谁都能玩儿得起的,如果缺乏核心技术,达不到自己的预期目标,钱也是白花的。

    2 成功大数据项目的标志

    成功很多时候跟失败是反过来的:

    一是项目用例(目标/实用价值)清晰。从上到下,大家都明白这个大数据要做什么,包括企业的财务主管和具体业务部门,比方说营销部门,这个大数据项目是用在营销部门的,他们也很清楚,负责执行的技术部门也很清楚,这个搞清楚了以后,对大家上下一心做好项目是非常重要的。

    二是项目规划完善+快速迭代研发试错稳步推进。

    一个项目规划的时候,不要做成规划三个月、六个月,你用传统的老办法去做,最后发现实际上第一阶段结束了以后,你去做测试完全没有达到你想要的效果。我们做一个大项目要用快速迭代的方法来做,每个星期可以推出一个功能,进行快速测试,内部市场、外部市场都测试成功,下一个星期就可以进行下一个功能的研发、扩展、推广。这样的话,可以通过迅速的试错,比方说第二个星期做的方向不对,或者有些功能没有办法实现,或者跟我设计的不一样,这样的试错代价会比较低,不会等到6个月才发现有重大的错误,调整了以后第三个星期可以接着来,可以换一个方向,可以调整开发的内容,或者是功能,三个月以后,已经经过了四、五个星期的测试和研发了,基本上犯错的可能性就比较低了。

    三是所选技术符合大数据项目功能要求。

    很多人都听说过要上一个大数据项目必须要用一些特殊的技术,大数据项目最重要的不是选高大上的平台,或者是特殊的技术,最重要的是选一款符合最初设计的业务功能的技术,这个技术可能相对来说比较简单,可能是SAS软件,或者是JAVA程序,没必要上高大上的技术,最重要的是符合你的要求。很多企业选了高大上,最后发现,实际上钱花了很多,但是没有达到预期的要求,因为你选了高大上的东西以后,会影响到各个方面的整合和所需要的数据量,预算会很大,成本也会比较高,很难实现盈利的目标。所以最重要的是选一款适合你这个项目目标的技术,这个非常重要。

    四是项目团队拥有各方面专业知识技能。

    大数据技术就像企业做的任何一款创新产品和项目一样,需要雇佣所有的对这个项目有贡献的,可能会受影响的资源,可能包括人力资源,包括技术资源,包括市场资源,包括运营资源等等各个方面的资源调动,形成这么一个团队,上面有领导的支持,中间有大家的共识,最下面的一线执行人员也很清楚自己要做什么,这方面要协调好,要有专门的技术,这个很重要。

    五是项目成果获得业务用例期望成果。

    这个项目做了三个月、六个月,做出来了,是不是获得了业务用例期望的结果,是一个非常重要的标志。很多时候,很难是百分之百,一般80%的项目达不到完全预期的结果,可能是80%的预期达到了,那已经很好了,可能达到50%,也不错,因为是一个创新的项目,可以根据达到的预期项目进行不停地调整,最差的是只达到了20%,很多企业做的项目结果,这是一个统计的结果,是大家能看得见的。根据业界的标准,到了50%基本上算比较成功了,到了80%就是相当好了。

    3 成功大数据项目的衡量标准

    成功大数据的横向标准是五点:

    一是项目在预定的时间里可以实现或者接近预定的目标;

    二是这个项目或者产品实现了传统数据方法没有办法带来的特殊的内部和外部的商业价值;

    三是在有限的大数据投资的条件下,给特定的业务带来的好处可以轻松复制到其它的业务领域,比如说营销部门获得的成功会推广到产品的研发部门,或者是推广到业务运营部门,这样会花很小的代价,但是做了更多的事儿。

    四是受益的业务部门可以运用大数据工具进行高效便捷的工作,这其实是最直接了当的,因为本来我们要做一款大数据的产品,或者是服务项目就是为了提高运营效率和工作效率。

    五是通过这个项目实施企业获得了新的商业模式和成长点,这个是最重要的,从战略的角度讲,这个大数据产品和项目成功实现了企业转型和升级。

    4 成功大数据项目的路线图

    成功大数据的路线图分为六步:

    第一步:确定对企业业务有重大影响的大数据用例和创新方向。

    第二步:我们要制定基于大数据项目的详尽的产品服务创新规划。

    第三步:要详细了解大数据项目所需要的业务功能要求和选择与之相匹配的技术。

    第四步:就大数据项目带来的商业利益在企业内部达成共识。

    第五步:我们要选择容易实现的目标入手,快速迭代研发、试错、稳步推进。也就是说不要刚开始就要搞高大上、大而全的项目,因为失败的几率几乎是百分之百,非常容易失败,因为预算太大,选的工具太复杂,调动的资源很多,很难一下子实现所有的目标,所以通常我们从一个晓得目标,容易实现的目标开始,这样可以鼓励士气,错误犯在研发的初期,而不是在中期和最后,这个最重要。

    第六步:做大数据项目和产品一定要挖掘和实现大数据能给我们带来的特殊价值,这是其它的方法或者是其它类的数据做不到的,只有实现了这种特殊的价值,我们才能实现业务所需要的具体功能,不管是扩展市场的份额,或者是更精准的了解你的客户需求,还是说你要增加边际利润率,或者是提高产品上市的速度,缩短研发周期,这些都是大数据可以做的。另外就是跨界创新,传统企业可以通过大数据这个纽带跟其他企业的业务结合起来。

    5 成功大数据项目实战案例

    其实有很多精彩的实战案例,我把美国福特公司去年以来做的一个大数据项目跟大家分享一下。我在福特有一个非常熟悉的朋友,我也介入了一点点,我来讲一下,他们基本上是按照我总结的几步来做的。

    福特第一步是确定了大数据用例,销售部门很想知道我怎么用大数据这个技术来提升汽车销售业绩,这是一个非常简单的业务用例。我们需要界定的是,一切影响销售业务的大数据,一般汽车销售商的普通做法是投放广告,看看影响力怎么样,动辄就是几百万,但是具体很难分清楚到底每一个受众看了这个广告以后会不会产生购买这个汽车的冲动,这个很难看到。大数据技术不太一样,它可以通过对某个地区的房屋市场、新建住宅、库存和销售数据、这个地区的就业率等各种相关的,可能会影响购买汽车意愿的原数据进行分析和收集,还可能会到跟汽车所有相关的网站上搜索,哪一种汽车,哪一种模式,哪一种款式,客户搜索了哪些汽车的价格,车型配置、汽车功能、汽车颜色等等这些客户喜好的数据。

    福特汽车用这些方法把所有的数据都界定好了以后,第二步是把项目交给了一个差不多200人的大数据分析专业团队,他们获取和搜索所需的外部数据,比方说第三方合同网站,区域经济数据、就业数据等等。

    第三步是他们获得数据以后,就开始对数据进行建模分析、挖掘,为销售和决策部门提供精准可靠的角色选择和效果分析,也就是说,你选这个方法,可能获得的营销效果是怎么样的,他们做了大概几十种可能的分析。

    第四步是营销部门和运营部门根据这些数据策划和实施有针对性的促销计划,比方说在某些区,某些州需求量特别旺盛的地方,他们有专门的促销计划,基本上这些促销计划都是根据某一个个体的需求量身订做的,非常非常精准,所以不需要花五、六百万美金,花出去了以后不知道谁感兴趣,只需要花五、六十万美金,就知道谁对这个汽车感兴趣,这个广告就送到电子邮箱和地区的报纸上了,非常精准。

    最后一步是大数据营销的创新效果衡量,跟传统的广告促销相比,福特花了很少的钱,做了大数据分析产品,我们叫大数据的模型和分析工具,运用这种方法,大幅度的提高了汽车的销售业绩。他们不光在汽车的销售方面运用了大数据,比较成功,还有其它方面的应用,包括汽车的整车质量、保险费用、汽车运输状况、汽车的智能和驾驶模式等等,他们希望用这些数据帮助驾驶员降低保险成本,这样的话可以促进很多销售者对福特这个品牌的认可,扩大市场占有率。

    3.大数据项目落地路线总结

    第一阶段:数据规划

    一个成功的大数据项目,需要有一个良好的开端,即做好数据规划阶段的各项工作,具体包括:

    1.战略意图:在这个阶段,要明确战略意图,这个战略意图需要在相关干系部门之间达成一致和共识,换句话说就是为什么要搞这个大数据项目?

    2.战略规划:战略意图清晰以后,就可以作为贯穿整个项目过程的灯塔,接下来要需要将战略意图转变为战略规划,通过战略规划来进一步让相关干系部门和人员清晰的认识到这个大数据项目将要做什么?

    3.商业目标:战略规划完成后,就要明确这个大数据项目的商业目标,即通过这个大数据项目实施,为企业带来怎样的商业价值?是降低成本呢,还是扩大营业收入,亦或是通过创新业务为企业带来新的价值增长点?

    4.执行方针:商业目标确定以后,需要进一步来确定该大数据项目的执行方针,包括:项目执行的基本原则、利益分配原则、分歧处理原则等等。

    5.组织支撑:上述Action完成后,就需要建立对应的项目组织了,成立项目小组,明确相关岗位以及岗位职责,根据不同的战略意图、战略规划、商业目标和执行方针,建立不同架构和规模的组织。

    6.上述Action还都属于项目可以成功落地的先导性工作,那么接下来就是许多细致的具体工作,这些具体工作都是保障项目可以成功落地的基石。

    7.产品(项目)规划:协同各个干系的部门和干系人,有效的建立起来项目内容规划机制,完成产品(项目)的总体规划。

    8.场景规划:完成产品(项目)的总体规划,作为大数据项目,需要继续规划出主要的应用场景,场景规划是有效地推动后续步骤阶段的基础,场景如果规划的不清晰,直接会影响到后续的一系列Action的执行。

    9.需求评估:产品(项目)规划、场景规划完成后,需要将规划内容反复与各个干系部门和干系人进行沟通与确认,最终形成项目需求说明书,同时完成需求的评估,评估相关规划和需求是否可以满足战略意图、战略规划以及商业目标。

    上述Action完成后,需要从架构和落地角度,进一步深化:

    架构规划:根据已完成的产品(项目)规划、场景规划和需求评估,从落地的角度完成数据架构规划,架构规划是项目成功落地的重要环节。

    有的大数据项目,还需要引入第三方的数据支持,以及体系内其他非干系部门的数据支持,这样就需要进行有效合作。

    合作意图:如果项目需要引入第三方的数据支持,以及体系内其他非干系部门的数据支持,需要充分评估项目风险与合作意图,有效达成合作共识。

    第二阶段:数据治理

    第一阶段的工作完成以后,已经具备了一个大数据项目成功落地的良好基础,接下来就需要按照数据规划阶段的成果继续后续的环节,首先要做的就是要有数据,并且要有高质量的数据,数据到位才能保障项目的有效推进和执行:

    1.来源评估:在数据治理阶段,首先要进行数据来源评估,展开数据梳理相关的工作,及时发现数据来源可能存在的风险并加以处理。来源评估完成后,确认可以有效获取到所需要的对应数据来源的数据,就可以进行数据的获取工作了。

    2.数据采集:数据采集是一个很重要的工作,只有把数据采集来,才能进行一系列的大数据相关的工作。数据采集过程中,注意数据采集的有效性。

    3.数据预处理:为了更好的、更有效的存储有价值的数据,同时方便系统对数据的使用,部分数据可以做预处理。

    4.数据质量:数据质量环节很重要,如何有效保证数据的质量?直接影响着大数据项目的实施效果,在这个环节中,要投入很多的精力去形成标准,并建立相对自动化的数据质量系统。

    上述的几个环节,必要时需要借助专业的产品工具。

    数据管理:数据管理工作,将影响项目的整个周期,建议采用专业的数据管理产品和工具,或借助有开发能力的供应商量身定做一套数据管理系统。

    第三方数据:可以通过数据资产置换、购买等等方式完成第三方数据的接入

    在整个第二阶段会形成一系列的标准和流程,这里不一一赘述

    第三阶段:数据应用

    第一、第二阶段工作完成以后,就将进入最重要的第三阶段工作,在这个阶段中,我们将承前启后的推动大数据项目完成落地工作,真正去形成大数据的应用,带来真实的业务价值:

    场景细分:在这个阶段,对于第一阶段中形成的场景规划,要进行可被实现的场景细分,通过对场景的细分,形成一个个的用例(Use Case)。

    干系组织利益共识:通过场景的细分后的一个个用例(Use Case),已经可以很好的明确给各干系组织带来的业务价值,在这个时候需要推动各个干系组织形成利益共识,以免由于利益问题导致项目执行的阻碍。

    完成上述Action后,就需要借助供应商的参与和力量继续完成后续的Action。

    1.功能规划:经过上述Action环节,项目已经进入重要的落地阶段,需要根据已经整理好的用例(Use Case)、数据,形成具体的功能规划。这些功能规划,需要是可被准确识别和实现的,直接对应了大数据应用系统的功能点。

    2.技术选型:完成了功能规划,就需要进行技术选型工作,由于大数据相关的技术非常多,这项工作需要借助专业供应商的力量来一起完成,需要充分考虑非功能性指标,比如:性能要求等等。

    3.产品选型:技术选型后,需要根据选择的技术路线,来找到可供选择的、符合技术路线的产品,完成产品选型工作,如:数据科学平台等等。

    4.应用分析模型设计:大数据项目的一个重要的内容,就是要通过数据来形成各种应用分析模型,借助类似于数据科学平台类的产品,可以快速有效形成各种预测分析模型。完成这个环节的工作,需要有数据科学家、业务分析师等等一系列的角色参与相关工作。或者说引入第三方的成熟产品,如客户智能分析平台、物联网智能分析平台、运营智能分析平台等等,通过引入这些产品来直接引入成熟的分析模型。

    技术选型、产品选型以及应用分析模型建立后,就需要进行验证工作了,主要包括场景PoC和商业验证。

    PoC:选取具有典型代表意义的大数据应用场景,进行现场的PoC验证工作,通过PoC,修正和完善每个用例(Use Case),同时验证技术选型、产品选型的正确性,发现问题及时处理,甚至重新选择技术与产品。

    商业验证:PoC环节完成后,还需要进行商业验证,验证和评估一些关键场景用例(UseCase)的应用效果,评估和预测是否可以达成商业目标,从而推导出达成商业目标可能存在的问题和风险,进行修订与处理,必要调整各个干系部门和干系人之间的利益共识。

    第四阶段:迭代实施

    前三个步骤阶段的工作有效得完成后,就进入了第四步骤阶段迭代实施,之所以是迭代实施,也跟大数据类项目的特征有关,就如大数据建立分析模型是一种探索的过程一样,大数据项目的执行也需要进行不断的验证、修正、实施这样的工作,可能需要经过多轮的迭代才能完成项目的建设:

    1.模型应用:第三阶段中经过PoC和商业验证的模型,需要开发为特定的大数据分析应用才能最终为使用者所使用并发挥价值。在模型应用过程中,注意模型的规约和使用条件,注意与现有系统的融合。

    2.系统开发:系统开发工作是保证模型应用环节有效达成的手段,同时通过系统开发能力可以开发出围绕大数据分析应用的外围系统。

    3.效果评价:效果评价环节,主要是组织相关干系组织与干系人,对实施效果进行研讨和确认,同时对利益共识进行确认和达成一致,如果没有达到预期效果则继续进行迭代改进。

    4.业务验证:业务验证工作是保障大数据分析应用项目真正可以融合于业务、服务于业务的重要手段,业务验证建议从业务流程是否通畅、关键业务点是否达到预期目标、是否对业务办理产生障碍等等多方面进行。验证人员需要是使用该大数据分析应用系统的一线业务人员。

    如果上述的环节发现了重大问题,则针对问题形成改进方案后进入迭代改进环节。

    迭代改进:迭代改进分为小迭代和大迭代,小迭代是在同一期项目中完成的,受到项目上线周期的制约,小迭代可以改进的问题是有限的、小型的。对于影响范围巨大,难度较高的问题需要进入大迭代改进,大迭代一版来说可以规划为项目的二期、三期等等,直到达成预期的战略意图、战略规划和商业目标。

    经过上述的Action环节,一个成功的大数据应用项目终于落地了,这也仅仅是落地的开始,接下来的工作是检验项目成果和真正发挥大数据价值的时刻:

    实施推广:围绕项目的战略意图、规划和商业目标,进行有效的实施推广工作将变得非常重要,良好的实施推广工作可以真正让大数据应用分析项目用起来,让数据“活”起来,源源不断产生价值。推广过程,要巧妙的运用各个干系部门和干系人之间的利益共识。

    数据安全:大数据项目有自己的特点就是一切都围绕数据来展开,说到数据就会涉及到一些隐私数据、高密级数据等等,不管在开发过程中、还是在推广过程中,亦或是在第二阶段的数据治理过程中,都需要严格遵守相关信息安全和数据保密的规划,从技术上和使用上都要保证数据的安全。数据安全是一个大数据项目真正可以成功的重要内容。

    第五阶段:商业价值

    前面四个步骤阶段工作很好的完成后,就是享受大数据应用项目成果的时刻了,相信在前面四个阶段的各个环节中,各个项目参与人员都受到了或多或少的各种折磨,不过这些折磨都是值得的,因此大数据项目真正可以为企业带来不可以预想的巨大价值,只有上马了成功大数据项目的企业才能深深体会到。

    在这个阶段中,企业获得了:

    1.数据资产:企业的数据资产是大数据应用项目带来的重要成果,也是推动企业创新、产业升级、企业转型等等的财富。

    2.数据服务:通过大数据应用项目的实施,可以有效推动企业的数字化转型工作,围绕数据资产形成数据服务的能力。

    3.决策支持:通过大数据的预测分析能力,有效提升了企业的决策支持能力。

    有效获取了内部商业利益价值、外部商业利益价值,真正去实现了企业建设大数据应用项目的战略意图、战略规划和商业目标。

    对了,想要了解更多项目管理解决方案可前往CORNERSTONE。

    展开全文
    weixin_39890102 2020-12-20 12:27:26
  • 大多数供应合同都包含成本、时间和功能等要素,但为项目签发的合同需要特殊考虑。将项目管理与供应商联系在一起的合同,通常是基于...基于共同风险的合同关系意味着双方试图将额外成本降到最低,并尽其所能完成自己的

    大多数供应合同都包含成本、时间和功能等要素,但为项目签发的合同需要特殊考虑。将项目管理与供应商联系在一起的合同,通常是基于项目在预算内按时完成的共同利益。这种共同利益允许你与供应商建立积极的关系,并在关键任务未履行时给予合同制裁。

    风险

    如果项目延迟或没有按计划进行,那么它就会给负责人带来风险。如果项目管理人员不得不采取特殊措施来加快工作速度以维持完成日期,项目就会产生额外的成本。理想情况下,主要供应商和负责人分担这些成本。基于共同风险的合同关系意味着双方试图将额外成本降到最低,并尽其所能地完成自己的工作。

    责任

    虽然你可以将合同关系建立在共同风险的基础上,但各方的责任必须明确。通常合同规定,每个供应商和负责人都要对自己的供应和工作负责。合同必须明确规定,你将履行计划和协调职责,供应商将履行合同职责。

    供应

    作为项目经理,你为项目所需的商品和服务下订单。最终的合同必须详细说明承包商必须提供的材料或工作、总价格、供应的时间和材料必须具备的特性。虽然合同的其他部分影响合同关系,但供应细节规定了核心义务。

    验收

    合同是建立良好关系的基础,它规定了供应必须具备的、以便项目管理人员验收的特性。如果项目需要一定数量或重量的材料或有特殊证明的材料,合同必须明确细节。如果员工必须拥有执照或许可证,合同必须列出它们。基于这种合同的合同关系为项目管理提供了明确的基础,以便验收供应或在供应不符合合同要求的情况下拒绝验收。

    付款

    项目管理的核心义务是按照合同条款进行付款。项目主要部分的典型合同规定了进度付款,例如签订、开始生产、发货、验收和项目完成的具体百分比。良好合同关系的基础是建立付款结构,最大限度地减少供应商的融资要求,同时限制项目管理人员在供应商不履行合同时多付款项的风险。

    保修

    项目管理的一个关键部分是交付完成负责人所要求功能的项目。项目合同通常规定,主要项目组成部分的供应商必须保证其供应在特定时期满足并继续满足项目要求。积极的合同关系意味着项目管理人员可以在友好的基础上与供应商解决保修问题。

    项目管理中的供应合同管理技巧

    传统上,项目管理中的合同管理和合同谈判是使用纸张、电子邮件和无组织的计算机文件手动进行的。但是,这通常会导致交易绩效低下、业务关系不佳、运营效率低下、错失机会和利润率低。很明显,这是供应商管理协议的一种无效方式,仍然依赖手动管理的企业应该寻求投资于自动化平台,以改进其流程。

    8Manage PM等专业项目管理软件为企业提供合同自动化、可审计的单一事实来源以及项目进度和合同活动的实时视图。

    启动的合同应反映目标、进度时间表、项目预算和可用资源,这一点很重要。它们还应反映法规、规范和潜在风险。使用8Manage PM将项目的所有方面相互联系起来,在修订期间提供审计跟踪,并保证在适当的时间与适当的人员进行沟通。

    你还可以实现以下好处:

    ○ 供应商和招标管理
    ○ 改进出价分析
    ○ 采购和资源规划
    ○ 合同变更管理
    ○ 加强沟通和协作
    ○ 审计追踪和文件记录
    ○ 在预算范围内按时交付项目

    当你投资自动化解决方案时,你可以利用标准化模板、绩效跟踪和其他功能来帮助你快速完成有利于你的业务的交易。 

    展开全文
    GZ8manage 2021-11-11 11:06:04
  • Java中,(class)是用来代表对象的基本单元。对象(object)可以是现实世界中的任何一个实体,它具有若干区别于其它对象的属性和操作。而则通过为对象定义属性和操作来概括一实体。它封装了一组变量和方法,是...

    Java中,类(class)是用来代表对象的基本单元。对象(object)可以是现实世界中的任何一个实体,它具有若干区别于其它对象的属性和操作。而类则通过为对象定义属性和操作来概括一类实体。它封装了一组变量和方法,是生成实例对象时的模板。如一辆汽车可视为一个对象,它既具有型号、颜色、载重等特点,又有完成启动、行驶、刹车等功能。定义汽车类时需要将这些属性都包括进去,通常用数据变量代表型号、颜色、载重等属性特点,用成员方法来实现启动、行驶、刹车等操作功能。可以说类是对象的抽象,对象是类的实例化。

    接口(interface)可看成一个空的抽象的类,只声明了一组类的若干同名变量和方法,而不考虑方法的具体实现。Java的包(package)中包含一系列相关的类,同一个包中的类可直接互相使用,对包外的类则有一定的使用限制。Java的包近似于其它语言的函数库,可提供重用的方便。

    在下面各部分的详细介绍中,我们将先给出基本概念,然后结合具体实例阐明Java的类、接口、包以及封装、继承、重载等有关内容。

    4.1 Java的类

    4.1.1 类的声明

    Java是一种很典型的面向对象的程序设计语言。在面向对象的语言中,世界被看成独立的对象集合,相互间通过消息来通信。因而这种语言以数据对象为中心,而不以处理对象的代码为中心。Java中的类将数据和有关的操作封装在一起,描述一组具有相同类型的对象,作为构筑程序的基本单位。

    类声明定义的格式为:

    [类修饰符] class类名 [extends 父类名][implements 接口名]

    其中类修饰符用于指明类的性质,可缺省。接下来的关键字class指示定义的类的名称,类名最好是唯一的。“extends 父类名”通过指出所定义的类的父类名称来表明类间的继承关系,当缺省时意味着所定义类为Object类的子类。“implements 接口名”用来指出定义的类实现的接口名称。一个类可以同时实现多个接口。类体则包括一系列数据变量和成员方法的定义声明。下面是一些略去类体的类定义例子:

    public class WelcomeApp

    public class Welcome extends java.applet.Applet

    public Car extends Automobile implements Runable

    其中前两个类是我们在上一章的示例中定义的。第三个类是小汽车类Car,它的父类是交通工具类Automobile,它还实现了接口Runnable。

    类修饰符是用以指明类的性质的关键字。基本的类修饰符有三个:

    public,abstract和final

    ■public

    如果一个类被声明为public,那么与它不在同一个包中的类也可以通过引用它所在的包来使用这个类;否则这个类就只能被同一个包中的类使用。

    ■abstract

    如果一个类被声明为abstract,那么它是一个抽象的类,不能被实例化生成自己的对象,通常只是定义了它的子类共有的一些变量和方法供继承使用。被声明为abstract的抽象类往往包含有被声明为abstract的抽象方法,这些方法由它的非抽象子类完成实现细节。

    ■final

    如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为abstract的,又被声明为final的。

    继承是面向对象程序设计中一个强有力的工具,它允许在已存在的类的基础上创建新的类。新创建的类称为其基础类的子类,基础类称为其子类的父类。子类的对象除了具有新定义的属性和方法外,还自动具有其父类定义的部分或全部属性方法。这样程序员可以在子类中重用父类中已定义好的变量和方法,只需对子类中不同于父类或新添加的部分重新定义,这样就节省了大量的时间、空间和精力。Java在类声明中使用

    extends 父类名

    的方式定义继承关系。如果不明显地写出继承的父类名,则缺省地认为所声明的类是Java的Object类的一个子类。Object类是Java中所有的类的祖先类。我们可以把这种类继承关系想象为一棵倒置的类家族树,Object类就是这棵树的根。

    4.1.2 类的组成

    我们已经知道类是代表对象的,而每一个对象总有特定的状态和行为,在类中分别用变量数据和在数据上可进行的操作表示这些状态和行为。因此类的组成成分是变量和方法。变量和方法的声明格式如下:

    [变量修饰符] 数据类型 变量名[=初值] ;

    [方法修饰符] 返回值类型 方法名(参数表)

    其中修饰符用来指明变量和方法的特性。变量可一次定义一个或多个,定义时可以给出初值。例如:

    public int a,b=12;

    protected String s="Hot Java";

    定义方法时一定要给出返回值类型和参数表。当没有返回值时,返回值类型记为void。参数表的形式为:

    参数类型 参数值{,参数类型 参数值}

    各参数间以逗号分隔。下面是一些简单的例子:

    public static void main(String args[])

    public void paint(Graphics g)

    public int area(int length,int width){return length * width;}

    其中前两个是我们在第三章已经见过的方法声明,这里略去了具体语句组成的方法体。第三个则是一个计算长方形面积的简单方法,接受整数类型的长度和宽度参数并返回它们的乘积作为结果。

    变量和方法修饰符是用来指明特性的关键字,主要有以下几种:

    ■public

    一个类中被声明为public的变量和方法是“公开”的,意味着只要能使用这个类,就可以直接存取这个变量的数据,或直接使用这个方法。

    ■protected

    一个类中被声明为protected的变量和方法是“受限”的,意味着它们仅能被与该类处于同一个包的类及该类的子类所直接存取和使用。

    ■private

    被声明为private的变量和方法是“私有”的,除了声明它们的类外,不能被任何其它的类直接存取和使用。

    当变量或方法前不加以上三种修饰符时,被认为取friendly状态,即它们只能被同一个包中的类直接存取和使用。但不存在friendly关键字。

    ■static

    被声明为static的变量和方法是属于类而不是属于对象的。不管这个类产生了多少个对象,它们都共享这个类变量或类方法。我们可以在不创建类实例对象时直接使用类变量和类方法。一般来说,在Java中,引用一个特定的变量或方法的形式是:

    对象名.变量名

    对象名.方法名

    例如:

    int a=rectangle.length;

    g.drawString("Welcome to Java World!");

    即变量和方法是受限于对象的,但声明为static的变量或方法受限于类,使用形式是

    类名.变量名

    类名.方法名

    例如:

    System.out.println("Welcome to Java World!");

    String s=String.valueOf(123);

    这里我们并没有创建System类或String类的对象,而直接调用System类的类变量out和String类的类方法valueOf。其中valueOf方法将整形参数转换为String类对象。被声明为static的类方法在使用时有两点要特别注意:

    (1)类方法的方法体中只能使用类中其它同样是static的变量或方法;

    (2)类方法不能被子类修改或重新定义。

    ■final

    将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。

    ■abstract

    这个修饰符仅适用于方法。被声明为abstract的方法不需要实际的方法体,只要提供方法原型接口,即给出方法的名称、返回值类型和参数表,格式如下:

    abstract 返回值类型 方法名(参数表);

    定义了abstract抽象方法的类必须被声明为abstract的抽象类。

    4.1.3 构造方法和finalizer

    Java中有两个特殊的方法:用于创建对象的构造方法(constructor)和用于撤销对象的方法finalizer,相当于C++中的构造函数和析构函数。构造方法是生成对象时编译器自动调用的方法,用以给出对象中变量的初值。构造方法必须与类同名,而且绝对不允许有返回值,甚至不允许以void来标记无返回值。一个类的构造方法可以有多个,以不同的参数表区分不同的情形,这是Java多态性的一个体现。下面是一个简单的例子。

    例4.1 Rectangle类的构造方法。

    class Rectangle{

    protected int width;/*类Rectangle的两个整型变量*/

    protected int height;/*分代表长方形的长和宽*/

    /*下面是类Rectangle的三个构造方法*/

    /*第一个构造方法,无参数,缺省地给出长和宽*/

    Rectangle()

    /*第二个构造方法,给出长、宽参数*/

    Rectangle(int w,int h)

    /*第三个构造方法,给出另一个Rectangle作参数*/

    Rectangle(Rectangle r)

    {width=r.width();

    height=r.height();

    }

    /*下面是类Rectangle的另外两个方法,分别为取长和宽的值*/

    public int width()

    {return width;}

    public int height()

    {return height;}

    }

    class Test{

    Rectangle r1=new Rectangle();/*调用第一个构造方法*/

    Rectangle r2=new Rectangle(12,20);/*调用第二个构造方法*/

    Rectangle r3=new Rectangle(r1);/*调用第三个构造方法*/

    }

    在这个例子中Rectangle有三个构造方法,它们的名字相同,参数不同因而采用的调用形式也不同。第一个构造方法不需要任何参数,调用时系统自动地给出统一的固定的长方形的宽和高(这里我们设定为20和30)。第二个构造方法需要两个整形参数,根据用户给出的长方形的宽和高创建长方形对象。第三个构造方法需要一个长方形参数,创建出与这个长方形具有同样的宽和高的长方形对象。在Rectangle类中,width和height都是protected的,不宜直接存取。为了使用方便,我们定义出width()和height()方法来获得一个特定长方形的宽和高,再将取得的数值传递给新创建的对象。像这样在一类中有两个或两个以上同名方法的现象叫Overloading,是多态的一种表现。这样同名方法应该有且必须有不同的参数表,调用时编译系统就是根据参数的匹配情况,包括个数和类型,来决定实际使用哪一个方法的。如果两同名方法的参数表也相同,会造成混淆,编译时将得到出错信息:

    Duplicate method declaration

    (重复的方法声明)

    为了实际创建出对象,我们要使用new。系统执行遇到new,才根据new后面跟随的构造方法名和参数表,选择合适的构造方式,分配内存,创建对象并初始化。一个类若没有显示地定义构造方法,使用new时将调用它的父类的构造方法,这种上溯可一直到达Object类,而Object类的构造方法是语言预先定义好的。

    相对于构造方法,在对象被撤销时调用的方法是finalizer。对所有的类,它的原始定义形式都是一样的:

    void finalize();

    没有返回值,而且没有任何参数。一般来说,由于Java的内存管理是由系统自动完成,通常不需要我们重写这个方法,而让它自然而然地从父类(最终也就是从Object类)继承。只有当某些资源需要自动归还时,才需要将这一方法重写。

    4.1.4 重写(Overriding)和重载(Overloading)

    方法的重写Overriding和重载Overloading是Java多态性的不同表现。前者是父类与子类之间多态性的一种表现,后者是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写(Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。这在例4.1中已经可以看到。下面再给出两个简单的例子,分别显示Overriding和Overloading。

    例4.2 Overriding的例示

    class Father{

    void speak(){

    System.out.println("I am Father!");//父类定义的speak方法

    }

    }

    class Son extends Father{

    void speak(){

    System.out.println("I am Son!");//子类重写的speak方法

    }

    }

    public class Check{

    public static void main(String args[]){

    Son x=new Son();

    x.speak();//调用子类的speak方法

    }

    }

    //output of class Check!

    I am Son!

    从这个例子我们可以看到,类Son中的speak()方法重写了其父类Father中一模一样的方法,而它的对象x调用speak()方法的结果是与Son中定义致的。

    例4.3 Overloading例示。

    class Father{

    void speak(){  //无参的speak方法

    System.out.println("I am Father.");

    }

    void speak (String s){  //有参的speak方法

    System.out.println("I like"+s+".");

    }

    }

    public class Check{

    public static void main(String args[]){

    Father x=new Father();

    x.speak();//调用无参的speak方法

    x.speak("music");//调用有参的speak方法

    }

    }

    //out put of class Check

    I am Father

    I like music.

    这个例子中类的Father定义了两个speak方法,在类Check中又两次调用,一次无参,一次有参,打印出两行不同的字符串。注意Java在打印字符串时,字符串间的连接用符号“+”来完成。

    Overriding是父类与子类之间多态性的一种表现;Overloading是一个类中多态性的一种表现。

    4.1.5 几个特殊的变量:null,this和super

    Java中有三个特殊的变量:null,this和super,这三个变量是所有的类都可以使用的,用来指示一些特定的对象。

    null相当于“空”,可以用来代指任何对象,但没有实例。如

    Rectangle r=null;

    创建了一个Rectangle的变量r,但并没有一个Rectangle的实例对象由r来代表。r就如同一个可放置Rectangle的盒子,只是这个盒子现在是空的。

    this用以指代一个对象自身。它的作用主要是将自己这个对象作为参数,传送给别的对象中的方法。它的使用形式是这样的:

    class Painter{

    ...

    void drawing(Father y){

    ...

    }

    }

    class Father{

    ...

    void draw(Painter x)

    {...

    x.drawing(this);/*将自身传递给x的drawing方法*/

    ...

    }

    }

    class Test{

    ...

    Father f=new Father();

    Painter p=new Painter();

    f.draw(p);

    ...

    }

    例中调用Father类的draw方法时,使用语句

    f.draw(p);

    又Father类中定义draw方法时以this为参数调用了类Painter的drawing方法:

    x.drawing(this);

    因而实际上调用了Painter类对象p的drawing方法,而将Father类对象f作为参数传递给drawing方法.

    super用来取用父类中的方法和变量数据。它的用法如在下面的例子中所示。

    例4.4在类中使用super的例示。

    /* Check.java */

    class Father{

    void speak(){

    System.out.println("I am Father.");

    }

    void speak(String s){

    System.out.println("I like "+s+".");

    }

    }

    class Son extends Father{

    void speak(){

    System.out.println("My father says.");

    super.speak();//相当于调用Father类的speak()方法

    super.speak("hunting");

    //相当于调用Father类的speak(String s)方法

    }

    }

    class Check{

    public static void main(String args[]){

    Son s=new Son();

    s.speak();

    }

    }

    //Check.java的执行结果:

    My father says:

    I am Fater.

    I like hunting.

    在这个例子中,类Son的speak()方法语句

    super.speak();

    super.speak("hunting");

    实际调用了Son的父类Father中的speak()和speak(String s)方法,以实现执行结果后两行的输出。使用父类的变量形式也很类似。

    super.变量名

    super和this的另一个重要用途是用在构造方法中。当一个类中不止一个构造方法时,可以用this在一个构造方法中调用中一个构造方法。若想调用父类的构造函数,则直接使用super。例如我们可心如下定义例4.1中类Rectangle的子类ColorRectangle:

    public class ColorRectaqngle extends Rectangle{

    int color;

    ColorRectangle(int w,int h,int c){

    super(w,h);

    color=c;

    }

    ...

    }

    与父类Rectangle相比,类ColorRectangle增加了color成员变量代表长方形的颜色。在它的构造方法中,用语句

    super(w,h);

    调用了类Rectangle的构造方法

    Rectangle(int w,int h);

    设定长方形的长和宽,然后就只需设定长方形的颜色:

    color=c;

    这样大大提高了代码的重用性。

    4.2 Java的包

    在Java中,包的概念和目的都与其它语言的函数库非常类似,所不同的只是其中封装的是一组类。为了开发和重用的方便,我们可以将写好的程序类整理成一个个程序包。Java自身提供了21个预先设定好的包,下面列出其中主要的几个,其余读者参看Java的API:

    java.lang    提供基本数据类型及操作

    java.util    提供高级数据类型及操作

    java.io     提供输入/输出流控制

    java.awt     提供图形窗口界面控制

    java.awt.event  提供窗口事件处理

    java.net     提供支持Internet协议的功能

    java.applet   提供实现浏览器环境中Applet的有关类和方法

    java.sql     提供与数据库连接的接口

    java.rmi     提供远程连接与载入的支持

    java.security  提供安全性方面的有关支持

    我们可以引用这些包,也可以创建自己的包。

    4.2.1 包的声明

    为了声明一个包,首先必须建立一个相应的目录结构,子目录名与包名一致。然后在需要放入该包的类文件开头声明包,形式为:

    package 包名;

    这样这个类文件中定义的所有类都被装入到你所希望的包中。例如

    package Family;

    class Father{

    ...//类Father装入包Family

    }

    class Son{

    ...//类Son装入包Family

    }

    class Daughter{

    ...  //类Daughter装入包Family

    }

    不同的程序文件内的类也可以同属于一个包,只要在这些程序文件前都加上同一个包的说明即可。譬如:

    //文件 Cat.java

    package Animals;

    class Cat{/*将类Cat放入包Animals中*;

    ...

    }

    //文件Dog.java

    package Animals;

    class Dog{  /*将类Dog放入包Animals中*/

    ...

    }

    4.2.2 包的使用

    在Java中,为了装载使用已编译好的包,通常可使用以下三种方法:

    (1) 在要引用的类名前带上包名作为修饰符。如:

    Animals.Cat cat=new Animals.Cat();

    其中Animals是包名,Cat是包中的类,cat是类的对象。

    (2)在文件开头使用import引用包中的类。如:

    import Animals.Cat;

    class Check{

    Cat cat=new Cat();

    }

    同样Animals是包名,Cat是包中的类,cat是创建的Cat类对象。

    (3)在文件前使用import引用整个包。如:

    import Animals.*;

    class Check{

    Cat cat=new Cat();

    Dog dog=new Dog();

    ...

    }

    Animals整个包被引入,Cat和Dog为包中的类,cat和dog为对应类的对象。

    在使用包时,可以用点“.” 表示出包所在的层次结构,如我们经常使用的

    import java.io.*;

    import java.applet.*;

    实际是引入了/java/io/或/java/applet/这样的目录结构下的所有内容。需要指出的是,java.lang这个包无需显式地引用,它总是被编译器自动调入的。使用包时还要特别注意系统classpath路径的设置情况,它需要将包名对应目录的父目录包含在classpath路径中,否则编译时会出错,提示用户编译器找不到指定的类。

    4.3 一个邮件类(Mails)的例子

    下面我们给出一个较大的例子,让读者在实例中进一步熟悉Java的类和包。

    这里所有的类都放在包ch4package中,先定义出一个虚基类Mails,然后派生出它的两个子类Parcel(包裹)和Remittance(汇款)。Show类用于实际执行,允许用户创建自己的邮件,然后显示出所有的邮件信息。为了方便地存取邮件,还定义了类ShowMails。接下来我们逐一介绍这经些类。

    例4.5 类Mails程序文件。

    1:package ch4package;

    2: public abstract class Mails{

    3:  protected String fromAddress;

    4:  protected String toAddress;

    5:  public abstract void showMe();

    6: }

    类Mails是一个虚类,不能产生自己的实例对象,而只是描述了邮件最基本的特性。类文件的开头首先用

    package cha4package;

    表明Mails类是放于ch4package这个包里的。然后程序第二行为Mails的类声明。

    public abstract class Mails

    用修饰符abstract指出这是个虚类。第三至第四行Mails类中定义了两个变量:

    protected String fromAddress;

    protected String toAddress;

    fromAddress和toAddress ,分别代表邮件的寄出地址和送往地址,都是protected类型的,这样cha4package包外的类不能直接引用,保证了信息的隐藏。第五行Mails类定义了方法

    showMe(),用于显示一个邮件自身的有在信息:

    public abstract voi showMe();

    声明时以abstract修饰,意味着这是一个抽象方法,只给出原型,具体实现要由Mails类的非虚子类通过Overriding完成。

    接下来是Mails的两个非虚子类。

    例4.6 类Parcel和类Remittance程序文件。

    //Parcel.java

    1: package ch4package;

    2:  public class Parcel extends Mails{//邮件类的子类Parcel类

    3:   protected int weight;

    4:   Parcel(String address1,String address2,int w){//构造方法

    5:   fromAddress=address1;

    6:   toAddress=address2;

    7:   weight=w;

    8:  }

    9:  public void showMe(){

    10:  System.out.print("Parcel:");

    11:  System.out.println("\tFrom:"+fromAddress+"\tTo:"+toAddress);

    12:  System.out.println("\tWeigth:"+weight+"g");}

    13: }

    //Remittance.java

    1: package ch4package;

    2:  public class Remittance extends Mails{//邮件类的子类Remittance

    3:   protected int money;

    4:   Remittance(String address1,String address2,int m){//构造方法

    5:   fromAddress=address1;

    6:   toAddress=address2;

    7:   money=m;

    8:  }

    9:  public void showMe(){//显示邮件信息

    10:  System.out.println("Remittance:");

    11:  System.out.println("\tFrom:"+fromAddress+"\tTo:"+toAddress);

    12:  System.out.println("\tMoney:"+money+" Yuan");

    13: }

    14:}

    这里是邮件的两个子类:包裹Parcel和汇款Remittance。以类Parcel为例详细说明。首先在程序开头写出:

    package ch4package;

    一方面将类Parcel装入包ch4package,另一方面方便类Parcel使用包ch4package中的其它类,如已定义的Mails类。接下来类Parcel声明时用

    extends Mails

    表明自己是Mails的一个子类。在第三行Parcel声明了一个weight变量,用来代表包裹的重量。加上从父类Mails继承下来的变量fromAddress和toAddress,类Parcel一共有三个成员变量:

    寄出地址 fromAddress,寄达地址toAddress和重量weight

    相对应的,它的构造方法Parcel也必须有三个参数,分别传递给三个成员变量。构造方法的定义如第四行至第八行所示。由于Parcel类不是虚类,所以必须在其中重写完成它的父类Mails中声明的抽象方法showMe。Parcel的showMe()方法仅仅是将自己的邮件类型和三个变量的信息在屏幕上显示出来。

    类Remittance与Parcel非常相似,只是它定义的变量为money,用来代表汇款的金额。它也必须具体完成方法showMe。

    下面我们看到的是用于存取邮件的类ShowMails。

    例4.7 类ShowMails程序文件。

    1: package ch4package;

    2: import java.lang.*;

    3: public class ShowMails{

    4:  protected Mails showList[];//邮件数组序列

    5:  protected static final int maxMails=50;//最大邮件个数

    6:  protected int numMails;//当前邮件个数

    7:  ShowMails(){

    8:   showList=new Mails[maxMails];

    9:   numMails=0;

    10: }

    11: public void putMails(Mails mail){

    12:  if(numMails

    13:   showList[numMails]=mail;//加入邮件

    14:   numMails++;//修改计数

    15:  }

    16: }

    17: public Mails getMails(int index){//获取邮件

    18:  if((0<=index)&&(index

    19:  else return null;

    20: }

    21: public void showAll(){//展示邮件

    22:  if(numMails>0)

    23:   for (int i=0;i

    24:    System.out.print("Mail NO"+(i+1)+":");//邮件序号

    25:    showList[i].showMe();//邮件具体信息

    26:   }

    27:  else

    28:   System.out.println("No mails.");

    29: }

    30: public int mailnum(){

    31:  return numMails;

    32: }

    33:}

    程序第四行至第六行类ShowMails定义了三个成员变量:

    showList[],maxMails和numMails

    变量showList[]是类Mails的一个数组。但由于Mails本身是个虚类,因而showList[]的元素不可能是Mails的对象,它实际上是用来存放Mails的两个子类Parcel和Remittance的对象的。一般说来,一个被声明为类A的的变量,总可以被赋值为任何类A的子类的实例对象。这与父子类之间的类型转换的原则是一致的:父类到子类的转换可以隐式地自动进行,而子类到父类的转换则需要显式地加以说明。

    变量maxMails用来指出showList[]中最多可容 纳的邮件数,它对ShowMails的所有对象都应是固定且一致的。因此它被声明为tatatic和final的,为所有对象共享且不可更改。变量numMails则用来作为showList[]中实际邮件个数的计数。

    对应ShowMails的三个成员变量,我们在ShowMails()构造方法中只需做两件事:实际创建类mails的数组showList[],然后将邮件计数numMails置零。

    第11行开始的方法putMails和第17行开始的方法getMails分别完成对showList[]中邮件的存取。第30行的mailnum方法则返回当时的邮件计数值。putMails方法接受一个邮件类参数,并把它加入到当前邮件序列的末尾。getMails方法接受一个整型参数作为邮件序号,根据该序号找出当前邮件序列中对应邮件返回。当给定的邮件号index不在有效范围时,以据该序号找出当前邮件序列中对应邮件返回。当给定的邮件号index不在有效范围时,以

    return null;(19行)

    返回一个定值。这一句看上去并没有完成什么实质性的工作,但如果省略则编译时会出错。因为getMails方法的返回值已声明为Mails类,这就要求在任何情况下都返回一个符合这一要求的值。而空变量null可与任何类型匹配,恰好能适合这样的要求。

    第21行的方法showAll显示showList[]中所有邮件的信息。每一邮件首先显示自己的邮件号。因为showList[]数组的下标从0开始,为了符合人们的日常习惯,将每一个下标加1后再作为邮件号输出。各个邮件的显示是调用邮件的showMe()方法来实现的。因为showMe()方法已经在虚类Mails中定义了,所以不管showList[]中的实际元素是Parcel还是Remittance,编译器总能顺利地连接调用相应的代码。Java面向对象特性中的动态绑定(Dynamic Binding),保证了无需在编译前确定地知道showList[]每一个数组元素的类型,就能成功地实现这样的链接。

    最后给出的类是实际执行的Shos类。

    例4.8 类Show程序文件

    1: package ch4package;

    2: import java.io.*;

    3:

    4: public class Show{

    5: public static ShowMails board=new ShowMails();//邮件库变量

    6:  public static void main(String args[])throws IOException{

    7:    boolean finished=false;

    8:   BufferedReader in =new BufferedReader(new InputStreamReader(System.in));

    9:   while(!finished){//添加邮件

    10:    System.out.print("\nDo you want to add mails(Y/N)?");

    11:    System.out.flush();

    12:    char ch=in.readLine().charAt(0);

    13:    if('Y'==Character.toUpperCase(ch)){//输入地址

    14:    System.out.println("Address information:");

    15:    System.out.print("\tFrom:");

    16:    System.out.flush();

    17:    String address1=in.readLine();

    18:    System.out.print("\tTo:");

    19:    System.out.flush();

    20:    String address2=in.readLine();

    //选择邮件各类(包裹或汇款)

    21:    System.out.print("Choose the mail type:1-Parcel 2-Remittance ");

    22:    System.out.flush();

    23:    ch=in.readLine().charAt(0);

    24:    if('1'==ch){//输入包裹重量

    25:     System.out.print("Parce\tWeight:");

    26:     System.out.flush();

    27:     int w=getInt();

    28:     Parcel pa=new Parcel(address1,address2,w);

    29:     board.putMails(pa);

    30:    }

    31:    if('2'==ch){//输入汇款金额

    32:     System.out.print("Remittance\tMoney:");

    33:     System.out.flush();

    34:     int m=getInt();

    35:     Remittance re=

    new Remittance(address1,address2,m);

    36:     board.putMails(re);

    37:    }

    38:   }

    39:   else finished=true;

    40:  }

    41:  System.out.println(" ");

    42:  board.showAll();//输出所有邮件信息

    43: }

    //键盘输入获取整数

    44: public static int getInt() throws IOException{

    45:  BufferedReader in= new BufferedReader

    (new InputStreamReader(System.in));

    46:  String st=in.readLine();

    47:  Integer i=new Integer(st);

    48:  return i.intValue();

    49: }

    50:}

    由于涉及交互,类Show中用到了许多输入输出语句,我们在程序第2行用

    import java.io.*;

    引入Java的IO包。这个包封装了大量有关输入输出的方法,具体内容将在第七章中详细介绍。这里我们只需要弄清楚所用到的输入/出语句的功能。

    在输入/出中,总有可能产生输入输出错误,Java反这引起错误都归入IOException(IO异常)因为我们不打算在程序中加入对这些异常的处理,所以需要在每个方法的参数表后用关键字throws“扔出”这些异常,如第6行

    public static void main(String args[])throws IOException

    这样异常发生时,将自动中止程序运行并进行标准处理。请参看第五章的内容。

    程序的输入来源是一个BufferedReader类的对象in,它的声明在第8行:

    BufferedReader in=new BufferedReader(new InputStreamReader(System.in));

    因而具有BufferedReader中定义的所有输入功能。

    in.readLine()

    是读入一行输入,并返回一字符串。而

    charAt(i)

    是String类的一个方法,取得指定字符串的第i个元素作为字符型返回。这两上方法边用,则可取得想要的输入。而在输入前用

    System.out.flush();

    将缓冲清空,以保证输入的正确性。

    System.out.print

    System.out.println

    都是输出语句,不同的只是后者在输出结束后自动换行。类System和getInt()中用到的类都是Interger(注意不是int!)都在Java的lang名中定义,我们将在第六章详细介绍。

    在了解以上的基本输入输出后,这个程序就变得较等了。为了方便起见,我们不失一般性的将Show类的所有成员都定义为static的,这样,类Show就不同志需要特别定义的构造方法了。在第5行声明的变量board是ShowMails类的对象,用来建立邮件库:

    public static ShowMails board=new ShowMails();

    第44行开始的getInt方法用来从键盘输入获得一个整数。第6行开始的main方法则是程序的主体。它实现的功能是不断询问是否要加入新邮件,肯定回答时要求选择邮件类型并输入相应信息。据此创建邮件子类对象并加入board中,直至得到不定回答退出。最后显示此时已有的邮件信息。邮件的加入和显示都通过简单的

    board.pubMails()

    board.showAll()

    调用ShowMails的方法来实现的,简洁明了而层次清晰。这就是面向对象进行数据封装和重用的优点所在。要执行类Show,我们需要将例4.5~例4.8的文件依次输入、编译。最后用解释器java执行类Show。下面给出的是Show的运行结果,其中加下划线“_”的是键盘输入。

    例4.9 类Show运行结果。

    D:\java01>java ch4package.Show

    Do you want to add mails(Y/N)?n //询问有是否添加邮件

    No mails.             //显示没有邮件

    D:\java01>java ch4package.Show

    Do you want to add mails(Y/N)?y//询问有是否添加邮件

    Address information:      //要求输入地址信息

    From:NanJing

    To:BeiJing

    Choose the mail type:1-Parcel 2-Remittance 1//要求选择邮件类型

    Parce Weight:100//要求输入包裹重量

    Do you want to add mails(Y/N)?y

    Address information:

    From:ShangHai

    To:TianJing

    Choose the mail type:1-Parcel 2-Remittance 2

    Remittance Money:400//要求输入汇款金额

    Do you want to add mails(Y/N)?n

    Mail NO1:Parcel://输出所有邮件信息

    From:NanJing To:BeiJing

    Weigth:2g

    Mail NO2:Remittance:

    From:ShangHai To:TianJing

    Money:400 Yuan

    D:\java01

    4.4 Java的接口

    4.4.1 引进接口的目的

    Java的接口也是面向对象的一个重要机制。它的引进是为了实现多继承,同时免除C++中的多继承那样的复杂性。前面讲过,抽象类中包含一个或多个抽象方法,该抽象类的子类必须实现这些抽象方法。接口类似于抽象类,只是接口中的所有方法都是抽象的。这些方法由实现这一接口的不同类具体完成。在使用中,接口类的变量可用来代表任何实现了该接口的类的对象。这就相当于把类根据其实现的功能来分别代表,而不必顾虑它所在的类继承层次。这样可以最大限度地利用动态绑定,隐藏实现细节。接口还可以用来实现不同类之间的常量共享。

    为了说明接口的作用,我们不妨假设有一系列的图形类,其中一部分在图形中加入了文字,成为可编辑的,它们应当支持最普遍的编辑功能:

    cut,copy,paste和changeFont

    将这些方法的原型统一组合在一个EditShape接口中,就可以保证方法名的规范统一和使用的方便。我们画出这个假想的类和接口的继承关系图,可以更直观地了解。

    Object

    Shape

    ┌────────────┼─────────────┐

    ↓            ↓             ↓

    Circle          Rectangle          Triangle

    ↙ ↘          ↙ ↘            ↙ ↘

    PaintCircle TextCircle PaintRectangle TextRectangle PaintTriangle TextTrangle

    ↑           ↑               ↑

    └───────────┼───────────────┘

    EditShape

    图4.1 Shape 和 EditShape

    以图中类Circle的两个子类为例。类PaintCircle未实现EditShape接口,不支持上述编辑功能。而类TextCircle既是Cricle的子类,又实现了EditShape接口,因而不但具有Circle类的图形牲,又支持EditShape定义的编辑功能。而在TextCircle,TextRectangle和TextTriangle中,支持这些编辑功能的方法是同名同参的(与EditShape的定义一致),这又提供了使用上的方便。

    4.4.2 接口的声明和使用

    Java的接口类似于抽象类,因而它的声明也和抽象类类似,只定义了类中方法的原型,而没有直接定义方法的内容。它的声明格式为:

    [接口修饰符] interface 接口名 [extends 父类名]

    接口修饰符可以是public或abstract,其中abstract缺省时也有效。public的含义与类修饰符是一致的。要注意的是一个编译单元,即一个.java文件中最多只能有一个public的类或接口,当存在public的类或接口时,编译单必须与这个类或接口同名。

    被声明的变量总是被视为static和final的,因而必须在声明时给定初值。被声明的方法总是abstract的,abstarct缺省也有效。与抽象类一样,接口不需要构造方法。接口的继承与为是一样的,当然一个接口的父类也必须是接口。下面是一个接口的例子:

    interface EditShape{

    void cut();

    void copy();

    void paste();

    void changeFont();

    }

    在使用时,为了将某个接口实现,必须使用关键字implements。格式是这样的:

    [类修饰符] class 类名 [extends 父类名] [implements 接口名表]

    其中,接口名表可包括多个接口名称,各接口间用逗号分隔。“实现(implements)“了一个接口的非抽象类必须写出实现接口中定义的方法的具体代码,同时可以读取使用接口中定义的任何变量。

    例4.10 接口的实现

    class TextCircle extends Circle implements EditShape

    {...

    void cut()

    void copy()

    void paste()

    void changeFont

    ...

    }

    4.4.3 多继承

    在Java中,类之间只允许单继承,但我们可以把一个类实现的接口类也看作这个类的父类。类从它实现的接口那里“继承”了变量和方法,尽管这些变量是静态常量,这些方法是未实现的原型。如果一个类实现的接口类不止一个,那么所有这些接口类都被视为它的“父类”。这样,实现了一个或多个接口的类就相当于是从两个(加上该类原有意义上的父类)或两个以上的类派生出来的。Java的多继承正是建立在这种意义之上。通过接口的继承,相当于只选择了一部分需要的特征汇集在接口中由不同的类共享并继承下去,而不必通过父子类间的继承关系将所有的方法和变量全部传递给子类。所以我们又可以把Java的这种多继承称为“有选择的多继承”。这种多继承与一般的多继承相比,更为精简,复杂度也随之大大降低。

    在多继承时,一个子类可能会从它的不同父类那里继承到同名的不同变量或方法,这往往会引起两义性问题,即不知道子类中这样的变量或方法究竟是继承了哪一个父类的版本,在Java中,为了防止出现这样的两义性问题,规定不允许一个子类继承的父类和实现的接口类中定义同名的不同变量,否则编译该子类时将出错,无法通过。而对于方法,由于接口类中定义的总是abstract的方法原型,而没有实际代码,所以不会出现类似的两义性问题。相反,常会存在这样的情况:当接口类中要求实现的方法子类没有实现,而子类的父类中定义有同名方法时,编译器将子类从父继承的该方法视为对接口的的实现。这样的继承和实现都被认为是合法的。

    4.5 实现了接口的邮件类例子

    这一节我们将4.3节邮件类的例子加以改进和扩展,加入有关接口的内容,以说明接口和多继承的概念。

    首先定义一个名为MailPost的接口,其中没有定义变量,而是给出两个有关邮寄方法原型。

    calPrice()计算邮费并以浮点数形式返回;

    post()完成邮寄。

    例4.11 接口MailPost。

    //MailPost.java

    package ch4package;

    public interface MailPost{

    public float claPrice();

    public void post();

    }

    接下来在包裹Parcel和汇款Remittance的基础上分别派生出可邮寄的包裹和汇款:PostParcel和PostRemit两个子类。

    例4.12 子类PostParcel和PostRemit。

    ---------------------------------

    //PostParcel.java

    package ch4package;

    import java.lang.*;

    public class PostParcel extends Parcel implements MailPost{

    protected int postage;

    protected boolean postable;

    protected boolean posted;

    PostParcel(Ttring address1,String address2,int w,intp){

    //构造方法

    super(address1,address2,w);

    postage=p;

    postable=false;

    posted=false;

    }

    public float calPrice(){//计算邮资

    return((float)0.05*weight);

    }

    public void post(){//邮寄包裹

    float price=calPrice();

    postable=(price<=postage);

    posted=true;

    }

    public void showMe(){//显示邮件信息

    float price=calPrice();

    System.out.println("Postable Parcel:");

    System.out.println("\tFrom:")+fromAddress+\tTo"

    +toAddress);

    System.out.println("\tWeigth:)+weigth+"g\tPostage:"

    +postage+"Yuan");

    if(posted){

    if(postable)System.out.println("\tIt has been

    posted !");

    else{

    System.out.println("\tIt needs more postage:");

    System.out.println("\tThe current postage

    is:"+postage+"Yuan");

    System.out.println("\t\tThe price is:"+price+"Yuan");

    }

    }

    }

    }

    //PostRemit.java

    package ch4package;

    import java.lang.*;

    public class PostRemit exteds Remittance implements MailPost{

    protected int postage;

    portected boolean postable;

    protected boolean posted;

    PostRemit(String address1,String address2,int m,int p){

    //构造方法

    super(address1,address2,m);

    postage=p;

    postable=false;

    posted=false;

    }

    public float calPrice(){//计算邮资

    float price=cealPrice();

    postable=(price<=postage);

    posted=true;

    }

    public void showMe(){//显示邮件信息

    float price=calPrice();

    System.out.println("Postable Remit:");

    System.out.println("\tFrom:"+fromAddress+"\tTo:"

    +toAddress);

    System.out.println("\tMoney:"+money+"Yuan"+"\tPostage:"

    +postage+"Yuan");

    if(posted){

    if(postable)System.out.println("\tIt has been

    posted!");

    else{

    System.out.println("\tIt needs more postage:");

    System.out.println("\t\tThe current postage is:"

    +postage+"Yuan");

    System.out.println("\t\tThe price is:"

    +price+"Yuan");

    }

    }

    }

    }

    ---------------------------------

    这两个类都实现了接口MailPost。由于两个类非常相似,我们仍然重点讲解其中一个:类PostParce。

    PostParcel仍是包ch4package中的一员,它是类Parcel的子类(extends Parcel),又实现了接口MailPost(implements MailPost):

    public class PostParcel extends Parcel implements MailPost

    在Parcel的基础上,它新增加了三个变量:

    postage,posted,postable

    其中整型的postage用来记录邮寄人提供的邮资,布尔型的posted和postable分别用来记录是否被尝试邮寄过以及邮寄是束成功。在PostParcel的构造方法中,第9行语句

    super(address1,address2,w);

    调用了它的父类Parcel的构造方法,设定它从Parcel中继承的变量寄出地址、寄达地址和重量的初值。这就是我们在前面提到过的super变量在构造方法中的用途:调用父类的相应构造方法。这样做的一个好处是可以重用父类的代码,然后PostParcel就只需设定邮资,并将posted和postable初值都置为false。

    PostParcel和PostRemit都实现了接口MailPost,国而在它们的定义中,都必须给出方法calPrice()和post()的具体实现。在PostParcel中,为了简单起见,邮费只是根据重量每克收到0.05元,而不考虑寄达的距离,如语句第15行:

    return ((float)0.05*weight);

    在post()方法中,将计算所得邮资与瑞有邮费加以比较,若邮费已够将postable设为true,包裹可邮寄;否则postable为false,包裹不可邮寄。无论postable取值如何,都已试图邮寄,所以将posted置为true。处理过程见第18行至20行。

    最后一个方法是showMe()。在这里,PostParcel重写(Overriding)了它的父类Parcel中的同名方法。当包裹尚未被试图邮寄过,则在基本信息后附加有关的邮寄信息,若未邮寄成功,给出所需最费提示。

    PostRemit类的基本构成与PostParcel是一致的,读者可以自己试着读懂它的源文件。

    在包ch4package中,类Mails,Parcel,Remittance以及ShowMails都无需改动,只有最后的可执行类Show需要相应的修改。它的源程序如下。

    例4.13 可执行类Show程序文件。

    -------------------------

    //Show.java

    1: package ch4package;

    import java.lang.*;

    2: import java.io.*;

    3:

    4: public class Show{

    5: public static ShowMails board=new ShowMails();

    6:  public static void main(String args[])throws IOException{

    7:    boolean finished=false;

    8:   BufferedReader in =new BufferedReader(new InputStreamReader(System.in));

    9:   while(!finished){//添加邮件

    10:    System.out.print("\nDo you want to add mails(Y/N)?");

    11:    System.out.flush();

    12:    char ch=in.readLine().charAt(0);

    13:    if('Y'==Character.toUpperCase(ch)){

    14:    System.out.println("Address information:");

    15:    System.out.print("\tFrom:");//输入地址信息

    16:    System.out.flush();

    17:    String address1=in.readLine();

    18:    System.out.print("\tTo:");

    19:    System.out.flush();

    20:    String address2=in.readLine();

    //选择邮件种类

    21:    System.out.print("Choose the mail type:1-Parcel

    2-Remittance ");

    22:    System.out.flush();

    23:    ch=in.readLine().charAt(0);

    24:    if('1'==ch){//输入包裹重量

    25:     System.out.print("Parcel\tWeight:");

    26:     System.out.flush();

    27:     int w=getInt();

    //是否寄出邮件

    System.out.print("Do you want to post it(Y/N?");

    System.out.flush();

    ch=in.readLine().charAt(0);

    if('Y'==Character.toUpperCase(ch)){//输入邮资

    System.out.println("You want to post in,then

    input your postage:");

    System.out.flush();

    int p=getInt();

    //可邮寄包裹

    PostParcel pa=new

    PostParcel(address1,address2,w,p);

    board.putMails(pa);

    }

    //不可邮寄包裹

    else{Parcel pa=new Parcel(address1,address2,w);

    board.putMails(pa);}

    }

    if('2'==ch){

    System.out.print("Remittance\tMoney:");

    System.out.flush();

    int m=getInt();

    System.out.print("Do you want to post it(Y/N)?");

    System.out.flush():

    ch=in.readLine().charAt(0);

    if('Y'==Character.toUpperCase(ch)){

    System.out.println("You want to post it,then input

    postage:");

    System.out.flush();

    int p=getInt();

    //可邮寄汇款

    PostRemit re=new PostRemit(address1,address2,m,p);

    board.putMails(re);

    }

    //不可邮寄汇款

    else{Remittance re=new Remittance(address1,address2,m);

    board.putMails(re);}

    }

    }

    else finished=true;

    }

    System.out.println("");

    board.showAll();//显示邮件信息

    post();

    }

    public static int getInt() throws IEOxception{

    BufferedReader in=new BufferedReader

    (new InputStreamReader(System.in));

    String st=in.readLine();

    Integer i=new Integer(st);

    return i.intValue();

    }

    private static void post()throws ClassCastException,IOException{

    int n\board.mailnum();

    if(n!=0){

    System.out.println("You have "+n+" mails");

    boolean end=false;

    //检查邮寄情况

    while(!end){

    System.out.print("\nInput the mail NO you want to check the

    result(输0退出):");

    System.out.flush();

    int i=getInt();

    if(i!=0){

    try{

    Mails obj=board.getMails(i-1);

    post((MailPost)obj);

    obj.showMe();

    }catch(ClassCastException ex){

    System.out.println("Mail is not postable!");}

    }

    else end=true;

    }

    }

    }

    private static void post(MailPost obj){

    obj.calPrice();

    obj.post();

    }

    }

    -------------------------

    与第三节例4.8中类的Show相比,改动后的Show的main方法增加了询问是否要将邮件设为可邮寄类型的功能以及相应的处理段,并调用Post()方法邮寄邮件并给出邮寄情况说明。类Show定义了两个post方法来实惠邮寄。这两个方法虽同名,但参数不同,完成的功能也大相径庭。

    第72行至92行的第一个post方法没有参数。它首先给出现有邮件数量,然后根据输入的邮件号通过ShowMails的getMails方法取得邮件,再调用第二个post方法实际将邮件寄出;当输入的邮件号为零时结束。在调用第二个post方法时,需要将邮件显式转换为接口类MailPost:

    83:Mails obj=bord.getMails(i-1);

    84:post((MailPost)obj);

    因为PostParcel和PostRemit都实现了接口MailPost,都支持这样的转换,就可以通过种形式从功能上将它们统一起来。如果该邮件所属的类没有实现接口MailPost ,如类Parcel或类Remittance,这样的类型转换就不能实现,将引发类型转换异常(ClassCastException),不再转去调用post方法,而由catch结构给出“邮件无法被邮寄”的报错信息:

    86:}catch(ClassCastException ex){

    87: System.out.println("Mail is not postable!");}

    其中的try-catch结构是Java中异常处理的典型结构。

    第二个post方法带一个MailPost接口类的参数,它实际调用接口定义的方法calPrice和post将邮件寄出。

    下面我们来看一个Show的执行实例,其中带下划线“_”的部分为执行的键盘输入。

    例4.14 Show的执行结果。

    --------------------

    --------------------

    当启动Show的运行后,首先依照提示创建三个邮件对象,其中第一个是不可邮寄包裹后两个分别是可邮寄的包裹和汇款。停止添加邮件后顺序显示现有邮件信息,包括邮件号、邮件类别、地址信息、重量/金额以及已付邮资,并提示现有邮件总数。此时我们可依次检查邮件是否可寄出:

    输入邮件号“1”,由于此包裹不是可邮寄包裹类,给出报告:邮件不可寄出;

    输入邮件号“2”,该邮件是可邮寄包裹,且通过邮资计算已付足,给出报告:邮件可寄出;

    输入邮件号“3”,该邮件是可邮寄汇款,但欠缺邮资,给出报告:邮件需补足邮资,然后列出应交邮费与实交邮费比较。

    最后输入数字“0”,结束本次执行。

    这样我们就完成了对第三节中邮件类的扩充和改进,最终得到的包ch4package中所有类和接口的层次继承关系,如图4.2所示。读者可以对照这个图理清它们的继承和实现关系。

    Object

    ┌─────┼─────┐

    ↓     ↓     ↓

    Mails  ShowMails  show

    ┌───┴───┐

    ↓       ↓

    Parcel    Remittance

    ↓       ↓

    PostParcel  PostRemit

    ↖  ↗

    MailPost

    图4.2 包ch4package的类和接口层次

    posted on 2007-02-02 20:26 ☜♥☞MengChuChen 阅读(2245) 评论(0)  编辑  收藏 所属分类: java_code

    展开全文
    weixin_34493827 2021-02-26 16:54:21
  • 1、 项目整合管理 注: 1点为项目整合管理的概述 2-7点主要为项目章程(启动)重点 8-11点主要为制定项目管理计划(规划/计划) 12-17点主要为指导工作与项目管理知识(执行) 18-22点主要为监控项目工作和实施变更...

    1、 项目整合管理

    注:
    1点为项目整合管理的概述
    2-7点主要为项目章程(启动)重点
    8-11点主要为制定项目管理计划(规划/计划)
    12-17点主要为指导工作与项目管理知识(执行)
    18-22点主要为监控项目工作和实施变更控制(监控-监督、控制)重点
    23-24点主要为结束项目和阶段(结尾)重点

    (1) 什么是整合管理?整合什么以及如何整合?

    ✧ 项目整合管理(整合是全部过程组的老大)
    ✧ 核心概念:
    ➢ 项目整合管理由项目经理负责。项目经理必须对整个项目承担最终责任;
    ➢ 整合所有其他知识领域的成果,并掌握项目总体情况;
    ➢ 项目整合管理包括对隶属于项目管理过程组的各种过程和项目管理活动进行识别、定义、组合、统一和协调的各个过程。
    ✧ 项目整合管理包括进行以下选择:
    ➢ 资源分配;
    ➢ 平衡竞争性需求;
    ➢ 研究各种备选方案;
    ➢ 为实现项目目标而裁剪过程;
    ➢ 管理各个项目管理知识领域之间的依赖关系;
    ✧ 项目整合管理大概图(PDCA):
    在这里插入图片描述
    ✧ 项目整合管理过程:PDCA(理解并记忆)
    ➢ 启动阶段输出的是项目章程,规划阶段输出的是项目管理计划,项目管理计划要经过批准后才能进入到执行过程组。
    ➢ 一个启动 一个规划 两个执行 两个监控 一个收尾。
    在这里插入图片描述

    (2) 项目章程的作用和主要内容分别是什么(重点理解)?

    ✧ 项目章程的作用:
    ➢ 编写一份正式批准项目并授权项目经理在项目活动中使用组织资源的文件的过程;
    ➢ 确保相关方在总体上就主要可交付成果、里程碑、以及每个项目参与者的角色和职责达成共识;
    ➢ 正式宣布项目的存在,授权项目经理有合法地位
    ➢ 记录业务需要,对客户的需求,以及需要交付的最终成果(目标,范围等)进行主要制约因素和假设条件等总体性描述;
    ➢ 良好的项目章程可以使项目团队对项目有一个整体的了解,并成为团队的规则,减少项目实施中出现的问题;
    ➢ 正式任命项目经理。授权其使用组织的资源开展项目活动
    ✧ 注:一个新的项目经理接手项目,首先应该形成一套完整的项目章程,并且能够得到发起人和关键相关方的支持
    ✧ 项目章程的ITTO(启动):
    ➢ 记录项生命周期和方法论在项目启动阶段做的
    ➢ 成本效益分析(包括项目成本及未来运营成本):收益=潜在效益-投资成本-运营成本
    ➢ 内部报酬率可以来比较项目的盈利能力和抵抗风险
    ➢ 需要制定某某计划要在项目章程批准之后才形成
    ➢ 商业论证牵扯到组织的业务目标,需要和高级管理层讨论决定
    ➢ 项目章程的批准人通常是启动者或者发起人(项目章程是由发起人批准的)
    ➢ 项目章程用来建立组织内部的合作关系
    ➢ 在确定项目完成时,项目章程是项目经理与项目发起人之间的协议依据
    ➢ 当项目的成本、范围、进度都出现严重问题,就要审核项目的可行性(审查商业论证和项目章程)
    ➢ 分析商业论证之前要完成需求评估
    在这里插入图片描述
    ✧ 项目章程的内容(高大上):
    ➢ 提供宏观要求也是高层及的需求,高层级需求的只有项目章程。
    ➢ 可交付成果成功的衡量标准对项目验收环节至关重要。
    在这里插入图片描述

    (3) 谁来负责项目章程的编写和发布?谁能修改项目章程?

    ✧ 项目章程的编写和发布:
    ➢ 项目章程是由项目发起人或联合项目经理编制;项目章程是由管理层签发的,项目经理是项目章程的执行者(参与制定),如果项目是有几个组织联合发起的,这些组织的管理层可联合签发项目章程。
    ➢ 项目章程发布在签订后,召开启动会议进行发布。
    ✧ 如何修改项目章程:
    ➢ 项目章程所贵的的应该是一些比较大的、原则性的问题,通常不会因项目变更而需要对项目章程作出修改,如果一旦需要修改章程,那只有管理层才有权进行,即谁签发的项目章程,谁才有权修改项目章程,项目经理无权进行修改。

    (4) 什么时候使用假设日志,假设日志是什么(考点)

    ✧ 假设日志、制约因素是:
    ➢ 在启动编制商业论证时,识别高层级的战略和运营假设条件与制约因素。假设条件与制约因素应纳入项目章程;
    ➢ 假设日志用于记录整个项目生命周期中的所有假设条件和制约因素;
    ➢ 假设条件则是假设为“真实”或“确定”的一些条件(渐进明性);
    ➢ 制约因素是指项目团队选择余地的因素,常见的是范围、时间、成本、质量等制约因素;
    ➢ (预算仅限于在线交易属于制约因素,而假设条件与制约因素都应纳入项目章程)
    ✧ 什么时候使用假设日志:
    ➢ 假设日志是制定项目章程的输出,假设日志用于记录整个项目生命周期中的所有假设条件和制约因素;
    ➢ 假设日志包括假设条件和制约因素;
    ➢ 寻找“限制/规定”、“假设/如果”等关键词。

    (5) 什么是商业论证?商业论证的作用是什么?

    ✧ 商业论证的定义是:
    ➢ 从项目的商业角度层面提供必要的信息,并决定该项目是否值得投资;
    ➢ 商业论证中通常要包含业务需求和成本效益分析等内容;
    ➢ 在项目生命的周期的早期,项目大气组织对商业论证的定期审核,有助于确认项目是否仍然需要;
    ➢ 商业论证一经批准后项目经理是无权修改和更新的;只可以提出修改建议;
    ➢ 编写有毒物质是商业论证的法律要求。
    ✧ 商业论证的作用是:
    ➢ 论证项目在早期的阶段过程中是否还有继续的必要;
    ➢ 商业论证是制定项目章程的输入,项目的合理性和边界,是高层级做决策的依据。

    (6) 什么时候使用商业论证?(考点)

    ✧ 商业论证是制定项目章程的输入,是高层做决策的依据;
    ✧ 寻找“早期阶段-成本、效益,质疑项目价值收益,分析项目的可行性”等关键词。

    (7) 制定项目章程的工具与技术,什么时候使用一下技术(考点)

    ✧ 专家判断
    ➢ 专业知识或者专业培训经历,各种顾问相关方
    ➢ 寻找”专业、专家组、复杂且没有历史数据“等关键词
    ✧ 头脑风暴
    ➢ 用于在短时间内获取大量的创意
    ➢ 寻找“创意、创新、讨论收集新想法”等关键词
    ✧ 引导
    ➢ 引导团队活动达成决定
    ➢ 寻找“出现意见不一致、为了达成一致”等关键词

    (8) 项目管理计划是什么样的计划?项目管理计划包含哪些主要内容?

    ✧ 项目管理计划定义:
    ➢ 定义、准备和协调项目计划的所有组成部分,并把它们整合为一份综合项目管理计划的过程。项目管理计划包括经过整合的项目基准和子计划;
    ➢ 项目管理计划要持续到项目收尾,项目管理计划是渐进明细出来的;
    ➢ 项目管理计划一旦确定,成为基准,就只能在提出变更请求并经过实施整体变更控制过程批准后,才能变更;
    ➢ 并且项目管理计划是作为其他所有过程的指导文件,它是其他七个过程里面的输入文件;
    ➢ 项目管理计划是作为其他所有过程的指导文件,指导所有项目的基本方针;
    ➢ 除了制定项目章程和制定项目管理计划,其他47过程都有项目管理计划作为输入文件。
    ✧ 制定项目管理计划的作用:
    ➢ 指导项目执行、监控、收尾;
    ➢ 为项目绩效考核和项目控制提供基准;
    ➢ 记录项目计划编制所依据的假设条件;
    ➢ 记录项目计划编制过程中的有关方案选择;
    ➢ 促进项目相关方之间的沟通;
    ➢ 规定管理层审查项目的时间、内容和方式。
    ✧ 项目管理计划的ITTO(规划):
    ➢ 相关方分析:对项目管理计划不确定,要明确。分析各种利害关系;
    ➢ 执行项目必须有管理计划,而管理计划必须得到发起人和相关方的批准认可;
    ➢ 项目管理计划是根据团队成员的输入信息,由项目经理创建项目管理;
    ➢ 一个项目处于规划阶段,要先制定工作分解结构(WBS)、估算资源和制定任务进度计划;
    ➢ 项目经理审查用于确定行动的文件是项目管理计划。
    在这里插入图片描述
    ✧ 项目管理计划主要包括内容:
    ➢ 基准是一份经过批准的项目计划加上或减去经批准的变更;
    ➢ 基准一定是经过高级管理层和主要相关方批准的;
    ➢ 如果要对基准进行变更,只有控制委员会才有权批准。项目经理无权。(项目管理计划能修改,要听过实施整体变更控制过程加以修改);
    ➢ 项目管理计划中没有报告和文档;
    ➢ 有可交付成果的文件是范围说明书、WBS、WBS词典。
    在这里插入图片描述

    (9) 项目管理计划是由谁制定的?又是由谁来负责审批?

    ✧ 项目管理计划由项目经理和项目团队成员进行制定,项目管理计划必须是至下而上编制出来的(专业的人做专业的事情),项目团队成员需要对于自己密切相关的部分编制相应的计划,并逐层向上报告和汇总;
    ✧ 项目管理计划可能不仅要得到管理层的审批,可能还需要得到其他主要项目相关方的批准;
    ✧ 相关方分散在各地又要快速批准的话是可以由关键相关方来批准。

    (10) 为什么项目管理计划的输入中要有其他过程的输出?项目管理计划和项目文件有什么区别?

    ✧ 为什么项目管理计划的输入中要有其他过程的输出?
    ➢ 制定项目管理计划是定义、准备和协调所有子计划,并把它们整合为一份综合项目管理计划的过程。项目管理计划确定项目的执行、监控和收尾方式,其内容会因项目的复杂程度和所在应用领域而异。编制项目管理计划,需要整合一系列相关过程,而且要持续到项目收尾。本过程将产生一份项目管理计划。该计划需要通过不断更新来渐进明细。这些更新需要由实施整体变更控制过程(见4.5节)进行控制和批准。存在于项目集中的项目也应该制定项目管理计划,而且这份计划需要与项目集管理计划保持一致。例如,若项目集管理计划中要求超过特定成本的任何变更都需要由变更控制委员会(CCB)来审查,则在项目管理计划中也应该做出相应规定。
    ✧ 项目管理计划和项目文件的区别:
    ➢ 项目管理计划一般由公司规定,项目文件由项目经理输出;
    ➢ 项目文件中,没有采购相关的文件,如协议与采购文档;采购一般由组织的采购部门负责。
    在这里插入图片描述

    (11) 项目启动大会(Initiating meeting)和项目开工会议(Kick-off meetiog)的内容和作用分别是什么?分别由谁来主导?(考点)

    ✧ 启动会不谈经验教训
    ✧ 开工会议需要哪些人参加要查询相关方登记册

    在这里插入图片描述
    ✧ 考点:Kick-off meetiog
    ➢ 召开时间节点:制定管理计划后,项目管理计划批准后、项目进入执行阶段的标志
    ➢ 目的:在传达项目目标、获得团队对项目的承诺,以及阐明每个相关方角色和职责

    (12) 指导与管理项目执行的主要活动是什么?主要任务是什么?为什么在执行中有变更的产生?

    ✧ 指导与管理项目执行的定义:为实现项目目标而领导和执行项目管理计划中所确定的工作,并实施已批准变更的过程;(照着计划做事情)
    ✧ 指导与管理项目执行的ITTO(执行):
    ➢ 变更管理计划是描述在整个项目期间如何正式审批和采纳变更请求
    ➢ 变更一旦批准就得执行,如果变更有问题或者风险要再次找提交变更的人商讨
    ➢ 项目发起人在项目执行过程中的角色是解决超出项目经理控制范围之外的冲突
    ➢ 范围成本基准已经变更,那么就得更新预算
    ➢ 指导与管理项目工作输入:批准变更请求
    ➢ 出现问题,首先更新问题日志
    在这里插入图片描述
    主要任务:
    在这里插入图片描述
    ✧ 为什么项目会有变更的产生?
    ➢ 在项目的过程中,变更请求可能会由于直接或间接,外部或内部提出,也有可能是自选的或由法律/合同强制的;因为项目有渐进明细性;
    ✧ 批准的变更请求书面记录了经过批准的变更

    (13) 可交付成果以及工作绩效数据的流向。(涉及后续章节)

    在这里插入图片描述

    (14) 变更请求包含哪几种,它们之间的区别是什么(考点区别)?

    ✧ 变更请求其中包含三种:
    预防措施、纠正措施、缺陷补救;(事前预防,事中纠正,事后缺陷补救)
    在这里插入图片描述
    在这里插入图片描述

    (15) 问题日志的主要内容以及针对问题后续的处理流程,什么时候使用问题日志?(考点)

    ✧ 问题日志的主要内容:
    ➢ 在整个项目生命周期中,项目经理通常会遇到问题、差距、不一致或意外冲突。项目经理需要采取某些行动加以处理,以免影响项目绩效。
    ➢ 问题日志便是其中一种记录和跟进所有问题的项目文件,所需记录和跟进的内容可能包括:问题类型和目标解决日期;问题状态;最终解决情况。
    ✧ 问题的处理流程:
    ➢ 问题日志应该在整个项目的生命周期内应该随同监控活动更新问题日志,贯穿整个过程。
    ✧ 什么时候使用问题日志:(已经发生,待解决的问题)
    ➢ 已经产生的问题、问题的跟踪、解决方案等都要查看/更新 问题日志;
    ➢ 寻找“问题、缺陷、问题如何解决”等关键字;
    ➢ 问题日志会记录由谁去解决问题,而问题日志可以避免两个人同时去解决这个问题。

    (16) 管理知识的主要内容及作用是什么?知识的两个大的分类是什么(考点)?知识管理的主要环节是什么?

    ✧ 管理项目知识的定义:
    ➢ 管理项目项目是使用现有知识并生成新知识,以实现项目目标,并且帮助组织学习的过程;
    ➢ 知识管理不只是在项目结束的时候总结经验教训,随时都可以,目的更好的帮助项目上升;
    ➢ 从组织的角度来看,知识管理指的是确保项目团队和其他相关方的技能、经验和专业只是在项目开始之前、开展期间和结束之后得到运用。
    ✧ 管理项目知识ITTO(执行):
    ➢ 经验教训登记册属于项目文件的一部分,在项目过程中即时更新(在项目/阶段收尾的时候才更新到组织过程资产中去)
    在这里插入图片描述
    ✧ 管理知识的两大分类(区别):
    ➢ 显性知识:可以简单的使用文字、图片和数字进行编撰的知识
    ➢ 隐性知识:个体知识以及难以明确表达的只是,如信念、洞察力、经验和“诀窍”
    ➢ 隐性知识(通过不一样的方式转化为)显性知识;
    ✧ 知识管理的主要环节:
    知识管理主要是通过技术和工具将员工联系起来,使他们能够合作生产新知识、分享隐形知识,以及集成不同团队成员所拥有的知识;
    ➢ 主要环节包含:信息管理、人际关系处理和团队技能;

    (17) 经验教训登记册的内容和作用?(必考)何时更新?

    ✧ 经验教训登记册内容:
    ➢ 可以包含情况的类别和描述,还可以包括与情况相关的影响、建议和行动方案;
    ➢ 经验教训登记册可以记录遇到的挑战、问题、意识道德风险和机会(问题总结,问题处理完后,防止问题再次发生);
    ➢ 在项目或阶段结束的时候,把相关信息归入经验教训知识库,成为组织过程资产的一部分。
    ✧ 经验教训登记册作用:
    ➢ 经验教训登记册应该在项目的全生命周期不断更新;
    ➢ 经验教训登记处可以记录:项目中遇到的挑战、问题、意识到的风险或者机会;
    ➢ 寻找”历史文件、为了避免为未来发生的某情况,提高未来项目的成功率“等关键字。
    ✧ 何时更新:
    ➢ 经验教训登记册在项目早期创建,作为本过程的输出;并且再整个项目期间,它可以作为很多过程的输入,也可以作为输出而不断更新。

    (18) 监控项目工作的主要内容是什么?监控的依据是什么?监控的结果是什么?工作绩效报告怎么产生的?监控项目的工具技术?

    ✧ 监控项目工作的定义:
    ➢ 跟踪、审查和报告整体项目进展,以实现项目管理计划中确定的绩效目标的过程;监控过程贯穿项目工作的始终,不仅要对项目执行进行监控,而且要对项目的启动、规划和收尾进行监控;可分为监督、控制工作。
    ✧ 内容包含:
    ➢ 把项目的实际绩效与项目管理计划(依据)进行比较,定期进行评估项目绩效,检查单个项目的风险状态等。
    ✧ 监控项目工作的ITTO(监督):
    ➢ 工作绩效报告的示例包括状态报告和进展报告;
    ➢ 工作绩效报告了解潜在会延迟项目的可能性。
    在这里插入图片描述
    ✧ 监控的结果:
    ➢ 评估项目绩效,决定是否需要采取纠正或预防措施,并推荐必要的措施。
    ✧ 工作绩效报告:
    ➢ 根据绩效数据→绩效信息汇总整理后,由项目经理进行工作绩效报告输出。
    ✧ 监控项目工作的工具与技术:
    在这里插入图片描述

    (19) 变更处理的一般流程是什么?不同的情况应该如何对应流程?(重点理解必考)

    ✧ 实施整体变更控制定义:
    ➢ 审查所有变更请求,批准变更,管理对可交付成果、项目文件和项目管理计划的变更,并对变更处理结果进行沟通的过程。该过程贯穿项目始终(有变更,走流程!)
    ✧ 实施整体变更控制ITTO(控制):
    ➢ 对于已经批准的变更,没必要再评估,批准的变更首先要更新对应的计划;
    ➢ 里程碑包含在进度基准里;
    ➢ 有变更,走流程,要先提交变更申请;
    ➢ 一般对于内部人员提出变更,先分析影响,再提交申请。外部人员提出变更,先提交申请,再分析影响;
    ➢ 对内部设计进行重大修改,属于范围修改了,涉及范围管理计划;
    ➢ 在收尾阶段,发现项目范围比最终的项目范围低,就在项目报告中记录项目原始和最终成本。
    在这里插入图片描述
    ✧ 变更处理的一般流程:
    (有变更,走流程,要先提交变更申请(可以约束口头变更,标志整体变更正式开始))
    ➢ 提变更请求→(评价变更对项目的影响)→批准或否决变更→实施变更(若批准)→追踪变更的实施情况→信息沟通存档;
    ✧ 不同情况下的变更流程:
    ➢ 所有相关方都可以发起变更请求;
    ➢ 所有的变更请求以书面的形式记录;
    ➢ 变更要分析全面;
    ➢ 批准了才能执行(更新项目管理计划);
    ➢ 相关方提出变更,先要内部团队评估,在与相关方谈;
    ➢ 不涉及基准:PM;
    ➢ 涉及基准:CCB。
    在这里插入图片描述

    (20) 不同状态的变更该如何处理?(考点)

    ✧ 变更一旦批准该怎么做?
    ➢ 更新计划、更新日志、再执行
    ➢ 更新项目管理计划
    ✧ 变更一旦拒绝该怎么做?
    ➢ 更新变更日志
    ➢ 通知相关方此变更请求已拒绝,并告知相关信息
    ✧ 没走变更流程就实施了变更怎么做?
    ➢ 补变更流程

    (21) 变更控制委员会的作用是什么?项目经理在变更过程中起什么作用?

    ✧ 变更控制委员会(Change Control Board)的定义:
    CCB不是一个具体的组织,它是一个决策机构,它的组成一般通过项目相关方进行组成(顾问团),负责审查变更请求,为准备提交的变更请求提供指导,对变更请求做出评价,批准或否决变更请求,并管理经批准的变更的实施流程。
    ✧ 项目经理的作用:
    项目经理再变更内容不涉及到项目的范围、时间、成本和质量(基准)的前提下,可直接进行项目的变更批准,并且需要把控项目变更的全过程。

    (22) 变更日志包括什么内容(变更状态:持续更新)?

    ✧ 批准的变更请求,变更日志是对项目所做更改的详细记录,通常包括修复和新功能。
    ✧ 项目管理计划更新。除了主项目日志外,项目中的每个文件或文档都可能包含自己的更改日志。
    ✧ 以项目文件更新的形式,在变更日志中记录所有变更请求的处理情况。
    ✧ 项目文件更新正式授权的任一项目文件都可在本过程变更,更改日志通常由按时间顺序排列的列表组成,详细列出已进行的更改以及更改的执行者。
    ✧ 变更日志只是用来记录的,变更不会对它照成影响。

    (23) 什么时候可以结束项目或阶段?异常终止时要不要走结束项目或阶段的流程?

    ✧ 结束项目或阶段得定义:
    ➢ 终结项目、阶段或合同得所有活动得过程,只有当顺利结束项目或因为意外终止得时候才算结束。
    ✧ 结束项目或阶段ITTO(收尾):
    ➢ 客户没有进行正式验收,并查出BUG,还是要修正后做正式验收;
    ➢ 项目已经验收,不再受理变更申请;
    ➢ 项目被取消,也应该进行完整收尾过程;
    ➢ 确认范围是正式验收已完成的项目可交付成果的过程;
    ➢ 收尾验收由客户、发起人;
    ➢ 需求跟踪矩阵连接了需求和可交付成果;
    ➢ 项目收尾收集信息供未来使用,是组织过程资产。
    在这里插入图片描述
    ✧ 异常终止项目是否还需要走流程呢?
    ➢ 异常终止项目也需要根据原有流程结束项目,并且需要调查异常结束原因并且归入经验教训登记册内形成组织过程资产。

    (24) 项目收尾包括什么内容?

    ✧ 四大种类收尾:
    ➢ 主要活动
    ➢ 项目最终报告
    ➢ 行政收尾:是结束项目或者阶段必须进行的工作
    ➢ 合同收尾

    ✧ 项目收尾包含的活动内容:
    ➢ 收尾先进行文件更新在归档文件;
    ➢ 解散资源一定在最后一步;
    ➢ 选择根本不是收尾该做的,可排除;
    ➢ 项目移交给运营团队后,要将相关方反馈加入经验教训库;
    ➢ 收集经验教训后要更新组织过程资产(提高对未来项目的管理);
    ➢ 在收尾过程中出了总结经验教训后,就应该收集客户的反馈;
    ➢ 前一个项目有问题要处理完毕之后才能进入到下一个项目;
    ➢ 已完成可交付成果后,先验收,再签字;
    ➢ 执行项目后评价也属于经验教训,需要记录经验教育并更新到经验教训知识库,成为组织过程资产的一部分;
    ➢ 项目结束后,为了获得运营的支持,需要结束项目转交。

    ✧ 收尾步骤:
    ➢ a.正式验收;
    ➢ b.移交结果;
    ➢ c.财务收尾
    ➢ d.满意度调查;
    ➢ d.收集经验教训;
    ➢ e.文件更新(组织过程资产);
    ➢ f.最终报告;
    ➢ g.文件归档;
    ➢ h.庆功会;
    ➢ l.释放资源(意味着项目正式结束、最后一步)
    ✧ 项目收尾所需做的工作:
    ➢ 产品核实→正式验收→收集记录→更新记录 →记录存档 →归档→经验教训 →绩效考评→团队庆祝活动→释放资源。

    展开全文
    LingAoXia 2021-08-27 11:22:03
  • Kaiyuan_sjtu 2021-09-11 00:58:31
  • XPF156915 2021-08-12 12:02:33
  • weixin_42525343 2021-07-23 13:08:03
  • pcgamer 2021-04-03 19:30:57
  • jiangyangll 2021-11-12 09:28:48
  • weixin_33324197 2021-03-05 12:22:13
  • weixin_47692652 2021-12-02 10:33:02
  • weixin_42404710 2021-05-11 20:27:40
  • Together_CZ 2021-01-06 19:28:32
  • liujwhb313 2021-10-14 17:34:05
  • weixin_38135620 2021-02-22 00:14:56
  • weixin_33416697 2021-02-05 23:51:22
  • ZYC88888 2021-06-03 20:48:41
  • weixin_44569172 2021-05-04 23:08:34
  • ZCShouCSDN 2021-02-01 14:17:25
  • weixin_29938187 2021-05-24 09:41:23
  • u010257584 2021-03-05 09:09:05
  • weixin_39714015 2021-03-01 07:58:26
  • Yong_Qi2015 2021-03-17 00:31:47
  • S_yyuan 2021-08-18 17:15:46
  • qq_29462849 2021-07-22 01:08:01
  • weixin_35956312 2021-06-17 05:21:47
  • qq_29061315 2021-10-28 10:07:34
  • whatday 2021-01-11 10:58:39
  • diandianxiyu 2021-06-18 07:17:03

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 133,886
精华内容 53,554
关键字:

哪些是限制类供地项目