软件构造考试重点
文章目录
重点:模式和原则(策略模式,迭代器模式,工厂模式,适配器模式,面向对象的设计原则【满不满足····原则,为什么?】),增量开发模型,UML类图(各种依赖关系,解释UML图表示的设计,画UML类图),JDBC(步骤,增删改查语句,加载驱动),GUI()
第一章 软件开发概述
程序与软件构造
- 什么是程序?> 程序是为了解决某个特定问题而用程序设计语言描述的适合计算机处理的语句序列。
- 什么是软件?> 软件是能够完成预定功能和性能的可执行的程序和使程序正常执行所需要的数据,加上描述软件开发过程及其管理、程序的操作和使用的有关文档,即“软件=程序+数据+文档”。
- 软件按功能划分为三种类型:、__、____。> 软件按功能划分为三种类型:系统软件、支撑软件和应用软件。
- 软件按工作方式划分为:、、******、******_。> 软件按工作方式划分为:实时处理软件、分时软件、交互式软件和批处理软件。
- 软件按服务对象的范围划分为_______、______> 软件按服务对象的范围划分为:项目软件(定制开发)和产品软件(或通用软件)。
- 程序设计的活动包括___、、、________、________等不同阶段。> 程序设计的活动包括分析、设计、编码、测试、排错等不同阶段。
- 图灵奖获得者________提出的________________是程序设计的精辟观点。> 沃斯 “程序=算法+数据结构”
- 程序设计的核心__________________________________________________。> 程序设计的核心就是选择和设计适合特定问题的数据结构与算法,用编程语言编制为程序。
- 软件开发不只是纯粹的程序的功能设计,还包括________、___________ 、___________ 、____________ 和 ___________ 。> 数据库设计、用户界面设计、软件接口设计、通用协议设计和复杂的系统配置。
- 什么是软件工程?> 软件工程是应用计算机科学、数据、逻辑学及管理科学等原理,开发软件的工程学科和活动。
软件生存周期
- 什么是软件生存周期?> 软件生存周期是指从形成开发软件概念起,所开发的软件使用以后,直到失去使用价值消亡为止的整个过程。
- 从用户的角度,软件生存周期分为哪几个阶段?> 分为三个阶段:提出需求、获取软件和使用软件
- 从开发者的角度,软件生存周期分为哪几个阶段?> 主要包括需求阶段、设计阶段、实现阶段、测试阶段,有时还包括安装阶段。
- 软件实现与通常的程序设计的主要区别是什么?> 软件实现与程序设计主要区别是软件的集成与测试。
软件开发过程(重点)
- 瀑布式开发过程把开发分为______、___________ 、____________ 、___________ 、___________、___________这6个基本活动。> 制定计划、需求分析、软件设计、程序编写、软件测试和运行维护
- 瀑布模型的核心思想是什么?> 按工序将问题化简,将功能的实现与设计分开,便于分工协作。
- 瀑布模型的主要问题是什么?> 1. 阶段划分僵硬,每个阶段都不能缺省,而且产生大量文档,增加了工作量。> 2. 开发是线性的,只有等到整个过程的末期才能见到开发成功——可运行软件,不利于快速响应变化的需求。> 3. 早期的错误要等到开发后期的测试阶段才能实现,可能带来严重的后果,增加了开发的风险。> 4. 瀑布模型的突出缺点是不适应用户需求的变化。
- 能够分析具体的案例,来进行判断软件开发需要使用哪种开发模型更为合适,并能给出理由> 瀑布式开发模型和增量开发模型(常答下面的特点,优点)。
- 什么是增量模型> 增量模型也称渐增模型。使用增量模型开发软件时,把软件产品作为一系列的增量构件来设计、编码、集成和测试。每个构件由多个相互作用的模块构成,并且能够完成特定的功能> > 使用增量模型时,第一个增量构件往往实现软件的基本需求,提供最核心的功能> > 把软件产品分解成增量构件时,唯一必须遵守的约束条件是,当把新构件集成到现有构件中时,所形成的产品必须是可测试的
- 增量模型特点==(重点)==> 把瀑布模型的顺序特征与快速原型法的迭代特征相结合> > 将软件看作一系列相互联系的增量,在开发过程的各次迭代中,每次完成其中的一个增量
- 增量模型优缺点==(重点)==> 优点> > > 1. 能在较短的时间内向用户提交可完成部分工作的产品> 2. 将待开发的软件系统模块化,可以分批次地提交软件产品,使用户可以及时了解软件项目的进展> 3. 以组件为单位进行开发降低了软件开发的风险。一个开发周期内的错误不会影响到整个软件系统> 4. 开发顺序灵活。开发人员可以对组件的实现顺序进行优先级排序,先完成需求稳定的核心组件。当组件的优先级发生变化时,还能及时地对实现顺序进行调整> > 缺点> > > 1. 由于各个构件是逐渐并入已有的软件体系结构中的,所以加入构件必须不破坏已构造好的系统部分,这需要软件具备开放式的体系结构> 2. 在开发过程中,需求的变化是不可避免的。增量模型的灵活性可以使其适应这种变化的能力大大优于瀑布模型和快速原型模型,但也很容易退化为边做边改模型,从而是软件过程的控制失去整体性> 3. 如果增量包之间存在相交的情况且未很好处理,则必须做全盘系统分析,这种模型将功能细化后分别开发的方法较适应于需求经常改变的软件开发过程。
- 增量模型作用==(重点)==> 1. 开发初期的需求定义只是用来确定软件的基本结构,使得开发初期用户只需要对软件需求进行大概的描述;而对于需求的细节性描述,则可以延迟到增量构件开发时进行,以增量构件为单位逐个地进行需求补充。这种方式能够有效适应用户需求的变更> 2. 软件系统可以按照增量构件的功能安排开发的优先顺序,并逐个实现和交付使用。不仅有利于用户尽早用上系统,能够更好地适应新的软件环境,而且在以增量方式使用系统的过程中,还能获得对软件系统后续构件的需求经验> 3. 软件系统是逐渐扩展的,因此开发者可以通过对诸多构件的开发,逐步积累开发经验。实际上,增量式开发还有利于技术复用,前面构件中设计的算法、采用的技术策略、编写的源码等,都可以应用到后面将要创建的增量构件中去> 4. 增量式开发有利于从总体上降低软件项目的技术风险。个别的构件或许不能使用,但一般不会影响到整个系统的正常工作> 5. 实际上,在采用增量模型时,具有最高优先权的核心增量构件将会被最先交付,而随着后续构件不断被集成进系统,这个核心构件将会受到最多次数的测试。这意味着软件系统最重要的心脏部分将具有最高的可靠性,这将使得整个软件系统更具健壮性。
敏捷开发
- 什么是敏捷开发> 以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。
- 敏捷开发的优点> 1. 为项目提供了按阶段划分的检查点。> 2. 当前一阶段完成后,您只需要去关注后续阶段。> 3. 它提供了一个模板,这个模板使得分析、设计、编码、测试和支持的方法可以在该模板下有一个共同的指导。
- 敏捷开发的4个核心价值观?> 1. 个体和互动胜过流程和工具。> 2. 工作的软件胜过详尽的文档。> 3. 客户合作胜过合同谈判。> 4. 响应变化胜过遵循计划。
- 敏捷开发方法需遵循的12条原则?
- 什么是意图导向编程?> 先假设当前这个对象中已经有了一个理想的方法,他可以准确无误地完成想做的事情,而不是直接盯着每一点要求来编写代码。
软件构造、为什么不直接编写软件
- 什么是软件构造?> 软件构造指的是运用软件最佳时间,通过设计、编码和测试的迭代过程,增量地建造出可运行软件。
- 按照语言的计算模型可以将高级语言划分为___和____两大类。> 声明式和命令式两大类
- 按照语言的转换和执行方式高级语言分为___和____ 。> 编译型语言和解释型语言
第三章 面向对象的软件构造
知识点
- 继承关系
- 继承指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力。在Java中继承关系通过关键字extends明确标识,在设计时一般没有争议性。在UML类图设计中,继承用一条带空心三角箭头的实线表示,从子类指向父类,或者子接口指向父接口。
- 实现关系 - 实现指的是一个class类实现interface接口(可以是多个)的功能,实现是类与接口之间最常见的关系。在Java中此类关系通过关键字implements明确标识,在设计时一般没有争议性。在UML类图设计中,实现用一条带空心三角箭头的虚线表示,从类指向实现的接口。
- 依赖关系 - 简单的理解,依赖就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性的、临时性的、非常弱的,但是类B的变化会影响到类A。比如某人要过河,需要借用一条船,此时人与船之间的关系就是依赖。表现在代码层面,为类B作为参数被类A在某个method方法中使用。在UML类图设计中,依赖关系用由类A指向类B的带箭头虚线表示。
- 关联关系 - 关联体现的是两个类之间语义级别的一种强依赖关系,比如我和我的朋友,这种关系比依赖更强、不存在依赖关系的偶然性、关系也不是临时性的,一般是长期性的,而且双方的关系一般是平等的。关联可以是单向、双向的。表现在代码层面,为被关联类B以类的属性形式出现在关联类A中,也可能是关联类A引用了一个类型为被关联类B的全局变量。在UML类图设计中,关联关系用由关联类A指向被关联类B的带箭头实线表示,在关联的两端可以标注关联双方的角色和多重性标记。
- 聚合关系 - 聚合是关联关系的一种特例,它体现的是整体与部分的关系,即has-a的关系。此时整体与部分之间是可分离的,它们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享。比如计算机与CPU、公司与员工的关系等,比如一个航母编队包括海空母舰、驱护舰艇、舰载飞机及核动力攻击潜艇等。表现在代码层面,和关联关系是一致的,只能从语义级别来区分。在UML类图设计中,聚合关系以空心菱形加实线箭头表示。
- 组合关系 - 组合也是关联关系的一种特例,它体现的是一种contains-a的关系,这种关系比聚合更强,也称为强聚合。它同样体现整体与部分间的关系,但此时整体与部分是不可分的,整体的生命周期结束也就意味着部分的生命周期结束,比如人和人的大脑。表现在代码层面,和关联关系是一致的,只能从语义级别来区分。在UML类图设计中,组合关系以实心菱形加实线箭头表示。
解释UML图表示的设计(其含义),说出图中各类之间的关系。(重要)
机械设计师、电气工程师和软件工程师都属于员工,他们组成一个飞机建造团队。飞机由零件组成,零件还可以(递归)有零件。
什么是依赖倒转原则
- 高层模块不应该依赖低层模块,二者都应该依赖其抽象。
- 抽象不应该依赖细节,细节应该依赖抽象。
- 依赖倒转的中心思想是面向接口编程。
- 依赖倒转的设计理念为:相对于细节的多变性,抽象的东西要稳定的多。以抽象的基础搭建的架构比以细节为基础的架构要稳定的多。在java中,抽象指的是接口或抽象类,细节就是具体的实现类。
- 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
面向对象的设计符号
“+”表示公用的,“-”表示私有的,“#”表示保护的。静态变量或常量用大写字母的标识符。
- 继承(extends)- 子类继承父类- 表示方式: 带三角箭头的实线空心三角形,箭头指向父类- 人继承动物的相关特性
- 实现(implements)- 类对接口的实现关系- 表示方式: 带三角箭头的虚线,箭头指向接口- 人实现IFly接口,拥有飞翔能力1. 关联关系- 是一种拥有的关系,它使一个类知道另一个类的属性和方法,当一个类‘知道’另一个类时,我们可以说它们之间相互关联;- 双向关联:可以有两个箭头或者没有箭头(不推荐);- 单向关联:有一个箭头,且箭头方向指向被关联的对象;- 表示方式: 实线箭头,且箭头指向被拥有者- 例子:如PeopleA了解天气变化2. 聚合关系- 一种弱的‘拥有’关系,体现的是 A 对象可以包含 B 对象,但 B 对象不是 A 对象的一部分;- 整体与部分的关系,如文学俱乐部全体成员与文学俱乐部成员- 表示方式: 带空心菱形的实心线,菱形指向整体- 例子:文学俱乐部全体成员与文学俱乐部成员注意关联关系和聚合关系的不同点:- 关联关系所涉及的两个类处于同一个层次上;- 聚合关系所涉及的两个类处于不平等的层次上(一个代表整体,一个代表部分)3. 合成关系- 一种强的‘拥有’关系,体现了部分与整体的关系,它们拥有相同的生命周期- 表示方式: 带实心菱形的实线,菱形指向整体- 例子:人由头、手等其它部分组成4. 依赖关系- 依赖是单向的,通常以方法参数的形式、局部变量的形式,及对静态方法调用的形式出现- 表示方式: 虚线箭头来表示- 例子:动物依赖水,没有水就会失去生命各关系的强弱顺序 继承=实现>组合>聚合>关联>依赖(18条消息) 设计模式之基础篇UML(类图)_u012551350的博客-CSDN博客_uml数据结构 https://blog.csdn.net/u012551350/article/details/52529931
策略模式(重要,待补充)
跟不同类型的 MM 约会,要用不同的策略,有的请电影比较好,有的则去吃小吃效果不错,有的去海边浪漫最合适,单目的都是为了得到 MM 的芳心,我的追 MM 锦囊中有好多 Strategy 哦。
策略模式:策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。
策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开来,算法的增减,修改都不会影响到环境和客户端。
迭代器模式(重要,待补充)
提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示.
迭代模式:迭代模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集,聚集对象是能够包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中,从而与聚集本身隔开。
迭代模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。
面向对象的设计原则(重要)
面向对象的5个基本原则:
- 单一职责原则:一个类只有一种单一功能,不要实现过多的功能。该原则可以视为面向对象程序对
低耦合、高内聚原则
的实践- 开放封闭原则:软件实体应该可以扩展,但是不可修改。对外扩展开放,对修改封闭,是面对相对所有原则的核心。继承相关,增加新功能,就增加基类。
- 依赖倒转原则:抽象不应该依赖细节,细节应该依赖于抽象。低层的子类依赖高层的、抽象的父类;高层模块定义接口,低层模块负责实现。
- 里氏代换原则:子类型必须能够替换他们的基类型。这一思想体现了对继承机制的约束规范,保证继承复用的基础。子类是否合理,比如鸡类不属于鸟类
- 接口隔离原则:不应该强迫客户依赖于他们不用的方法。基类最小化,功能最小化
- 迪米特法则:尽量减少类之间的依赖关系,最直接的实现就是在两个类之间创建一个中间类。
- 合成复用原则:尽量使用聚合、组合关系。设计模式-七大原则(图解一目了然)
题目
- 运用面向对象方法设计软件,并用UML表示类之间的关系:一个网上购物系统,客户(Customer)可以从商品目录(Category)中浏览商品(Item),把挑选的商品放进购物车(shopping_cart),并且可以说明同一商品的数量。如果不如意,也可以随时从购物车拿出一件或若干商品。客户付款(Payment)时,系统计算购物车中所有商品的价格,客户选择E-bao、Band_card或货到付款(Cash)等付款方式。系统根据付款方式和金额为客户增加积分(Reward),并根据年度消费总金额把客户划分成三类:Type_A、Type_B和Type_C,以便提供针对性的服务和营销。客户能浏览自己的积分、一年采购的所有商品,但是不知道自己在网站的客户分类。
- 解释下面用UML类图表示的设计
第七章 GUI软件构造
设计原则
设计原则:
1、关注用户及任务,而不是技术
2、首先考虑功能,然后才是表示
3、对人物的看法与用户保持一致
4、设计要符合常见情况
5、不要分散用户对目标的注意力
6、促进学习
7、传递信息,而不仅仅数据数据
8、设计应满足相应需求
9、通过用户试一下 是用试用发现并改正错误
第八章 应用数据库
JDBC 的使用(重要)
流程
- 注冊驱动 (仅仅做一次)
Class.forName("com.mysql.jdbc.Driver");
- 建立连接(Connection)
Connection conn = DriverManger.getConnection(url,account,password);
- 创建传输器Statement
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY);
- 运行SQL语句
ResultSet rs = stmt.executeUpdate(sql);
- 处理运行结果(ResultSet)
rs.getString('');/rs.getString(1);
- 释放资源
rs.close();``````stmt.close();``````conn.close();
代码
importjava.sql.*;// 加载驱动Class.forName("com.mysql.jdbc.Driver");// 数据库地址、账号、密码String url ="jdbc:mysql://IpAddress:3306/DataBaseName";String account ="XX";String password ="XX";Connection conn;Statement stmt;ResultSet rs;try{// 创建Connection对象
conn =DriverManager.getConnection(url,account,password);
stmt =conn.CreatStatement();String sql ="select/insert/update/delete";
rs = stmt.executeQuery(sql);// Boolean flag = stmt.executeUpdate(sql);while(rs.next()){System.out.println(rs.getString(1)+""+ rs.getString(2)+"");}
rs.close();
stmt.close();
conn.close();}catch(Exception e){
e.printStackTrace();}
Statement属性
属性 含义ResultSet.TYPE_FORWARD_ONLY表示结果集只能向下滚动ResultSet.TYPE_SCROLL_INSENSITIVE表示结果集的游标可以上下滚动,当数据库变化时,当前结果集不变ResultSet.TYPE_SCROLL_SENSITIVE表示结果集的游标可以上下滚动,当数据库变化时,当前结果集同时改变ResultSet.CONCUR_READ_ONLY不能用结果集更新数据库中的表ResultSet.CONCUR_UPDATABLE可以用结果集更新数据库中的表
倒序输出数据库表中的数据
importjava.sql.*;publicclassConn{publicstaticvoidmain(String[] args)throwsClassNotFoundException{Class.forName("com.mysql.jdbc.Driver");Connection conn;Statement stmt;ResultSet rs;String sql ="select * from info";ResultSetMetaData rsmd;int columnCount;//ResultSet的总列数try{
conn =DriverManager.getConnection("jdbc:mysql://121.36.86.90/train","XX","XX");
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
rs = stmt.executeQuery(sql);
rsmd = rs.getMetaData();
columnCount = rsmd.getColumnCount();
rs.last();
rs.afterLast();while(rs.previous()){// 当rs.getString不为空时for(int i =1; i < columnCount +1; i++){System.out.print(rs.getString(i)+" ");}System.out.println();}
rs.close();
stmt.close();
conn.close();}catch(SQLException e){
e.printStackTrace();}}}
语句(重要)
创建表语句
CREATETABLE QUESTION(
QuestionID VARCHAR(9),
Factor1 INT,
Operator VARCHAR(2),
Factor2 INT,
Result INT,
CategoryID VARCHAR(9));
插入语句
INSERTINTO<表名>(<属性列1>,<属性列2>)VALUES(<常量1>,<常量2>);
删除语句
DELETEFROM Question
WHERE CategoryID =(Select CategoryID FROM Category where Name ='Top');
更新语句
UPDATE Question
SET Operator ='*'WHERE CategoryID =(SELECT CategoryID
FROM Category
WHERE Name ='Junior');
查询语句
SELECT Factor1,Operator,Factor2,Result
FROM Question
WHERE Operator ='+'AND Result<50;
一些问题 (待补充)
- 有哪些常用的数据库管理系统?简要介绍一个你比较熟悉的数据库管理系统。如果要访问其他数据库管理系统,需要对项目进行哪些修改?> MySQL、Oracle、DB2、SQL server。> > MySQL 是一款安全、跨平台、高效的,并与 PHP、Java 等主流编程语言紧密结合的数据库系统。> > 修改:驱动,jar包,url,账号,密码,sql语句
- 查询数据库数据和删除数据库数据调用的方法相同吗?如果不同,其返回值各有什么作用?> 不相同> > 查询:executeQuery方法的返回该查询生成的 ResultSet 对象。> > 删除:executeUpdate 方法的返回值是一个整数,指示受影响的行数(即更新计数)> > execute方法
- 假如数据表user的字段为name1、password,新注册用户的姓名为Tomcat,密码为12356,试写出将该用户信息写入数据库的核心代码。访问数据库时,JDBC能完成哪些工作?要利用JDBC访问数据库,程序员通常遵循的基本流程是什么?
第九章 基于复用的软件构造
复用
什么是软件复用
软件复用是指在两次或者多次不同软件开发过程中重复使用相同或相近的软件或软件模块的过程。
软件复用的优点
- 提高生产率。软件开发生产率的提高体现在软件开发的各个阶段。使用经过实践检验、高度优化的可复用件构造系统,还可以提高系统的性能和可靠性。
- 减少维护代价。由于使用经过检验的软构件,减少了可能的错误;同时由于复用的增加,软件中需要维护的部分也减少了。
- 提高互操作性。通过使用接口的同一个实现,系统将更有效地实现与其他系统之间的互操作。
- 支持快速原型。利用软构件库可以快速有效地构造出应用程序的原型。
复用哪些东西
软件产品的复用包括代码、设计、测试数据和需求规格书等。
工厂模式
工厂顾名思义就是创建产品,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式。该模式用于封装和管理对象的创建,是一种创建型模式。
使用工厂模式的场合及益处:
- 平行连接类的层次结构
- 一个类想让其子类说明对象
- 一个类不预计子类,但必须创建子类
- 一簇对象需要用不同的接口分隔开
- 代码要处理接口而不是实现的类
- 连接子类的方式比直接创建对象更加灵活
- 对客户隐藏具体的类
工厂模式的核心思想是:有一个专门的类来负责创建实例的过程。他把产品视为一系列的类的集合,这些类是由某个抽象类或接口派生出来的一个对象树。
简单工厂模式(违反开闭原则,继承相关,增加新功能,就增加基类。)
该模式对对象创建管理方式最为简单,因为其仅仅简单的对不同类对象的创建进行了一层薄薄的封装。该模式通过向工厂传递类型来指定要创建的对象,其UML类图如下:
\\ Phone类:手机标准规范类(AbstractProduct)publicinterfacePhone{voidmake();}
\\ MiPhone类:制造小米手机(Product1)
publicclassMiPhoneimplementsPhone{publicMiPhone(){this.make();}@Overridepublicvoidmake(){// TODO Auto-generated method stubSystem.out.println("make xiaomi phone!");}}
\\ IPhone类:制造苹果手机(Product2)
publicclassIPhoneimplementsPhone{publicIPhone(){this.make();}@Overridepublicvoidmake(){// TODO Auto-generated method stubSystem.out.println("make iphone!");}}
\\ PhoneFactory类:手机代工厂(Factory)
publicclassPhoneFactory{publicPhonemakePhone(String phoneType){if(phoneType.equalsIgnoreCase("MiPhone")){returnnewMiPhone();}elseif(phoneType.equalsIgnoreCase("iPhone")){returnnewIPhone();}returnnull;}}publicclassDemo{publicstaticvoidmain(String[] arg){PhoneFactory factory =newPhoneFactory();Phone miPhone = factory.makePhone("MiPhone");// make xiaomi phone!IPhone iPhone =(IPhone)factory.makePhone("iPhone");// make iphone!}}
优缺点:
- 优点 - 将对象的创建交给专门的工厂类负责,实现了对象的创建和对象的使用分离。
- 缺点 - 工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码- 违反开闭原则,继承相关,增加新功能,就增加基类。
工厂方法模式
和简单工厂模式中工厂负责生产所有产品相比,工厂方法模式将生成具体产品的任务分发给具体的产品工厂,其UML类图如下:
也就是定义一个抽象工厂,其定义了产品的生产接口,但不负责具体的产品,将生产任务交给不同的派生类工厂。这样不用通过指定类型来创建对象了。
// AbstractFactory类:生产不同产品的工厂的抽象类publicinterfaceAbstractFactory{PhonemakePhone();}// XiaoMiFactory类:生产小米手机的工厂(ConcreteFactory1)publicclassXiaoMiFactoryimplementsAbstractFactory{@OverridepublicPhonemakePhone(){returnnewMiPhone();}}// AppleFactory类:生产苹果手机的工厂(ConcreteFactory2)publicclassAppleFactoryimplementsAbstractFactory{@OverridepublicPhonemakePhone(){returnnewIPhone();}}
\\ Phone类:手机标准规范类(AbstractProduct)publicinterfacePhone{voidmake();}
\\ MiPhone类:制造小米手机(Product1)
publicclassMiPhoneimplementsPhone{publicMiPhone(){this.make();}@Overridepublicvoidmake(){// TODO Auto-generated method stubSystem.out.println("make xiaomi phone!");}}
\\ IPhone类:制造苹果手机(Product2)
publicclassIPhoneimplementsPhone{publicIPhone(){this.make();}@Overridepublicvoidmake(){// TODO Auto-generated method stubSystem.out.println("make iphone!");}}// Main类publicclassDemo{publicstaticvoidmain(String[] arg){AbstractFactory miFactory =newXiaoMiFactory();AbstractFactory appleFactory =newAppleFactory();
miFactory.makePhone();// make xiaomi phone!
appleFactory.makePhone();// make iphone!}}
优缺点:
- 优点 - 遵循了开闭原则,扩展性极强。
- 缺点 - 增加了类的数量,当有成千上万个类型的产品时,就需要有成千上万个工厂类来生产这些产品。
抽象工厂模式
上面两种模式不管工厂怎么拆分抽象,都只是针对一类产品Phone(AbstractProduct),如果要生成另一种产品PC,应该怎么表示呢?
最简单的方式是把2中介绍的工厂方法模式完全复制一份,不过这次生产的是PC。但同时也就意味着我们要完全复制和修改Phone生产管理的所有代码,显然这是一个笨办法,并不利于扩展和维护。
抽象工厂模式通过在AbstarctFactory中增加创建产品的接口,并在具体子工厂中实现新加产品的创建,当然前提是子工厂支持生产该产品。否则继承的这个接口可以什么也不干。
其UML类图如下:
从上面类图结构中可以清楚的看到如何在工厂方法模式中通过增加新产品接口来实现产品的增加的。
接下来我们继续通过小米和苹果产品生产的例子来解释该模式。
为了弄清楚上面的结构,我们使用具体的产品和工厂来表示上面的UML类图,能更加清晰的看出模式是如何演变的:
\\ PC类:定义PC产品的接口(AbstractPC)publicinterfacePC{voidmake();}
\\ MiPC类:定义小米电脑产品(MIPC)publicclassMiPCimplementsPC{publicMiPC(){this.make();}@Overridepublicvoidmake(){// TODO Auto-generated method stubSystem.out.println("make xiaomi PC!");}}
\\ MAC类:定义苹果电脑产品(MAC)publicclassMACimplementsPC{publicMAC(){this.make();}@Overridepublicvoidmake(){// TODO Auto-generated method stubSystem.out.println("make MAC!");}}
\\ AbstractFactory类:增加PC产品制造接口
publicinterfaceAbstractFactory{PhonemakePhone();PCmakePC();}
\\ XiaoMiFactory类:增加小米PC的制造(ConcreteFactory1)
publicclassXiaoMiFactoryimplementsAbstractFactory{@OverridepublicPhonemakePhone(){returnnewMiPhone();}@OverridepublicPCmakePC(){returnnewMiPC();}}
\\ AppleFactory类:增加苹果PC的制造(ConcreteFactory2)
publicclassAppleFactoryimplementsAbstractFactory{@OverridepublicPhonemakePhone(){returnnewIPhone();}@OverridepublicPCmakePC(){returnnewMAC();}}
\\ Main类
publicclassDemo{publicstaticvoidmain(String[] arg){AbstractFactory miFactory =newXiaoMiFactory();AbstractFactory appleFactory =newAppleFactory();
miFactory.makePhone();// make xiaomi phone!
miFactory.makePC();// make xiaomi PC!
appleFactory.makePhone();// make iphone!
appleFactory.makePC();// make MAC!}}
优缺点:
- 优点 - 增加固定类型产品的不同具体工厂比较方便。
- 缺点 - 类图优点复杂,可读性没有工厂方法模式那么好。
适配器模式
举例:某OA系统需要提供一个加密模块,将用户机密信息(如:用户口令、邮箱等)加密之后再存储到数据库中,系统已经定义好了数据库操作类。为了提高开发效率,系统需要重用已有的加密算法,这些算法封装在一些由第三方提供的类中,有些甚至没有源代码,试用适配器模式设计该加密模块,实现在不修改现有类的基础上重用第三方的加密方法。
适配器(变压器)模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。
publicclassAdapterPattern{publicstaticvoidmain(String[] args){System.out.println(newAdapter(newSpeaker()).translate());}}classSpeaker{publicStringspeak(){return"China No.1";}}interfaceTranslator{publicStringtranslate();}classAdapterimplementsTranslator{privateSpeaker speaker;publicAdapter(Speaker speaker){this.speaker = speaker;}@OverridepublicStringtranslate(){String result = speaker.speak();return result;}}
适配器模式适合下面场合:
- 想使用一个已经存在的类,而它的接口不符合目前的需求。
- 想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(那些可能不一定兼容的类)协同工作。
- 想使用一些已经存在的子类,但是不可能对每个都进行子类化以匹配他们的接口。对象适配器可以适配它的父类接口。
核心思想:
将一个类的接口转换成另外一个客户希望的接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配就是由“源”到“目标”的适配,当中连接两者的关系就是适配器。负责把“源”过度到目标。
题目
正在运行的程序使用NEC NP-CD1100 型号的投影仪output 文件,现在又购置了爱普生CH-TW7000 型号的投影仪,但是它提供了不同的输出函数disply()。如果不想改变当前程序的编码,想使用新的类、但又不能改变它,如何设计?
- 根据以上描述,请问该题解决方案应该采用适配器模式还是工厂方法模式?(3分)> 适配器模式
- 用UML类图表达它的解决方案。
- 给出解决方案实现代码。>
> publicclassAdapterPattern{publicstaticvoidmain(String[] args){> projector chtw =newAdapter();> chtw.project();}}interface projector{publicvoidproject();}classNpCD1100implements projector{@Overridepublicvoidproject(){System.out.println("project");}}classChTw7000{publicvoiddisply(){System.out.println("display");}}classAdapterextendsChTw7000implements projector{@Overridepublicvoidproject(){disply();}}>
- 依据以上解析,请概括出所用设计模式的核心思想。> 将一个类的接口转换成另外一个客户希望的接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
- 请概括出所用设计模式适合的场合。> > - 想使用一个已经存在的类,而它的接口不符合目前的需求。> - 想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(那些可能不一定兼容的类)协同工作。> - 想使用一些已经存在的子类,但是不可能对每个都进行子类化以匹配他们的接口。对象适配器可以适配它的父类接口。
版权归原作者 Laccoliths 所有, 如有侵权,请联系我们删除。