`
lvwenwen
  • 浏览: 964048 次
  • 性别: Icon_minigender_1
  • 来自: 魔都
社区版块
存档分类
最新评论

设计模式之设计模式遵循的七大原则

阅读更多
文章链接:http://blog.csdn.net/csh624366188/article/details/7459918
设计模式分类(什么是GOF)
首先先简单说一下设计模式的分类设计模式可以分为三大类,分别是创建型设计模式、行为型设计模式以及结构型设计模式。
创建型的设计模式:单例模式(Singleton)、构建模式(Builder)、原型模式(Prototype)、抽象工厂模式(Abstract Factory)、工厂方法模式(Factory Method)
行为设计模式:策略模式(Strategy)、状态模式(State)、责任链模式(Chain of Responsibility)、解释器模式(Interpreter)、命令模式(Command)、观察者模式(Observer)、备忘录模式(Memento)、迭代器模式(Iterator)、模板方法模式(Template Method)、访问者模式(Visitor)、中介者模式(Mediator)
结构型设计模式:装饰者模式(Decorator)、代理模式(Proxy)、组合模式(Composite)、桥连接模式(Bridge)、适配器模式(Adapter)、蝇量模式(Flyweight)、外观模式(Facade)
  简单工厂模式
      从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
简单工厂模式的一般结构,如图所示:

    简单工厂模式存在三个组成部分,参考《Java与模式》一书,对应于三个不同的角色:
l 工厂角色
l 抽象产品角色
l 具体产品角色
   其实角色这个词用的比较确切,能够让我们理解到,每个角色的不是单纯地指一个类,可能是一组类所构成了这个角色。下面对三个角色进行描述:
1. 工厂角色
  工厂角色负责产品的生产工作。在简单工厂模式中,工厂类是一个具体的实现类,在系统设计中工厂类负责实际对象的创建工作。
  工厂类(Factory)的特点是:它知道系统中都存在哪些能够创建对象的具体类(ConcreteProduct),也知道该如何将创建的对象,以某种能够屏蔽具体类实现细节的方式(AbstractProduct)提供给所需要的其他角色来使用该对象提供的数据和服务。
2.抽象产品角色
  抽象产品角色是具体的产品的抽象。抽象就是将产品的共性抽取出来,可以直接暴露给客户端(需要使用具体产品的角色),对所有的客户端来说,从工厂中直接获取到的原始产品的外部形态都是相同的,没有任何的差别,包括数据和服务。这也就是说,具体客户端应该“秘密”掌握着某一个或一些具体产品的详细资料(具体产品类型、数据和服务),然后根据具体客户端(任何一个需要使用某种具体产品的数据和服务的实现类)需要什么样的附加数据和服务,进行类类型转换后,通过借助于对应的具体产品对象来完成其职责。
  抽象产品角色,在实际系统中可以定义为接口或者抽象类。
3.具体产品角色
  具体产品实现类一定是抽象产品类的实现或扩展。为了保证工厂类能够创建对象,工厂类需要知道具体产品的创建方式,这就涉及到具体产品类所提供的构造方法,以便,可能工厂类会向客户端提供具体创建服务所需要的数据。例如:某个产品类需要通过一个账号才能构造其实例,所以工厂类必须根据它的创建需求,为客户端提供一个带账号参数的生产方法,才能创建该具体产品类的对象。
  也就是说,工厂类依赖于具体产品实现类。同样,客户端类是依赖于工厂类的。
通过上述三个角色的描述,我们应该能够了解,系统中哪些类能够胜任上述的三个角色,并通过各类之间的关系,通过工厂模式来实现系统或者某个模块。在实际的设计过程中,可能不存在完全与上述基本简单工厂模式完全适应的,需要根据具体的需求来调整简单工厂模式的应用。只要能够实现系统的良好设计,有时候变化才能满足需要。
下面用一个简单的例子来说明一下,给大家加深一下印象(例子来自于网络):
[html] view plaincopy
运动员.java 
public interface 运动员 {        
        public void 跑(); 
        public void 跳(); 

足球运动员.java 
public class 足球运动员 implements 运动员 { 
        public void 跑(){ 
                //跑啊跑 
        }  
        public void 跳(){ 
                //跳啊跳 
        } 

篮球运动员.java 
public class 篮球运动员 implements 运动员 { 
        public void 跑(){ 
                //do nothing 
        }      
        public void 跳(){ 
                //do nothing 
        } 

体育协会.java 
public class 体育协会 {    
        public static 运动员 注册足球运动员(){ 
                return new 足球运动员(); 
        }      
        public static 运动员 注册篮球运动员(){ 
                return new 篮球运动员(); 
        } 

 
俱乐部.java 
public class 俱乐部 { 
        private 运动员 守门员; 
        private 运动员 后卫; 
        private 运动员 前锋; 
        public void test() { 
                this.前锋 = 体育协会.注册足球运动员(); 
                this.后卫 = 体育协会.注册足球运动员(); 
                this.守门员 = 体育协会.注册足球运动员(); 
                
                守门员.跑(); 
                后卫.跳(); 
        } 


以上就是简单工厂模式的一个简单实例,读者应该想象不用接口不用工厂而把具体类暴露给客户端的那种混乱情形吧(就好像没了体育总局,各个俱乐部在市场上自己胡乱的寻找仔细需要的运动员),简单工厂就解决了这种混乱。
工厂方法模式
工厂方法模式是类的创建模式,又叫虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。 工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际工作推迟到子类中。
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。工厂方法模式的对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不在负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。
工厂方法模式角色与结构
1.抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。  
2.具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
3.抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
4.具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
工厂方法模式的一般结构,如图所示:

我们在不改变产品类(“足球运动员”类和“篮球运动员”类)的情况下,写一下工厂方法模式的例子:
[html] view plaincopy
运动员.java 
public interface 运动员 {        
        public void 跑(); 
        public void 跳(); 

 
足球运动员.java 
public class 足球运动员 implements 运动员 { 
 
        public void 跑(){ 
                //跑啊跑 
        } 
        
        public void 跳(){ 
                //跳啊跳 
        } 

 
篮球运动员.java 
public class 篮球运动员 implements 运动员 { 
 
        public void 跑(){ 
                //do nothing 
        } 
        
        public void 跳(){ 
                //do nothing 
        } 

 
体育协会.java 
public interface 体育协会 { 
        public 运动员 注册(); 

 
足球协会.java 
public class 足球协会 implements 体育协会 { 
        public 运动员 注册(){ 
                return new 足球运动员(); 
        } 

 
篮球协会.java 
public class 篮球协会 implements 体育协会 { 
        public 运动员 注册(){ 
                return new 篮球运动员(); 
        } 

 
俱乐部.java 
public class 俱乐部 { 
        private 运动员 守门员; 
        private 运动员 后卫; 
        private 运动员 前锋; 
 
        public void test() { 
                体育协会 中国足协 = new 足球协会(); 
                
                this.前锋 = 中国足协.注册(); 
                this.后卫 = 中国足协.注册(); 
 
                守门员.跑(); 
                后卫.跳(); 
        } 


很明显可以看到,“体育协会”工厂类变成了“体育协会”接口,而实现此接口的分别是“足球协会”“篮球协会”等等具体的工厂类。
这样做有什么好处呢?很明显,这样做就完全OCP了。如果需要再加入(或扩展)产品类(比如加多个“乒乓球运动员”)的话就不再需要修改工厂类了,而只需相应的再添加一个实现了工厂接口(“体育协会”接口)的具体工厂类。
抽象工厂模式
       抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据LSP原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。
      先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。还是让我们用一个例子来形象地说明一下吧。

图中的BmwCar和BenzCar就是两个产品树(产品层次结构);而如图所示的BenzSportsCar和BmwSportsCar就是一个产品族。他们都可以放到跑车家族中,因此功能有所关联。同理BmwBussinessCar和BenzSportsCar也是一个产品族。
抽象工厂模式中的有以下的四种角色:
抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
具体产品(Concrete Product)角色:这个角色用以代表具体的产品。
Abstract Factory模式的结构:

抽象工厂模式就相当于创建实例对象的new,由于经常要根据类生成实例对象,抽象工厂模式也是用来创建实例对象的,所以在需要新的事例对象时便可以考虑是否使用工厂模式。虽然这样做可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
举例来说:生产餐具和相应食物的工厂,有两个车间,其中一个车间用以生产餐具,一个车间用以生产相应的食物。
当消费者消费时,只需要向相应的具体工厂请求具体餐具和具体食物便可以使用餐具消费食物。
使用UML图表示以上的描述如下:

图1抽象工厂与具体工厂

图2抽象餐具与具体餐具(生产车间)

图3抽象食物与具体食物
注:图中厨房单词写错了:kitchen
每个具体工厂生产出来的具体产品根据不同工厂的不同各不相同,但是客户使用产品的方法是一致的。比如客户在得到餐具和食物之后,两者的搭配是正确的(使用汤匙喝牛奶,使用刀子切面包)。
在本例子中有3个具体工厂AKitchen, BKitchen, BKitchen,分别生产牛奶和汤匙、面包和刀、肉和叉子。牛奶、面包和肉都实现了食物接口。汤匙、刀和叉子都实现了餐具接口。
抽象工厂的接口定义如下所示;
   
[html] view plaincopy
package abstractFactory; 
 
public interface KitchenFactory{ 
 
   public Food getFood(); 
 
   public TableWare getTableWare(); 
 

 
抽象餐具的接口定义如下所示: 
 
package abstractFactory; 
 
public interface TableWare{ 
 
public String getTool(); 
 

 
抽象事物的接口定义如下所示: 
 
package abstractFactory; 
 
public interface Food{ 
 
   public String getEatable(); 
 

 
而具体的实现也非常简单,以AKitchen为例子 
 
具体工厂AKitchen的定义如下所示; 
 
package abstractFactory; 
 
public class AKitchenimplements KitchenFactory{ 
 
   public Food getFood(){ 
 
      return new Milk(); 
 
   } 
 
   public TableWare getTableWare(){ 
 
      return new Spoon(); 
 
   } 
 

 
  
 
具体餐具(spoon)的定义如下所示: 
 
package abstractFactory; 
 
public class Spoonimplements TableWare{  
 
   public String getTool() { 
 
      return "spoon"; 
 
   } 
 

 
具体食物(milk)的定义如下所示: 
 
package abstractFactory; 
 
public class Milkimplements Food{ 
 
   public String getEatable(){ 
 
      return "milk"; 
 
   } 
 

 
客户端的定义如下: 
 
package abstractFactory; 
 
public class Client{ 
 
   public void eat(KitchenFactory k){ 
 
      System.out.println("A person eat "+k.getFood().getEatable() 
 
             +" with "+k.getTableWare().getTool()+"!"); 
 
   } 
 
   public static void main(String[] args){ 
 
      Client client=new Client(); 
 
      KitchenFactory kf =new AKitchen(); 
 
      client.eat(kf); 
 
      kf=new BKitchen(); 
 
      client.eat(kf); 
 
      kf=new CKitchen(); 
 
      client.eat(kf); 
 
   } 
 


在以下情况下应当考虑使用抽象工厂模式:
· 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
· 这个系统有多于一个的产品族,而系统只消费其中某一产品族。
· 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
· 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
分享到:
评论

相关推荐

    第一章设计模式与七大原则.doc

    设计模式是软件工程中的一种重要思想,它是经验丰富的软件开发者在实践中提炼出来的一套解决方案模板。...在实际开发中,选择合适的设计模式和遵循设计原则,可以帮助我们构建出更加优雅、可扩展的系统。

    尚硅谷_韩顺平_图解Java设计模式

    第二章深入探讨了设计模式的七大原则,这是理解并运用设计模式的基础。设计模式的目的在于提高软件的灵活性、可扩展性和可维护性。这七大原则包括单一职责原则、接口隔离原则、依赖倒置原则、里氏替换原则、接口隔离...

    设计模式C#版

    开放-封闭原则是设计模式的核心原则之一,它要求软件实体应当对扩展开放,对修改封闭。C#中的接口实现和继承就是遵循开放-封闭原则的典型案例。 七、里氏代换原则(LSP) 里氏代换原则指出,在软件中,如果一个...

    设计模式解析(英文版).pdf

    设计模式之所以能够被广泛接受和应用,关键在于它们遵循了一系列基本原则和动机。这些原则和动机包括但不限于: 1. **封装行为**:设计模式强调封装不仅限于数据,更重要的是封装行为。这意味着将行为和数据紧密...

    设计模式精心总结

    六大原则是设计模式遵循的指导原则: 1. 开闭原则(Open/Closed Principle):软件实体应该是对扩展开放的,对修改关闭的。 2. 里氏代换原则(Liskov Substitution Principle):所有引用基类的地方必须能透明地...

    论设计模式的重要性-《重学设计模式》

    在设计模式的学习过程中,了解软件设计的七大原则也至关重要。这七大原则包括单一职责原则(SRP)、开放封闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)、依赖倒置原则(DIP)、迪米特法则(LoD)和合成...

    设计模式之禅之+组合模式

    ### 设计模式之禅之组合模式 #### 一、引言 在面向对象的设计中,设计出既符合当前需求又能适应未来变化的软件系统是一项挑战。为了提高代码的复用性和系统的灵活性,开发者们总结出了多种设计模式。本文将探讨其中...

    Java设计模式学习笔记

    设计模式的七大原则 ##### 1.1 设计模式的目的 设计模式是一种解决特定问题的通用解决方案,它可以帮助开发人员编写出更高质量、更容易维护和扩展的代码。设计模式的目标在于提高代码的可重用性、可读性、可扩展...

    软件设计模式知识点

    软件设计模式还遵循七大设计原则: 1. 开放封闭原则(OCP):一个软件实体应当对扩展开放,对修改关闭。 2. 单一职责原则(SRP):强调的是职责的分离。 3. 里氏代换原则(LSP):在一个软件系统中,子类应该可以...

    设计模式汇总(含思维导图)

    设计模式分为三大类: 1. 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 2. 行为型模式,共十一种:命令模式、迭代器模式、观察者模式、备忘录模式、状态模式、模板方法模式、...

    java开发中使用的设计模式

    #### 设计模式七大原则 设计模式原则是指导程序员在编程时应当遵守的基本准则,也是各种设计模式的基础。 1. **单一职责原则**:一个类应该只有一个引起它变化的原因。这意味着类应当专注于完成单一的任务。 2. **...

    java常用设计模式 设计原则 应用场景介绍 极速版

    ### Java常用设计模式、设计原则及其应用场景介绍 #### 一、设计模式概述 设计模式是一种在软件工程领域中被广泛采用的概念,它是一系列解决特定问题的通用解决方案的集合。这些解决方案通常来源于软件开发人员的...

    设计模式基础培训材料-面向对象设计原则与模式

    #### 二、面向对象设计七大原则详解 1. **开闭原则(Open-Closed Principle, OCP)** - **定义**:开闭原则强调系统应当对扩展开放,对修改关闭。这意味着当需要增加新功能时,应尽可能不修改现有代码。 - **...

    Java之23种设计模式解析_尚硅谷_宋红康

    设计模式遵循以下六大原则: 1. **开闭原则**(Open-Closed Principle) - **定义**:软件实体应该是可扩展的,但不可修改的。 - **应用场景**:在设计软件模块时,考虑未来可能的变化,保持模块的稳定性。 2. *...

    设计模式,软件开发者必读

    这篇教材主要面向IT专业人士,深入探讨了设计模式的概念、作用、来源和分类,并详细讲解了面向对象设计的七个核心原则。 首先,设计模式的定义是指在软件工程中,经过时间验证的,针对特定问题的有效解决方案,它是...

    设计模式.pdf

    设计模式的七大原则是指导设计模式实践的基础原则,包括开放封闭原则、单一职责原则、依赖倒置原则、接口隔离原则、里氏替换原则、迪米特原则和合成复用原则。这些原则帮助设计者在维护和扩展软件时,保持设计的灵活...

Global site tag (gtag.js) - Google Analytics