应用OOP的设计过程演化_第1页
应用OOP的设计过程演化_第2页
应用OOP的设计过程演化_第3页
应用OOP的设计过程演化_第4页
应用OOP的设计过程演化_第5页
已阅读5页,还剩58页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、应用OOP的设计过程演化面向对象的程序设计(Object-Oriented Programming,简记为OOP)立意于创建软件重用代码,具备更好地模拟现实世界环境的能力,这使它被公认为是自上而下编程的优胜者。它通过给程序中加入扩展语句,把函数“封装”进编程所必需的“对象”中。面向对象的编程语言使得复杂的工作条理清晰、编写容易。在计算时代的早期,程序员基于语句思考编程问题。到了20世纪七八十年代,程序员开始基于子程序去思考编程。进入21世纪,程序员以类为基础思考编程问题。而类是OOP中的核心组成元素,通常都是使用类来“封装”对象(属性、行为)。在经典图书代码大全里定义:“创建高质量的类,第一步

2、,可能也是最重要的一步,就是创建一个好的接口。这也包括了创建一个可以通过接口来展现的合理的抽象,并确保细节仍被隐藏在抽象背后。”为了更好的理解设计思想,本系列文章以简单的书店信息系统为例,但随着需求的增加,程序将越来越复杂。此时就有修改设计的必要,重构和设计模式就可以派上用场了。最后当设计渐趋完美后,你会发现,即使需求不断增加,你也可以神清气闲,不用为代码设计而烦恼了。在一个书店里,主要业务就是销售书,销售书后所得到的就是收取到的资金(本次交易金额),那以这个业务来分析,在不考虑设计的情况下,我们该怎么去实现:1namespace EBook.Step123/*/ <summary>

3、;4/ 会员购书5/ </summary>6public class Buy78/*/ <summary>9/ 处理销售书的方法10/ </summary>11public void Execute()1213Console.WriteLine("会员购买了一本书");141516/*/ <summary>17/ 买书得到了多少钱18/ </summary>19public void GetMoney()2021Console.WriteLine("收到了xx.xx元RMB");222324这是

4、针对书店的会员购书的业务逻辑,那如果是普通的顾客来购书呢?此时我们不得不为普通的顾客提供专门的服务(建立普通顾客业务逻辑类):1namespace EBook.Step123/*/ <summary>4/ 普通顾客购书5/ </summary>6public class SBuy78public void Execute()910Console.WriteLine("普通顾客购买了一本书");111213public void GetMoney()1415Console.WriteLine("收到了xx.xx元RMB");1617

5、18而客户端通过判断顾客的类型来决定调用具体的类来处理相应的操作:1namespace EBook.Step123class Program45static void Main(string args)67string uType = Console.ReadLine();8switch (uType)910case "会员": Member(); break;11case "普通顾客": General(); break;12131415private static void General()1617SBuy sbuy = new SBuy();18

6、sbuy.Execute();19sbuy.GetMoney();202122private static void Member()2324Buy buy = new Buy();25buy.Execute();26buy.GetMoney();272829仔细分析这段代码,虽然我们已经应用了OO的思想,将不同的顾客分为不同的对象来处理,但这样的设计同样很糟糕。也许你已经看出,这糟糕之处就是在switch这里。 不错,如果书店的客户不只是上述所提到的两种类型,还有如黄金会员,白金会员,白银会员,普通会员.等等一系列的划分,随着业务的扩展,将来会员类型也许还会不断的增加,那么就会去修改swit

7、ch不断的增加相应的会员处理逻辑,然后让switch子句越来越长,直至达到你需要无限的拉动滚动条才能看到switch的结束。如上设计的UML图如下:在上面的设计中,我们已经应用到了OO的思想,把不同个顾客类型做为一独立的对象来处理。仔细观察,会员(Buy)和普通顾客具有完全相同的方法,为什么不为它们建立一个共同的父类呢?通过共性的抽象,让会员和普通顾客都去继承并实现父类的抽象方法,那代码是这样的吗?1/*/ <summary>2/ 抽象出销售书的父类,所以的销售行为都继承于它。3/ </summary>4public abstract class Sell56/*/ &

8、lt;summary>7/ 处理销售书的方法8/ </summary>9public abstract void Execute();1011/*/ <summary>12/ 卖书得到了多少钱13/ </summary>14public abstract void GetMoney();1516-17/*/ <summary>18/ 会员购书19/ </summary>20public class Buy:Sell2122public override void Execute()2324Console.WriteLine(&q

9、uot;会员购买了一本书");252627public override void GetMoney()2829Console.WriteLine("收到了xx.xx元RMB");303132-33/*/ <summary>34/ 普通顾客购书35/ </summary>36public class SBuy:Sell3738public override void Execute()3940Console.WriteLine("普通顾客购买了一本书");414243public override void GetMon

10、ey()4445Console.WriteLine("收到了xx.xx元RMB");4647我们通过抽象,引用了继承的思想,使整个设计也有了OOP的味道。然而从现实生活中来分析,销售逻辑是一个抽象层,而我们所针对的是具体的顾客类型,出了在程序里应用多态特性,Sell类并没有实际使用的情况,这就是为何将其设计为抽象类及抽象方法,而不是使用普通的类里定义虚方法(virtual)的方式来实现。对应在设计中,就是:这个类永远不会被实例化,实例化的是它的子类。此时,客户端的调用可以直接依赖于抽象层(Sell),不过这样的设计实质并没有多大的变化,客户端还是需要通过判断决定该调用那一个

11、具体的实现。1public class Resolve23/*/ <summary>4/ /依赖于抽象5/ </summary>6/ <param name="sell"></param>7public void Execute(Sell sell)89sell.Execute();10sell.GetMoney();11121314namespace EBook.Step21516/依赖于抽象,有了继承,有了OO的味道。17class Program1819static void Main(string args)2021/

12、会员22new Resolve().Execute(new Buy();23Console.WriteLine("n-n");24/普通顾客25new Resolve().Execute(new SBuy();26272829这里我们先不谈客户端调用去判断顾客的类型。从现在的设计来看,即满足了类之间的层次关系,同时又保证了类的最小化原则,更利于扩展。即使你现在要增加如黄金会员(Gold)和白金会员(Platinum)等会员类型,只需要设计Gold和Platinum类,并继承Sell,重写Execute和GetMoney方法即可,而Resolve类对象的Execute方法根本

13、就不用改变。针对如上的设计来说,完全可以满足一个简单的销售逻辑的处理,可算是一个完美的设计。然而,在我们的实际项目中会有很多意想不到的事发生,其中需求变更应该是最为头疼的。刁钻的客户是永远不会满足的,这意味着我们就不能给我们的设计画上圆满的句号。时间久了,书店的一些书籍早已因陈旧而不能销售出去,可老板又不想让这些书成为废品,书无论是新还是旧都有他的价值所在,旧书的里的知识或许是不能与新版的书籍比配,但还是有一定的参考价值,就如我们去研究历史一样,是为了什么?是为了更好的迎接未来。书店的业务扩展,老板决定将陈旧的书籍用来出租(呵呵,这想法不错,满足了像我这样的穷人想看书可又没钱买书的XX,UPU

14、P.),根据我们上面在设计销售经验来看,那出租我们应该怎么来设计呢?是不是也应该把不同的对象做为的独立的逻辑来处理呢?答案是肯定的,那到底要怎么去设计呢,这要求我们深入到具体的业务逻辑了。通过分析现实中的业务逻辑,出租主要涉及到两个方面:租借和归还。而我们上面的设计中把顾客分为了会员和普通顾客两类,那么归还是不是应该划分为会员还书和普通顾客换书呢?这是肯定的,因为会员和普通顾客在租书的租金上是不一样的,会员和普通顾客在租金上应该是两种不同的策略。从上面的分析得出,出租主要分为租借、会员归还和普通顾客归还这三种类型的逻辑。而租书不用给租金但必须先交押金,还会则需要收取租金(可从押金中扣除)。也就

15、是说这三种类型里都回有处理出租(租借和归还)和交易金额的逻辑。既然都有共性,那也应该抽象出父类,是这样设计的吗?1namespace EBook.Step323/*/ <summary>4/ 作为租赁业务的一个基类,所以的租赁行为都继承于它。5/ </summary>6public abstract class Hire78/*/ <summary>9/ 处理租赁书的方法10/ </summary>11public abstract void Execute();1213/*/ <summary>14/ 租书所得到的租金15/ <

16、;/summary>16public abstract void GetMoney();1718我们来看看UML草图:1/*/ <summary>2/ 租书3/ 分析:租书的时候是不需要支付租金的,但是需要支付押金4/ </summary>5public class Rent:Hire67/*/ <summary>8/ 执行出租逻辑9/ </summary>10public override void Execute()1112Console.WriteLine("租出一本XXX书");131415/*/ <sum

17、mary>16/ 计算出租后所得到的租金17/ </summary>18public override void GetMoney()1920Console.WriteLine("得到了XX.XX元的租金");21221/*/ <summary>2/ 还书3/ 会员还书租金和普通顾客的租金有区别4/ </summary>5public class MBack:Hire67/*/ <summary>8/ 执行还书逻辑9/ </summary>10public override void Execute()111

18、2Console.WriteLine("会员还书");131415/*/ <summary>16/ 计算会员租书的租金17/ </summary>18public override void GetMoney()1920Console.WriteLine("会员租金打5折");21221/*/ <summary>2/ 普通顾客还书3/ </summary>4public class SBack:Hire56public override void Execute()78Console.WriteLine(&

19、quot;普通顾客还书");91011/*/ <summary>12/ 计算普通顾客租书的租金13/ </summary>14public override void GetMoney()1516Console.WriteLine("普通顾客租金打8折");1718此时,在Resolve类里就需要通过业务类型(销售或出租)、用户类型(会员或普通顾客)和出租类型(租借或归还)的不同层次的判断,然后去执行相应的具体逻辑实现。1public class Resolve23/*/ <summary>4/5/ </summary&g

20、t;6/ <param name="sType">销售类型</param>7/ <param name="uType">用户类型</param>8/ <param name="rType">出租类型</param>9public void Execute(string sType,string uType,string rType)1011switch (sType)1213case "销售": if (uType = "会员&quo

21、t;)1415Sell(new Buy();1617else1819Sell(new SBuy();20; break;21case "出租": if (rType = "租借")2223Hire(new Rent();2425else2627if (uType = "会员") Hire(new MBack();28else Hire(new SBack();29; break;30313233private void Sell(Sell sell)3435sell.Execute();36sell.GetMoney(); /本次交易

22、的金额373839private void Hire(Hire hire)4041hire.Execute();42hire.GetMoney();4344可以看到,上面的Resolve类里的方法定义特别的复杂,switch和if.else语句使整个设计显得太过迂腐,破坏了设计之美。这里需要怎么改善代码,使得干净利落呢?这里我们先不谈使用switch和if.else造成的迂腐设计,在后续文章里我会详细的介绍怎么搞定这个坏点。现在可以总结一下,从Resolve类的演变,我们可以得出这样一个结论:在调用类对象的属性和方法时,尽量避免将具体类对象作为传递参数,而应传递其抽象对象,更好地是传递接口,将

23、实际的调用和具体对象完全剥离开,这样可以提高代码的灵活性。如public void Sell(Sell sell);方法,我们就是使用的高层抽象Sell(销售行为的父类)作为参数类型,而在实际调用中则传递的是具体的实现子类。这种遵循依赖于抽象而不依赖于具体实现的设计原则,让设计更具灵活性。上述设计的UML草图如下:仔细观察会发现,Sell和Hire都具有相同的行为,这里我们完全可以在进一步的抽象,为这两个类定义一个统一的接口,详细本文就不做介绍,我已经把内容安排到下一篇文章里,大家可以关注本系列的后续文章。本文主要目的是讲述OOP的设计过程演化,在实例上没有做详细的业务逻辑处理;我相信看到我这

24、句话的朋友是认真的阅读完了本文的全部内容,通过对代码一步一步的修改重构,应用OOP的设计思想,抽象继承来演义OOP的设计过程,至于本文的价值所在,我想看过本文的朋友心里都有个数。应用OOP的设计过程演化(二)在我上篇文章应用OOP的设计过程演化(一) 里,结合了实例通过应用OOP和重构等技术,你已看到代码是怎样一步一步复活的。让最初死板的代码变得灵活、可扩展,设计的不断演化过程证实,代码一步一步的复活就如同给一只冻僵翅膀的小鸟带去温暖的阳光一样。上一篇文章虽然算得上是完美的演义了一个应用OOP的设计过程,但缺点也不少,可能因为这样给文章留下了败笔。那下面我们就来分析下这些不足之出。我们在设计中

25、为什么要不断的抽象,重构?因为最初的设计不可能是完美的,我们不能一下子就完全把各个对象、类、接口等角色的职责划分得清清楚楚,只有通过不断的对设计进行修改才能更进一步的分清各个角色的职责。“既然抽象销售业务的基类(Sel)l和租赁业务的基类(Hire)都具有相同的行为,这里我们完全可以在进一步的抽象,为什么不为这两个类定义一个统一的接口呢?”这是上一篇文章中留下的问题。是的,我们确实应该这么做:1/*/ <summary>2/ 系统总接口3/ </summary>4public interface IMoney56/*/ <summary>7/ 返回本次交易的

26、金额8/ </summary>9/ <returns></returns>10double GetMoney();1112/*/ <summary>13/ 执行某项特定操作(销售、出租、归还)14/ </summary>15/ <returns></returns>16string Execute();17此时,我们还需要修改Sell和Hire两个类,让其继承IMoney接口,如下UML图示:此时,客户端调用就可以直接依赖于最高层抽象IMoney接口,是不是到此就画上完美的句号了呢?事实并非我们所想的那么简单,

27、我们虽然已经抽象出了最高层次的接口,但是这样还是有所不足,那不足之处在哪里呢?解决这个问题之前我们先来分析下具体的业务逻辑。在一个书店的业务(不管是销售还是租借业务)里,只要存在业务关系,那就存在这这样的依赖,从第一篇文章(没有阅读过第一篇文章建议先阅读完第一篇文章:书店信息系统系列一-应用OOP的设计过程演化 )里的设计可以看出,每完成一笔业务交易,就会涉及到顾客类型(会员、普通顾客)、交易类型(出售、出租)、租借类型(租借、归还),我们还可以为书进行分类,比如生活类,小说类以及杂志等。既然有这样的关系存在,从设计上来说我们是不能在应用中强行来指定类型的,那应该怎么做呢?我们是不是应该对业务

28、类型进行封装?这里我采用枚举:1/*/ <summary>2/ 会员类型3/ </summary>4public enum U_Type56/*/ <summary>7/ 会员8/ </summary>9MEMBER,1011/*/ <summary>12/ 普通顾客13/ </summary>14SHOPPER151617/*/ <summary>18/ 书的类型19/ </summary>20public enum B_Type2122/*/ <summary>23/ 小说分类24/

29、 </summary>25NOVEL,2627/*/ <summary>28/ 生活百态29/ </summary>30LIFT,3132/*/ <summary>33/ 杂志34/ </summary>35MAGAZINE363738/*/ <summary>39/ 交易类型40/ </summary>41public enum S_Type4243/*/ <summary>44/ 出售45/ </summary>46SELL,4748/*/ <summary>49/ 出租

30、50/ </summary>51HIRE525354/*/ <summary>55/ 租借类型56/ </summary>57public enum H_Type5859/*/ <summary>60/ 租借61/ </summary>62RENT,6364/*/ <summary>65/ 归还66/ </summary>67BACK68对也类型进行封装后,我们在次进一步的分析具体的业务逻辑,在书店业务里,每次交易是不是还存在着书名、客户(顾客)名、书的定价以及顾客所支付的现金呢?然后这些属性都是任何一笔业务交

31、易都存在的,从对象的职责上来说,我们应该把这些属性建立在共性层次上,那是这样的吗?1public abstract class Root:IMoney23protected U_Type _uType; /会员类型4protected B_Type _bType; /书的类型5protected S_Type _sType; /交易类型67protected string _userName;/用户名8protected string _bookName;/书名9protected double _bookPrice; /书的定价10/实际支付现金,不管是租书还是还书还是买书,他都会涉及到最终

32、给了多少钱这个问题11protected double _bookCash;1213/*/ <summary>14/ 处理租赁或销售的操作15/ </summary>16/ <returns></returns>17public abstract string Execute();1819/*/ <summary>20/ 返回本次交易的金额21/ </summary>22/ <returns></returns>23public abstract double GetMoney();24从新建立了R

33、oot类,用来封装业务逻辑共享的属性,之前我们抽象出了最高层次的IMoney,Root除了封装属性外还应该具备共同的操作行为,而共同的行为已经定义在IMoney接口里,此时我们就可以一劳永逸地享受原有的设计了,只需要让Root继承于IMoney接口就OK。到此,系统的体系结构就算设计完成了应用体系设计完毕,那下面应该把全部精力投入到业务逻辑的分析上了。首先从销售逻辑出发,书店要销售出去一本书,那他首先要做的工作是什么?暴露书的属性:书名和定价还应该有买书的用户吧,其次还应该有客户所支付的现金。显然这些职责应该划分到销售书的父类(Sell)里,实际收取了多少钱这个还需要根据顾客的类型来决定具体采

34、用何种收费策略,具体的收费策略的职责应该是具体的业务对象(Buy和SBuy)来完成,Sell作为父类,他所承担的职责是封装具体业务对象的共同属性和行为。详细如下:1namespace EBook.Step423/*/ <summary>4/ 抽象出销售书的父类,所以的销售行为都继承于它。5/ </summary>6public abstract class Sell:Root78/*/ <summary>9/ 初始化该类10/ </summary>11/ <param name="userName">用户名<

35、/param>12/ <param name="bookName">书名</param>13/ <param name="bookPrice">书的定价</param>14public Sell(string userName, string bookName, double bookPrice)1516_userName = userName;17_bookName = bookName;18_bookPrice = bookPrice;192021外露属性(用户名、书名、定价)#region 外露

36、属性(用户名、书名、定价)2223/*/ <summary>24/ 获取用户名称25/ </summary>26public string UserName2728get return _userName; 293031/*/ <summary>32/ 获取书名33/ </summary>34public string BookName3536get return _bookName; 373839/*/ <summary>40/ 获取书的定价41/ </summary>42public double BookPrice4

37、344get return _bookPrice; 454647/*/ <summary>48/ 实际支付现金49/ </summary>50public double BookCash5152get return _bookCash; 53set _bookCash = value; 5455#endregion5657实现基类中的抽象方法以及将任务分派到下面的派生类去#region 实现基类中的抽象方法以及将任务分派到下面的派生类去58/*/ <summary>59/ 实现基类的抽象方法,但是考虑到还需要再下级的派生类来完成60/ 所以我们选择让他调用其

38、他能够被派生类修改的方法61/ </summary>62/ <returns></returns>63public override string Execute()6465return TExecute();666768public override double GetMoney()6970return TGetMoney();7172#endregion7374/*/ <summary>75/ 处理销售书的方法76/ </summary>77public abstract string TExecute();7879/*/ &l

39、t;summary>80/ 返回本次交易的金额81/ </summary>82public abstract double TGetMoney();838485抽象业务层之下的具体业务对象,他门的职责就是完成具体的业务,根据我们之前的体系设计来分析,抽象销售业务(Sell)下有两个具体的业务对象(会员购书Buy和普通顾客购书SBuy),深入到具体的业务对象领域,之前我们为书分类了,那用户在购买书的时候在收费策略上肯定会判断书的类型,书的类型属性我们已经在抽象层Root里定义,这里我们只需要给他初始化下值就可以了(通过构造方法):1/*/ <summary>2/3/

40、 </summary>4/ <param name="bType">书的类型</param>5/ <param name="userName">用户名</param>6/ <param name="bookName">书名</param>7/ <param name="bookPrice">书的定价</param>8public Buy(B_Type bType, string userName, strin

41、g bookName, double bookPrice)9: base(userName, bookName, bookPrice)1011_bType = bType;12下面是具体的逻辑行为:1/*/ <summary>2/ 根据书的类型来定折扣3/ 当然,这里的折扣本来是应该从数据库或者配置文件中取的,我们演示就固化到这里。4/ </summary>5/ <returns></returns>6public override double TGetMoney()78switch (_bType)910case B_Type.NOVEL:

42、BookCash = BookPrice * 0.9;11break;12case B_Type.LIFT: BookCash = BookPrice * 0.7;13break;14case B_Type.MAGAZINE: BookCash = BookPrice * 0.8;15break;1617return BookCash;181920/*/ <summary>21/ 执行插入数据库的操作,但是我们这里不需要,只要把结果显示出来22/ 所以我们让他给我们返回一句话就OK了。23/ </summary>24/ <returns></retur

43、ns>25public override string TExecute()2627return string.Format("尊敬的会员:0,您购买1,定价为:2元,折扣后为:3元",28UserName, BookName, BookPrice, BookCash);29普通顾客的逻辑于会员的逻辑差不多,只是在收费的策略上有所不同,主要体现在折扣上。1/*/ <summary>2/ 普通顾客购书3/ </summary>4public class SBuy:Sell56public SBuy(B_Type bType, string use

44、rName, string bookName, double bookPrice)7: base(userName, bookName, bookPrice)89_bType = bType;101112public override double TGetMoney()1314switch (_bType)1516case B_Type.NOVEL: BookCash = BookPrice * 0.8;17break;18case B_Type.LIFT: BookCash = BookPrice * 0.4;19break;20case B_Type.MAGAZINE: BookCash

45、 = BookPrice;/不打折21break;2223return BookCash;242526public override string TExecute()2728return string.Format("尊敬的顾户:0,您购买1,定价为:2元,折扣后为:3元",29UserName, BookName, BookPrice, BookCash);3031此时的结构体系就应该是这样的:销售业务分析完毕,接下来我们来看看租借业务的实现。在租借业务里存在着两种业务三个业务对象:出租,归还(会员和普通顾客),首先来分析出租的业务逻辑,我们回想到现实生活中的租书业务,

46、租书的时候是不需要支付租金的,但是需要支付押金,而收取押金需要根据租借时间(天数)来计算。也就是说,在租借业务里出了从继承体系中继承而来的属性外,我们不得不在另外添加两个属性:租借天数和所交押金;这是租借(出租和归还)业务所共有的:1private int _day;2private double _deposit; 同样,我们还得对外暴露属性,包括用户名、书名、定价、租借天数、押金和实收现金:1/*/ <summary>2/ 用户名3/ </summary>4public string UserName56get return _userName; 789/*/ &l

47、t;summary>10/ 书名11/ </summary>12public string BookName1314get return _bookName; 151617/*/ <summary>18/ 书的定价19/ </summary>20public double BookPrice2122get return _bookPrice; 232425/*/ <summary>26/ 租借天数27/ </summary>28public int Day2930get return _day; 31set _day = val

48、ue; 323334/*/ <summary>35/ 押金36/ </summary>37public double Deposit3839get return _deposit; 40set _deposit = value; 414243/*/ <summary>44/ 实收现金45/ </summary>46public double BookCash4748get return _bookCash; 49set _bookCash = value; 50在具体的业务行为上和销售行为没有什么区别,详细定义如下:1实现基类中的抽象方法以及将任

49、务分派到下面的派生类去#region 实现基类中的抽象方法以及将任务分派到下面的派生类去3/*/ <summary>4/ 实现基类的抽象方法,但是考虑到还需要再下级的派生类来完成5/ 所以我们选择让他调用其他能够被派生类修改的方法6/ </summary>7/ <returns></returns>8public override string Execute()910return TExecute();111213public override double GetMoney()1415return TGetMoney();1617#endre

50、gion1819/*/ <summary>20/ 处理租赁书的方法21/ </summary>22public abstract string TExecute();2324/*/ <summary>25/ 返回本次交易的金额26/ </summary>27public abstract double TGetMoney();实现基类的抽象方法,但是考虑到还需要再下级的派生类来完成,所以我们选择让他调用其他能够被派生类修改的方法,这也就把具体的逻辑派生到具体的业务对象去实现了,这里的具体业务对象也就是租借业务对象(Rent)、会员归还业务对象(M

51、Back)和普通顾客归还业务对象(SBack)。租借业务对象(Rent):1namespace EBook.Step423/*/ <summary>4/ 租书5/ 分析:租书的时候是不需要支付租金的,但是需要支付押金6/ </summary>7public class Rent:Hire89/*/ <summary>10/ 初始化该类11/ </summary>12/ <param name="userName">用户名</param>13/ <param name="bookName">书名</param>14/ <param name="bookPrice">书的定价</param>15/ <param name="deposit">押金</param>16/ <param name="bookCash">实际支付<

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论