案例分析:设计模式与代码的结构特性

一、什么是软件设计模式

1、概念        

  软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

2、作用

  使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。

3、分类

软件设计模式一般可分为以下几类:

(1)创建模式
  a. 抽象工厂模式(Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  b. 生成器模式(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
  c. 工厂方法模式(Factory Method):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。
  d. 原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
  e. 单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点。

(2)结构模式

  a. 适配器模式 (Adapter) :将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
  b. 桥接模式(Bridge) :将抽象部分与它的实现部分分离,使它们都可以独立地变化。
  c. 组合模式(Composite) :将对象组合成树形结构以表示“部分-整体”的层次结构。它使得客户对单个对象和复合对象的使用具有一致性。
  d. 容器模式
  e. 修饰模式 (Decorator) :动态地给一个对象添加一些额外的职责。就扩展功能而言, 它比生成子类方式更为灵活。
  f. 扩展性模式
  g. 外观模式
  h. 享元模式
  i. 管道与过滤器模式
  j. 代理模式(Proxy) :为其他对象提供一个代理以控制对这个对象的访问。

(3)行为模式

  a. 责任链模式 (Chain of Responsibility) :为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。
  b. 命令模式 (Command) :将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。
  c. 事件监听器模式
  d. 解释器模式
  e. 迭代器模式
  f. 中介者模式
  g. 备忘录模式 (Memento) :在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。
  h. 观察者模式(Observer) :定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
  i. 状态模式 (State) ,允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。
  j. 策略模式 (Strategy) ,定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
  k. 访问者模式 (Visitor),表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

(4)并发模式

(5)实时模式

(6)其他:模型—视图—控制器模式

  本文选取创建模式中的工厂方法模式展开具体分析。

二、工厂方法模式(Factory Method)

1、简单工厂模式        

  在正式介绍工厂方法模式之前,我们首先对简单工厂模式做简要介绍,以便帮助我们更好的理解工厂方法模式。

  简单工厂模式不属于以上介绍的软件设计模式的分类中,可分为:普通简单工厂、多方法简单工厂和静态方法简单工厂。

  适用于大量产品需要创建,并且这些产品具有共同的接口的情况,并且在三种分类中,通常选用静态方法简单工厂。

(1)普通简单工厂

  建立一个工厂类,使用该类的同一接口创建实例。

  关系图如下所示:

  举例说明(以发送邮件和短信的例子):

  第一步:创建发送的共同接口

1 public interface Sender {  
2     public void Send();  
3 }  

  第二步:创建实现类

发送邮件的实现类:

1 public class MailSender implements Sender {  
2     @Override  
3     public void Send() {  
4         System.out.println("this is mailsender!");  
5     }  
6 }  

发送短信的实现类:

1 public class SmsSender implements Sender {  
2   
3     @Override  
4     public void Send() {  
5         System.out.println("this is sms sender!");  
6     }  
7 }  

  第三步:建立工厂类

 1 public class SendFactory {  
 2   
 3     public Sender produce(String type) {  
 4         if ("mail".equals(type)) {  
 5             return new MailSender();  
 6         } else if ("sms".equals(type)) {  
 7             return new SmsSender();  
 8         } else {  
 9             System.out.println("请输入正确的类型!");  
10             return null;  
11         }  
12     }  
13 }  

  测试:

1 public class FactoryTest {  
2   
3     public static void main(String[] args) {  
4         SendFactory factory = new SendFactory();  
5         Sender sender = factory.produce("sms");  
6         sender.Send();  
7     }  
8 }  

  输出结果为:thiis is sms sender!

(2)多方法简单工厂

  对普通简单工厂的改进,解决了普通简单工厂中因字符串传递出错而不能正确创建对象的问题。在多方法简单工厂中,提供了多个工厂方法,分别用于创建不同的对象。

  关系图如下所示:

(3)静态方法简单工厂

  又是对多个方法简单工厂的改进,将多个方法简单工厂中的方法设置为静态(static)的,不需要再创建实例。

2、工厂方法模式

  在简单工厂模式中,类的创建完全依赖于工厂类,这就意味着,如果我们因为工作的拓展需要修改程序时,必须去修改工厂类,这种做法违反了软件设计模式中的闭包原则。

  解决措施:提出了工厂方法模式,我们创建一个工厂接口和多个工厂实现类,在这种情况下, 需要添加新的功能时只需要添加新的工厂实现类就可以了,不用再对工厂接口做任何的修改,符合软件设计模式的原则。

  关系图如下所示:

  举例说明(仍然以发送邮件和短信来进行说明):

  第一步:创建一个接口类

1 public interface Sender {  
2     public void Send();  
3 }  

  第二步:创建基于接口类的两个实现类

发送邮件的实现类:

1 public class MailSender implements Sender {  
2     @Override  
3     public void Send() {  
4         System.out.println("this is mailsender!");  
5     }  
6 }  

发送短信的实现类:

1 public class SmsSender implements Sender {  
2   
3     @Override  
4     public void Send() {  
5         System.out.println("this is sms sender!");  
6     }  
7 }  

   第三步:增加一个接口

1 public interface Provider {  
2     public Sender produce();  
3 }  

  第四步:创建基于新的接口的两个工厂类

发送邮件的工厂类:

1 public class SendMailFactory implements Provider {  
2       
3     @Override  
4     public Sender produce(){  
5         return new MailSender();  
6     }  
7 }  

发送短信的工厂类:

1 public class SendSmsFactory implements Provider{  
2   
3     @Override  
4     public Sender produce() {  
5         return new SmsSender();  
6     }  
7 }  

测试:

1 public class Test {  
2   
3     public static void main(String[] args) {  
4         Provider provider = new SendMailFactory();  
5         Sender sender = provider.produce();  
6         sender.Send();  
7     }  
8 }  

  结果为:this is mail sender!

三、模式分析

1、引入该设计模式后对系统架构和代码结构带来了哪些好处?

  工厂方法模式的是定义一个创建产品对象的工厂接口或抽象方法,让子类决定实例化哪一个类。工厂方法是一个类的实例化延迟的其子类。因为每一个具体产品类对应着一个具体的工厂类,故增加具体产品时只需要增加一个具体工厂类.。工厂方法模式是简单工厂模式的进一步抽象和推广,克服了简单工厂的违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。

2、解释其中用到的多态机制

   主要涉及到的是编译时多态,有多个不同的子类继承自相同的一个父类,由子类对象的类型决定具体应该去实例化哪一个类。

3、说明模块抽象封装的方法

    抽象:在定义类时,将一类事务的公有属性和行为进行提取,形成一个固定的模型。如上文中的Sender类。

  封装:把抽象之后的数据和对数据的操作封装在一起,数据保存在内部,只有某个被允许访问的行为和操作才能对数据进行更改。

4、分析各个模块的内聚度和模块之间的耦合度

   内聚度:标志着一个模块内部各成分彼此结合的紧密程度。此处工厂实现类中的各元素共同完成一个功能,基本上不涉及到其他模块的功能,内聚度较高。

  耦合度:标志着各模块之间关联程度的多少。此处的工厂实现类依赖于工厂接口,但是工厂接口不涉及到实现,因此模块间的耦合度较低。

 

原文地址:https://www.cnblogs.com/liujianing0421/p/12007976.html