学习原型模式,从模式动机、模式定义与分析、模式实例及代码要点、模式优缺点及应用场景四个方面分析该模式。

1模式动机:

√复制一个对象,从而克隆出多个与原型对象一模一样的对象——原型模式

√有些对象的创建过程较为复杂,而且需要频繁创建

√通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象

2模式定义与分析:

2.1模式定义:

√原型模式(Prototype Pattern)∶原型模式一种对象创建型模式,用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。

√原型模式允许通过一个原型对象创建一个或个同类型的其他对象,而无须知道任何创建的细节

2.2模式分析:

所有的Java类都继承自java.lang.Object,而Object类提供一个clone()方法,可以将一个Java对象复制

Java中可以直接使用Object提供的clone()方法来实现对象的克隆(浅克隆)

能够实现克隆的Java类必须实现一个标识接口Cloneable,表示这个Java类支持复制

如果一个类没有实现这个接口但是调用了clone()方法,Java编译器将抛出一个CloneNotSupportedException异常

浅克隆(Shallow Clone) :当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制

深克隆(Deep Clone) :除了对象本身被复制外,对象所包含的所有成员变量也将被复制

 

 

3 模式实例及代码要点

 

 

3.1模式实例:V邮件复制

( 1) 实例说明

由于邮件对象包含的内容较多(如发送者、接收者、标题、内容、日期、附件等) ,某系统中现需要提供一个邮件复制功能,对于已经创建好的邮件对象,可以通过复制的方式创建一个新的邮件对象,如果需要改变某部分内容,无须修改原始的邮件对象,只需要修改复制后得到的邮件对象即可。使用原型模式设计该系统。在本实例中使用浅克隆实现邮件复制,即复制邮件(Email)的同时不复制附件(Attachment)。

 

 

 代码

 

Client.java

 

package prototype.shallow;

public class Client
{
    public static void main(String a[])
    {
        Email email,copyEmail;
        email=new Email();
        ropyEmaiI=(Emai1)email.clone();
        System.out.println(" email==copyEmail?");
        System.out.println(email=acopyEmail);     
System.out.println("email.getAttachment==copyEmail.getAttachment?"); System.out.println(email.getAttachment()==copyEmail.getAttachment());   } }

 

 

Email.java

 package prototype.shallow;

public class Email implements Cloneable
{   
private Attachment attachment =null ;   public Email(){    this.attachment=new Att achment();   }   public Object clone()   {     Email clone=null;     try     {      clone=(Email)super.clone();
   }   
catch(CloneNotSupportedException e)     {       System.out.print1n("Clone failure!");     }     return clone;
  }   
public Attachment getAttachment ( )   {
    return this.attachment;
  }
  public void display(){
     System.out.print1n("查看邮件");
  }
}

 

 

 

 

分析:核心要点在 clone=(Email)super.clone();

 深克隆案例(邮件复制)

 

 

 Email.java

 

   

 

  

 Attachment.java

 

 Client.java

 

 

 

 

 

4 模式优缺点及应用场景

4.1 原型模式优点

√简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率

扩展性较好

简化创建结构,原型模式中产品的复制是通过封装在原型类中的克隆方法实现的,无须专门的工厂类来创建产品

可以使用深克隆的方式保存对象的状态,以便在需要的时候使用,可辅助实现撤销操作

4.2 原型模式缺点:

需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,

对已有的类进行改造时,需要修改源代码,违背'了开闭原则

在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每层对象对应的类都必须支持深克隆, 实现起来可能会比较麻烦

 

5 应用场景:
1). 创建新对象成本较大,新对象可以通过复制已有对象来获得,如果是相似对象,则可以对其成员变量稍作修改

2). 系统要保存对象的状态,而对象的状态变化很小

3).需要避免使用分层次的工厂类来创建分层次的对象

 

请将学过的四种设计模式进行关系比较,至少包含两个要点:

1     每种模式的定义和适用情况

2     至少挑选2个模式,比较他们的异同。

1.  模式定义及适用情况

1.1 工厂模式定义一个用于创建对象的接口,让接口子类通过工厂方法决定实例化哪一个类。

1)简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为。  

适用情况包括:工厂类负责创建的对象比较少;客户端只知道传入工厂类的参数,对于如何创建对象不关心。
2)工厂方法模式:工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象  

适用情况包括:一个类不知道它所需要的对象的类;一个类通过其子类来指定创建哪个对象;将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。
3)抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。  

适用情况包括:一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节;系统中有多于一个的产品族,而每次只使用其中某一产品族;属于同一个产品族的产品将在一起使用;

 

1.2 生成器模式(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

生成器模式适用环境:需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性;需要生成的产品对象的属性相互依赖,需要指定其生成顺序;对象的创建过程独立于创建该对象的类;在生成器模式中引入了指挥者类,将创建过程封装在指挥者类中,而不在生成器类中;隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

 

1.3 单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

单例模式适用情况包括:系统只需要一个实例对象;客户调用类的单个实例只允许使用一个公共访问点。

1.4 原型模式( Prototype Pattern )

通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。

原型模式是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

原型模式应用场景:

  1)当一个系统应该独立于它的产品创建,构成和表示时。

  2)当要实例化的类是在运行时刻指定时,例如,通过动态装载。

  3)为了避免创建一个与产品类层次平行的工厂类层次时。

  4)当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

 

 

2. 生成器模式与抽象工厂模式的异同

  • 抽象工厂模式与生成器模式功能上相似,它也可以创建复杂对象;
  • 与抽象工厂模式相比,生成器模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。生成器模式在最后一步返回产品,而对于抽象工厂模式来说,产品是立即返回的。
  • 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在生成器模式中,客户端可以不直接调用生成器的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。而抽象工厂模式着重于多个系列的产品对象(简单或复杂的)
  • 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么生成器模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。