java设计模式(6):原型模式(Prototype)

概述

在软件系统中,有时候面临的产品类是动态变化的,而且这个产品类具有一定的等级结构。这时如果用工厂模式,则与产品类等级结构平行的工厂方法类也要随着这种变化而变化,显然不大合适。那么如何封装这种动态的变化?从而使依赖于这些易变对象的客户程序不随着产品类变化?

意图

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

结构图

Prototype模式结构图

生活中的例子

Prototype模式使用原型实例指定创建对象的种类。新产品的原型通常是先于全部产品建立的,这样的原型是被动的,并不参与复制它自己。一个细胞的有丝分裂,产生两个同样的细胞,是一个扮演主动角色复制自己原型的例子,这演示了原型模式。一个细胞分裂,产生两个同样基因型的细胞。换句话说,细胞克隆了自己。

使用细胞分裂例子的Prototype模式对象图

原型模式解说

我们考虑这样一个场景,假定我们要开发一个调色板,用户单击调色板上任一个方块,将会返回一个对应的颜色的实例,下面我们看看如何通过原型模式来达到系统动态加载具体产品的目的。

很自然,我们利用OO的思想,把每一种颜色作为一个对象,并为他们抽象出一个公用的父类,如下图:

实现代码:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. public abstract class Color {  
  2.     public abstract void Display();  
  3. }  
  4.   
  5.   
  6. public class GreenColor extends Color{  
  7.     public void Display() {  
  8.         System.out.println("Green's RGB Values are:0,255,0");  
  9.     }  
  10. }  
  11.   
  12. public class RedColor extends Color{  
  13.     public void Display() {  
  14.         System.out.println("Red's RGB Values are:255,0,0");  
  15.     }  
  16. }  


客户程序需要某一种颜色的时候,只需要创建对应的具体类的实例就可以了。但是这样我们并没有达到封装变化点的目的,也许你会说,可以使用工厂方法模式,为每一个具体子类定义一个与其等级平行的工厂类,那么好,看一下实现:

实现代码

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. public abstract class ColorFactory {  
  2.      public abstract Color Create();  
  3. }  
  4.   
  5. public class GreenFactory extends ColorFactory{  
  6.     public  Color Create()  
  7.     {  
  8.         return new GreenColor();  
  9.     }  
  10. }  
  11.   
  12. public class RedFactory extends ColorFactory{  
  13.     public  Color Create()  
  14.     {  
  15.         return new RedColor();  
  16.     }  
  17. }  

实现了这一步之后,可以看到,客户程序只要调用工厂方法就可以了。似乎我们用工厂方法模式来解决是没有问题的。但是,我们考虑的仅仅是封装了new变化,而没有考虑颜色的数量是不断变化的,甚至可能是在程序运行的过程中动态增加和减少的,那么用这种方法实现,随着颜色数量的不断增加,子类的数量会迅速膨大,导致子类过多,显然用工厂方法模式有些不大合适。

进一步思考,这些Color子类仅仅在初始化的颜色对象类别上有所不同。添加一个ColorTool这样的类,来参数化的它的实例,而这些实例是由Color支持和创建的。我们让ColorTool通过克隆或者拷贝一个Color子类的实例来创建新的Color,这个实例就是一个原型。如下图所示:

实现代码:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. public abstract class ColorPrototype implements Cloneable{  
  2.      public abstract ColorPrototype clonenew() throws CloneNotSupportedException;  
  3. }  
  4.   
  5. public class ConcteteColorPrototype extends ColorPrototype{  
  6.     private int red;  
  7.     private int green;  
  8.     private int blue;  
  9.   
  10.     public ConcteteColorPrototype(int red, int green, int blue) {  
  11.         this.red = red;  
  12.         this.green = green;  
  13.         this.blue = blue;  
  14.     }  
  15.   
  16.     public ColorPrototype clonenew() throws CloneNotSupportedException  {  
  17.         return (ColorPrototype) this.clone();  
  18.     }  
  19.   
  20.     public void Display(String colorname) {  
  21.         System.out.println(colorname+"'s RGB Values are: "+red+","+green+","+blue);  
  22.     }  
  23. }  
  24.   
  25. public class ColorManager {  
  26.      private HashMap<String,ColorPrototype> colors = new HashMap<String,ColorPrototype>();  
  27.      public void put(String key,ColorPrototype cp)  
  28.      {  
  29.          colors.put(key, cp);  
  30.      }  
  31.      public ColorPrototype get(String key)  
  32.      {  
  33.          return  colors.get(key);  
  34.      }  
  35. }  

现在我们分析一下,这样带来了什么好处?首先从子类的数目上大大减少了,不需要再为每一种具体的颜色产品而定一个类和与它等级平行的工厂方法类,而 ColorTool 则扮演了原型管理器的角色。再看一下为客户程序的实现:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. public class Client {  
  2.     public static void main(String[] args) throws CloneNotSupportedException {  
  3.         ColorManager colormanager = new ColorManager();  
  4.         // 初始化颜色  
  5.         colormanager.put("red"new ConcteteColorPrototype(25500));  
  6.         colormanager.put("green"new ConcteteColorPrototype(02550));  
  7.         colormanager.put("blue"new ConcteteColorPrototype(00255));  
  8.         colormanager.put("angry"new ConcteteColorPrototype(255540));  
  9.         colormanager.put("peace"new ConcteteColorPrototype(128211128));  
  10.   
  11.         // 使用颜色  
  12.         String colorName = "red";  
  13.         ConcteteColorPrototype c1 = (ConcteteColorPrototype) colormanager.get(colorName).clonenew();  
  14.         c1.Display(colorName);  
  15.   
  16.         colorName = "green";  
  17.         ConcteteColorPrototype c2 = (ConcteteColorPrototype) colormanager.get(colorName).clonenew();  
  18.         c2.Display(colorName);  
  19.     }  
  20. }  

可以看到,客户程序通过注册原型实例就可以将一个具体产品类并入到系统中,在运行时刻,可以动态的建立和删除原型。

1.为什么需要Prototype模式?

引入原型模式的本质在于利用已有的一个原型对象,快速的生成和原型对象一样的实例。你有一个A的实例a:A a = new A();现在你想生成和car1一样的一个实例b,按照原型模式,应该是这样:A b = a.Clone();而不是重新再new一个A对象。通过上面这句话就可以得到一个和a一样的实例,确切的说,应该是它们的数据成员是一样的。Prototype模式同样是返回了一个A对象而没有使用new操作。

2.引入Prototype模式带来了什么好处?

可以看到,引入Prototype模式后我们不再需要一个与具体产品等级结构平行的工厂方法类,减少了类的构造,同时客户程序可以在运行时刻建立和删除原型。

3.Prototype模式满足了哪些面向对象的设计原则?

依赖倒置原则:上面的例子,原型管理器(ColorManager)仅仅依赖于抽象部分(ColorPrototype),而具体实现细节(ConcteteColorPrototype)则依赖与抽象部分(ColorPrototype),所以Prototype很好的满足了依赖倒置原则。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值