`
dwphper
  • 浏览: 17878 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
最近访客 更多访客>>
社区版块
存档分类
最新评论

三种重要设计模式简介

阅读更多
一、设计模式的概念
设计模式是对被用来在特定场景下解决一般设计问题的类和相互通信的对象的描述。设计模式是针对问题和解的抽象,是对一系列具有共同的问题的完整的解决方案。设计模式强调系统的复用性,它帮助人们做出有利于系统复用的选择,从而避免设计损害系统的复用性,是可复用面向对象软件的基础。一个完整的设计模式主要由模式名称、问题、解决方案和效果四个基本要素组成。
设计模式中最重要的思想就是“封装变化的概念”。这是绝大多数射进模式的核心概念。一方面,设计出来的软件应该体现出一定的灵活性,以适应可能的变化;另一方面,必须把这种灵活性所带来的软件内部的复杂性封装起来,为外界提供一个简单而稳定的访问接口,这两方面分别从内部实现和外部接口上提高了软件的复用性。这就要求我们在进行可复用面向对象软件设计时应遵循:不断剥离出系统中可变化的部分并把这部分封装起来。
二、设计模式将带来什么
1、设计模式带来了一套通用的设计词汇
各种设计模式的名字组成了一个词汇表,这个词汇表可以帮助开发人员更好地交流。设计模式为设计者们交流讨论、书写文档以及探索各种不同设计提供了一套通用的设计词汇。设计模式使设计者可以在比设计表示或编程语言更高的抽象级别上谈论一个系统,从而降低了其复杂度。
2、书写文档和学习的辅助手段
当一个系统的文档描述系统所用的模式时,它们可以帮助人们更快地理解这个系统。学习这些设计模式有助于设计者理解已有的面向对象系统,同时也能提高设计者的设计水平。而且,按照一个系统所使用的设计模式来描述该系统可以使他人理解起来容易得多,否则,就必须对该系统的设计进行逆向工程来弄清其使用的设计模式。有一套通用的设计词汇的好处是你不必描述整个设计模式,而只要使用它的名字,当他人读到这个名字就会理解系统的设计。
3、设计模式是现有方法的一种补充
设计模式总结了专家的经验,使得普通的开发人员可以使用。面向对象方法可用来促进良好的设计,教新手如何设计,以及对设计活动进行标准化。设计模式是面向对象设计方法所缺少的一块重要内容。这些设计模式展示了如何使用诸如对象、继承和多态等基本技术。它们也展示了如何以算法、行为、状态或者需生成的对象类型将一个系统参数化。设计模式在将一个分析模型转换为一个实现模型时特别有用。一个成熟的设计方法不仅要有设计模式,还可有其他类型的模式,如分析模式,用户界面设计模式或者性能调节模式等等,但设计模式是最主要的部分。
4、设计模式为系统重构提供了目标
无论系统是否用脑海中的模式来设计,它们都可以使更改系统机构变得容易。开发可复用软件的一个问题是开发者常常不得不重新组织或重构软件系统。设计模式可以帮助开发者重新组织一个设计,同时还能减少以后的重构工作。设计模式记录了许多重构产生的设计结构。在设计初期使用这些模式可以防止以后的重构。而且即使是在系统建成以后才了解使用这些模式,它们仍可以教设计者如何修改系统。
三、三种设计模式的介绍
在用设计模式进行面向对象设计时,特别强调两个面向对象设计的原则:针对接口编程而不是针对实现编程和优先使用组合而不是类继承。其中针对接口编程而不是针对实现编程要求不将变量声明为某个特定的具体类,而是让它遵从抽象类所定义的接口。然而,有时不得不在系统的某个地方实例化具体的类,这时创建型模式(Factory Method,Abstract Factory,Builder,Prototype,Singleton)可以做到这点。在这里主要通过具体的实例介绍三种创建型设计模式:工厂方法模式(Factory Method),抽象工厂模式(Abstract Factory),以及生成器模式(Builder)。
假设有这样的一个企业:该企业有四川和重庆两个分公司,每个子公司都有一套自己的薪资计算规则,每个月每个公司都要计算自己公司的薪资。那么应该如何为该企业设计一套薪资系统呢?
我们可能这样想,首先抽象出一个薪资类,然后所有的子公司的薪资类都继承这个抽象的薪资类,最后在客户端判断是哪个子公司,然后新建该子公司的薪资类对象。如果是这样,那么当这个企业的子公司有许多的时候,客户端的条件判断岂不是要写许多,代码就会变得很长。
我们可以再创建一个类,把具体的判断语句抽取到这个类中,在客户端只负责薪资类的计算,这样可以解决在客户端要写许多判断语句的问题。还有一个问题就是如果该企业的子公司有很多,那么判断语句中的if…else语句就会很多,代码就不好看,而且一般在薪资计算前,都会有一些初始化工作要做,把许多公司的初始化工作都放在一个类中来做,代码量就可想而知了。所以,在这里,我们需要使用工厂方法模式来进行设计。
1、工厂方法模式(Factory Method)
(1)意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类。
(2)适用性:
1)当一个类不知道它所必须创建的对象的类的时候;
2)当一个类希望由它的子类来指定它所创建的对象的时候;
3)当类将创建对象的职责委托给多个帮助子类中的某一个,并且希望将哪一个帮助子类是代理者这一信息局部化的时候。
(3)参与者:
1)Product——定义工厂方法所创建的对象的接口
2)ConcreteProduct——实现Product接口
3)Creator——声明工厂方法,该方法返回一个Product类型的对象
4)ConcreteCreator——重定义工厂方法以创建一个Product对象。
(4)实例代码:
这里我们还是以上面的那个企业的薪资系统为例。代码如下:
//*** 抽象的薪资类定义 ***
//********Salary.java**********
interface Salary{
void computerSalary();
}
//*** 四川子公司的薪资类的代码 *****
//****SCSalary.java******
class SCSalary implements Salary{
public void computerSalary(){
System. out .println( " 开始计算四川子公司的薪资 " );
}
}
//*** 重庆子公司的薪资类的代码 *****
//****CQSalary.java*****
class CQSalary implements Salary{
public void computerSalary(){
System. out .println( " 开始计算重庆子公司的薪资 " );
}
}
//*** 创建一个只负责定义创建方式的抽象的工厂类 ***
//***Factory.java*******
interface Factory{
public Salary createSalary();
}
//*** 四川子公司的工厂类 ***
//***SCSalaryFactory.java***
class SCSalaryFactory implements Factory{
public Salary createSalary(){
return new SCSalary();
}
}
//*** 重庆子公司的工厂类 ***
//***CQSalaryFactory.java***
class CQSalaryFactory implements Factory{
public Salary createSalary(){
return new CQSalary();
}
}
//*** 客户端代码 ***
//***Client.java***
public class Client{
public static void main(String [] args){
Factory factory= new SCSalaryFactory();
Salary salary=factory.createSalary();
salary.computerSalary();
factory= new CQSalaryFactory();
salary=factory.createSalary();
salary.computerSalary();
}
}
在实例中,创建了一个只负责定义薪资创建方式的抽象工厂类 Factory ,而在客户端就只负责对象的调用即可。从而避免了把对象的创建和组装都放在客户端,造成客户端代码很复杂,同时也明确了各个类的职责。
(5 )小结:
在工厂方法模式中,客户端不需要负责对象的创建,而是把这个责任交给了具体的工厂类,客户端只负责对象的调用,从而明确了各个类的职责。如果有新的产品加进来,只需要新增加一个具体的产品工厂类( ConcreteCreator )和具体的产品类 (ConcreteProduct) 就可以了,不会影响到原来已有的其他代码,代码量不会变大,后期维护更加容易,增强了系统的可扩展性。
在工厂方法模式中,一个具体的工厂类负责创建一个单独的产品,如果有两个不同的产品要创建,就需要两个不同的工厂类,即使这两个产品之间存在相关性,同样还需要两个不同的工厂类。同样如此,对于上面的实例,该企业计算完薪资,如果还要计算税收,倘若采用工厂方法模式,那么就需要定义两个抽象工厂类,分别用来定义薪资和税收,然后每个子公司分别继承这两个抽象工厂类以实现具体的工厂类,这样一来,每个子公司至少要 2 个工厂类:薪资、税收。如果该企业的子公司有许多,工厂类的数量就可想而知了。这时我们可以重新定义一个抽象的工厂类,用来定义创建薪资类和税收类的方式,这就是抽象工厂模式。
2 、抽象工厂模式 (Abstract Factory)
1 )意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
2 )适用性:
1 )一个系统要独立于它的产品的创建、组合和表示时;
2 )一个系统要由多个产品系列中的一个来配置时;
3 )当你要强调一系列相关的产品对象的设计以便进行联合使用时;
4 )当你提供一个产品类库,而只想显示它们的接口而不是实现时。
(3)参与者:
1)AbstractFactory——声明一个创建抽象产品对象的操作接口
2)ConcreteFactory——实现创建具体产品对象的操作
3)AbstractProduct——为一类产品对象声明一个接口
4)ConcreteProduct——实现AbstractProduct,定义一个将被相应的具体工厂创建的产品对象
5)Client——仅使用由AbstractFactory和AbstractProduct类声明的接口。
(4)实例代码:
税收类和薪资类的设计一样,先设计一个抽象的接口,然后每个子公司的税收类都继承该接口。代码如下:
//*** 抽象的薪资类定义 ***
//********Salary.java**********
interface Salary{
void computerSalary();
}
//*** 四川子公司的薪资类的代码 *****
//****SCSalary.java******
class SCSalary implements Salary{
public void computerSalary(){
System. out .println( " 开始计算四川子公司的薪资 " );
}
}
//*** 重庆子公司的薪资类的代码 *****
//****CQSalary.java*****
class CQSalary implements Salary{
public void computerSalary(){
System. out .println( " 开始计算重庆子公司的薪资 " );
}
}
//*** 抽象的税收类定义
//***Tax.java***
interface Tax{
void computerTax();
}
//*** 四川子公司的税收类代码 ***
//***SCTax.java***
class SCTax implements Tax{
public void computerTax(){
System. out .println( " 开始计算四川公司的税收 " );
}
}
//*** 重庆子公司的税收类代码 ***
//***CQTax.java***
class CQTax implements Tax{
public void computerTax(){
System. out .println( " 开始计算重庆公司的税收 " );
}
}
//*** 定义一个抽象的工厂类,用来定义创建薪资类和税收类的方式 ***
//***Factory.java*******
interface Factory{
Salary createSalary();
Tax createTax();
}
//*** 四川子公司的抽象工厂类 ***
//***SCFactory.java***
class SCFactory implements Factory{
/* 创建四川子公司的薪资对象 */
public Salary createSalary(){
return new SCSalary();
}
/* 创建四川子公司的薪资对象 */
public Tax createTax(){
return new SCTax();
}
}
//*** 重庆子公司的抽象工厂类 ***
//***CQFactory.java***
class CQFactory implements Factory{
/* 创建重庆子公司的薪资对象 */
public Salary createSalary(){
return new CQSalary();
}
/* 创建重庆子公司的薪资对象 */
public Tax createTax(){
return new CQTax();
}
}
//*** 客户端代码 ***
//***Client.java***
public class Client{
public static void main(String [] args){
Factory factory= new SCFactory();
Salary salary=factory.createSalary();
salary.computerSalary();
Tax tax=factory.createTax();
tax.computerTax();
factory= new CQFactory();
salary=factory.createSalary();
salary.computerSalary();
tax=factory.createTax();
tax.computerTax();
}
}
在这个实例中,创建了一个抽象工厂类 Factory 来定义薪资类和税收类的创建,而不是分别定义两个抽象的工厂类,分别负责定义薪资类和税收类的创建,从而避免了程序中出现许多工厂类,增加程序代码复杂度。
(5 )小结:
与工厂方法模式相同,在抽象工厂模式中,客户端不再负责对象的创建,而是把这个责任交给了具体的工厂类,客户端只负责对对象的调用,从而明确了各个类的职责。当一系列相互关联的产品被设计到一个工厂类里后,客户端的调用将会变得非常简单,而且,如果要更换这一系列的产品,只需要更换一个工厂类即可。但是如果有新的产品加进来,则需要修改抽象工厂类的设计,并同时修改实现这个抽象工厂类的具体工厂类,需要额外编写代码,增加了工作量。
在抽象工厂模式中,把相互关联的产品的对象的组装都放在了客户端,如果产品很多,客户端就会变得非常臃肿;但如果放在工厂类中,则又违反了单一职责的原则,使得工厂类既要负责对象的创建,又要负责对象的组装。当然,我们可以创建一个组装类来负责对象的组装,工厂类只负责对象的创建,而客户端直接调用组装类就可以了,这就是生成器模式。
3 、生成器模式 (Bulider)
1 )意图:将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。
2 )适用性:
1 )当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装方式时
2 )当构造过程必须允许被构造的对象有不同的表示时。
(3)参与者:
1)Builder——为创建一个Product对象的各个部件指定抽象接口
2)ConcreteBuilder——实现Builder的接口以构造和装配该产品的各个部件
3)Director——构造一个使用Builder接口的对象
4)Product——表示被构造的复杂对象,包含定义组成部件的类。
(4)实例代码:
//*** 抽象的薪资类定义 ***
//********Salary.java**********
interface Salary{
void computerSalary();
}
//*** 四川子公司的薪资类的代码 *****
//****SCSalary.java******
class SCSalary implements Salary{
public void computerSalary(){
System. out .println( " 开始计算四川子公司的薪资 " );
}
}
//*** 重庆子公司的薪资类的代码 *****
//****CQSalary.java*****
class CQSalary implements Salary{
public void computerSalary(){
System. out .println( " 开始计算重庆子公司的薪资 " );
}
}
//*** 抽象的税收类定义
//***Tax.java***
interface Tax{
void computerTax();
}
//*** 四川子公司的税收类代码 ***
//***SCTax.java***
class SCTax implements Tax{
public void computerTax(){
System. out .println( " 开始计算四川公司的税收 " );
}
}
//*** 重庆子公司的税收类代码 ***
//***CQTax.java***
class CQTax implements Tax{
public void computerTax(){
System. out .println( " 开始计算重庆公司的税收 " );
}
}
//*** 定义一个抽象的工厂类,用来定义创建薪资类和税收类的方式 ***
//***Factory.java*******
interface Factory{
Salary createSalary();
Tax createTax();
}
//*** 四川子公司的抽象工厂类 ***
//***SCFactory.java***
class SCFactory implements Factory{
/* 创建四川子公司的薪资对象 */
public Salary createSalary(){
return new SCSalary();
}
/* 创建四川子公司的薪资对象 */
public Tax createTax(){
return new SCTax();
}
}
//*** 重庆子公司的抽象工厂类 ***
//***CQFactory.java***
class CQFactory implements Factory{
/* 创建重庆子公司的薪资对象 */
public Salary createSalary(){
return new CQSalary();
}
/* 创建重庆子公司的薪资对象 */
public Tax createTax(){
return new CQTax();
}
}
//*** 组装类,负责产品的组装 ***
//***Director.java***
class Director{
private Factory factory ;
public Director(Factory factory){
this . factory =factory;
}
public void computer(){
Salary salary= factory .createSalary();
salary.computerSalary();
Tax tax= factory .createTax();
tax.computerTax();
}
}
//*** 客户端代码 ***
//***Client.java***
public class Client{
public static void main(String [] args){
Director director= new Director( new SCFactory());
director.computer();
}
}
在这里,我们创建了一个工厂类 Factory 负责定义薪资类和税收类的创建,并且创建了一个创建者类 Director 负责对象的组装,而在客户端则只需要调用这个创建者类即可,从而明确了各个类的职责,使得各个类更好的分工。
(5 )小结:
在构造器模式中,客户端不再负责对象的创建和组装,而是把这个创建的责任交给了具体的创建者类,把组装的责任交给组装类,客户端只负责对象的调用,从而明确了各个类的职责。
虽然利用构造器模式可以创建出不同类型的产品,但如果产品之间的差异非常大,就需要编写多个创建这类才能实现,这是如果结合工厂模式更好。
分享到:
评论

相关推荐

    C++ Qt设计模式(第2版)

    C++ Qt设计模式(第2版)是美国萨福克大学已使用十余年的经典教程,利用跨平台开源软件开发框架Qt阐释了C++和设计模式中的主要思想。全书共分四个部分:第一部分介绍C++、UML、Qt、模型-视图、SQL、XML、设计模式等...

    设计模式解析-英文

     第1章 面向对象范型 2 第2章 UML 21 第二部分 传统面向对象设计的局限 第3章 对代码灵活性要求很高的问题 33 第4章 标准的面向对象解决方案 41 第三部分 设计模式 第5章 设计模式简介 53 第6章 Facade模式 65 第7...

    Java的23种设计模式疯狂Java总结.doc

    设计模式(超级详细) 内容简介 有感于设计模式在日常开发中的重要性,同时笔者也自觉对设计模式小有心得,故笔者 *写二十三种设计模式的简单例子、 并整理二十三种设计模式的理论局部,综合汇总成这份Java设计模式〔...

    领域驱动设计与模式实战

    2.4 针对具体应用程序类型的设计模式 2.5 领域模式 2.6 小结 第3章 TDD与重构 3.1 TDD 3.1.1 TDD流程 3.1.2 演示 3.1.3 设计效果 3.1.4 问题 3.1.5 下一个阶段 3.2 模拟和桩 3.2.1 典型单元测试 3.2.2 声明独立性 ...

    java 多线程设计模式 进程详解

    《JAVA多线程设计模式》PDF 下载 《Java线程 高清晰中文第二版》中文第二版(PDF) 前言 第一章 线程简介 Java术语 线程概述 为什么要使用线程? 总结 第二章 Java线程API 通过Thread类创建线程 使用Runable接口...

    敏捷软件开发原则、模式与实践 C#版

    Martin深入而生动地 使用真实案例讲解了面向对象设计的基本原则、重要的设计模式、UML和敏 捷方法。 本书Java版曾荣获2003年第13届Jolt大奖,是公认的经典著作。本书是 C#程序员提升功力的绝佳教程,也可用作高校...

    敏捷软件开发:原则、模式与实践.pdf

     ●设计模式:本书中讲述了23个设计模式,并都有具体的实例。讲解的重点在如何在实际的应用中去使用模式,如何根据当前问题的上下文以及约束力去选择最适合的模式,以及何时避免使用模式。  ●UML:本书不是关于 ...

    吴天雄--Spring笔记.doc

    Spring框架简介(EJB、JMX、Spring核心功能、Spring模块详解、Spring重要概念(容器)、Spring容器初始化的整个流程、Spring后处理器),IOC详解,Spring环境搭建,Spring创建Bean的三种方式,scope属性详解(包含...

    开发模式UML的介绍对开发的应该有帮助

    出发点在这一章将概述了面向对象的分析与设计( ooad ) ,重点是在对三个最重要的概念,它所包含的物体,分析,设计,因为要了解UML的,你首先必须明白,这些更广泛的概念。如果您的程序与任何面向对象的语言,那么...

    UML基础、案例与应用(第三版)].施穆勒.扫描版_2分.pdf

    22.5 使用设计模式的好处 260 22.6 小结 260 22.7 常见问题解答 261 22.8 小测验和习题 261 22.8.1 小测验 261 22.8.2 习题 261 第三部分 高级应用 第23章 嵌入式系统建模 265 23.1 回到餐馆 265 23.2 发明之母 ...

    asp.net知识库

    深入剖析ASP.NET组件设计]一书第三章关于ASP.NET运行原理讲述的补白 asp.net 运行机制初探(httpModule加载) 利用反射来查看对象中的私有变量 关于反射中创建类型实例的两种方法 ASP.Net应用程序的多进程模型 NET委托...

    OpenSceneGraph三维渲染引擎设计与实践

    4.3 重要节点的功能实现 74 4.3.1 空间变换节点 74 4.3.2 范例:使用空间变换节点 79 4.3.3 开关节点 81 4.3.4 范例:使用开关节点 82 4.3.5 细节层次节点(lod) 83 4.3.6 范例:使用lod节点 85 4.3.7 范例...

    企业文化三个设计方案.docx

    企业文化三个设计方案1 为进一步提升企业发展水平,增强员工对企业文化认知度,根据总裁指示精神,特制定以下方案: 一、栏目设置 根据公司企业文化墙的实际情况,初步计划列出八个板块,分别是:编者按、企业简介、...

    敏捷软件开发原则,模式与实践

     ●设计模式:本书中讲述了23个设计模式,并都有具体的实例。讲解的重点在如何在实际的应用中去使用模式,如何根据当前问题的上下文以及约束力去选择最适合的模式,以及何时避免使用模式。  ●UML:本书不是关于...

    领域驱动设计.软件核心复杂性应对之道-3

    ●隔离领域●实体、值对象、服务和模块●一个领域对象的生命周期●将过程表示为领域对象●创建没有副作用的函数●总体轮廓●独立的类●扩展说明●应用分析模式●将设计模式与模型相联系●维护模型的完整性●设计领域...

    超级双模式俄罗斯方块文档(支持联机对战)

    3.1.1设计模式的选取 6 3.1.2游戏的重难点分析 7 3.2 主要模块划分 8 3.3 系统基本流程结构 8 3.4简单UML图解 9 四.详细设计 10 4.1 游戏主流程图 10 4.2 模型的设计 13 4.2.1方块的数据结构 14 4.2.2方块的产生 15...

    毕业设计:python基于改进高斯混合模型的图割算法(源码 + 数据库 + 说明文档)

    (一) B/S设计模式 5 (二) MYSQL 5 (三) python语言简介 6 四、 需求分析 6 (四) 功能需求 6 (五) 系统总体建设 6 五、 系统可行性研究 7 1. 法律可行性 7 2. 经济可行性 7 3. 操作可行性 7 六、 系统总体设计 8 七、...

    UML和模式应用(架构师必备).part06.rar

    26.2 一些GRASP原则是对其他设计模式的归纳 26.3 设计中发现的“分析”:领域模型 26.4 工厂(Factory) 26.5 单实例类(GoF) 26.6 具有不同接口的外部服务问题的结论 26.7 策略(GoF) 26.8 组合(GoF)和...

Global site tag (gtag.js) - Google Analytics