zoukankan      html  css  js  c++  java
  • 13.原型模式(原型设计模式)详解

    在有些系统中,存在大量相同或相似对象的创建问题,如果用传统的构造函数来创建对象,会比较复杂且耗时耗资源,用原型模式生成对象就很高效,就像孙悟空拔下猴毛轻轻一吹就变出很多孙悟空一样简单。

    原型模式的定义与特点

    原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。例如,Windows 操作系统的安装通常较耗时,如果复制就快了很多。在生活中复制的例子非常多,这里不一一列举了。

    原型模式的结构与实现

    由于 Java 提供了对象的 clone() 方法,所以用 Java 实现原型模式很简单。

    1. 模式的结构

    原型模式包含以下主要角色。

    1. 抽象原型类:规定了具体原型对象必须实现的接口。
    2. 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
    3. 访问类:使用具体原型类中的 clone() 方法来复制新的对象。


    其结构图如图 1 所示。

    原型模式的结构图
    图1 原型模式的结构图

    2. 模式的实现

    原型模式的克隆分为浅克隆和深克隆,Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。其代码如下:

    1. //具体原型类
    2. class Realizetype implements Cloneable
    3. {
    4. Realizetype()
    5. {
    6. System.out.println("具体原型创建成功!");
    7. }
    8. public Object clone() throws CloneNotSupportedException
    9. {
    10. System.out.println("具体原型复制成功!");
    11. return (Realizetype)super.clone();
    12. }
    13. }
    14. //原型模式的测试类
    15. public class PrototypeTest
    16. {
    17. public static void main(String[] args)throws CloneNotSupportedException
    18. {
    19. Realizetype obj1=new Realizetype();
    20. Realizetype obj2=(Realizetype)obj1.clone();
    21. System.out.println("obj1==obj2?"+(obj1==obj2));
    22. }
    23. }


    程序的运行结果如下:

    具体原型创建成功!
    具体原型复制成功!
    obj1==obj2?false

    原型模式的应用实例

    【例1】用原型模式模拟“孙悟空”复制自己。

    分析:孙悟空拔下猴毛轻轻一吹就变出很多孙悟空,这实际上是用到了原型模式。这里的孙悟空类 SunWukong 是具体原型类,而 Java 中的 Cloneable 接口是抽象原型类。

    同前面介绍的猪八戒实例一样,由于要显示孙悟空的图像(点击此处下载该程序所要显示的孙悟空的图片),所以将孙悟空类定义成面板 JPanel 的子类,里面包含了标签,用于保存孙悟空的图像。

    另外,重写了 Cloneable 接口的 clone() 方法,用于复制新的孙悟空。访问类可以通过调用孙悟空的 clone() 方法复制多个孙悟空,并在框架窗体 JFrame 中显示。图 2 所示是其结构图。

    孙悟空生成器的结构图
    图2 孙悟空生成器的结构图


    程序代码如下:

    1. import java.awt.*;
    2. import javax.swing.*;
    3. class SunWukong extends JPanel implements Cloneable
    4. {
    5. private static final long serialVersionUID = 5543049531872119328L;
    6. public SunWukong()
    7. {
    8. JLabel l1=new JLabel(new ImageIcon("src/Wukong.jpg"));
    9. this.add(l1);
    10. }
    11. public Object clone()
    12. {
    13. SunWukong w=null;
    14. try
    15. {
    16. w=(SunWukong)super.clone();
    17. }
    18. catch(CloneNotSupportedException e)
    19. {
    20. System.out.println("拷贝悟空失败!");
    21. }
    22. return w;
    23. }
    24. }
    25. public class ProtoTypeWukong
    26. {
    27. public static void main(String[] args)
    28. {
    29. JFrame jf=new JFrame("原型模式测试");
    30. jf.setLayout(new GridLayout(1,2));
    31. Container contentPane=jf.getContentPane();
    32. SunWukong obj1=new SunWukong();
    33. contentPane.add(obj1);
    34. SunWukong obj2=(SunWukong)obj1.clone();
    35. contentPane.add(obj2);
    36. jf.pack();
    37. jf.setVisible(true);
    38. jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    39. }
    40. }


    程序的运行结果如图 3 所示。

    孙悟空克隆器的运行结果
    图3 孙悟空克隆器的运行结果


    用原型模式除了可以生成相同的对象,还可以生成相似的对象,请看以下实例。

    【例2】用原型模式生成“三好学生”奖状。

    分析:同一学校的“三好学生”奖状除了获奖人姓名不同,其他都相同,属于相似对象的复制,同样可以用原型模式创建,然后再做简单修改就可以了。图 4 所示是三好学生奖状生成器的结构图。

    奖状生成器的结构图
    图4 奖状生成器的结构图


    程序代码如下:

    1. public class ProtoTypeCitation
    2. {
    3. public static void main(String[] args) throws CloneNotSupportedException
    4. {
    5. citation obj1=new citation("张三","同学:在2016学年第一学期中表现优秀,被评为三好学生。","韶关学院");
    6. obj1.display();
    7. citation obj2=(citation) obj1.clone();
    8. obj2.setName("李四");
    9. obj2.display();
    10. }
    11. }
    12. //奖状类
    13. class citation implements Cloneable
    14. {
    15. String name;
    16. String info;
    17. String college;
    18. citation(String name,String info,String college)
    19. {
    20. this.name=name;
    21. this.info=info;
    22. this.college=college;
    23. System.out.println("奖状创建成功!");
    24. }
    25. void setName(String name)
    26. {
    27. this.name=name;
    28. }
    29. String getName()
    30. {
    31. return(this.name);
    32. }
    33. void display()
    34. {
    35. System.out.println(name+info+college);
    36. }
    37. public Object clone() throws CloneNotSupportedException
    38. {
    39. System.out.println("奖状拷贝成功!");
    40. return (citation)super.clone();
    41. }
    42. }


    程序运行结果如下:

    奖状创建成功!
    张三同学:在2016学年第一学期中表现优秀,被评为三好学生。韶关学院
    奖状拷贝成功!
    李四同学:在2016学年第一学期中表现优秀,被评为三好学生。韶关学院

    原型模式的应用场景

    原型模式通常适用于以下场景。

    • 对象之间相同或相似,即只是个别的几个属性不同的时候。
    • 对象的创建过程比较麻烦,但复制比较简单的时候。

    原型模式的扩展

    原型模式可扩展为带原型管理器的原型模式,它在原型模式的基础上增加了一个原型管理器 PrototypeManager 类。该类用 HashMap 保存多个复制的原型,Client 类可以通过管理器的 get(String id) 方法从中获取复制的原型。其结构图如图 5 所示。

    带原型管理器的原型模式的结构图
    图5 带原型管理器的原型模式的结构图


    【例3】用带原型管理器的原型模式来生成包含“圆”和“正方形”等图形的原型,并计算其面积。分析:本实例中由于存在不同的图形类,例如,“圆”和“正方形”,它们计算面积的方法不一样,所以需要用一个原型管理器来管理它们,图 6 所示是其结构图。

    图形生成器的结构图
    图6 图形生成器的结构图


    程序代码如下:

    import java.util.*;
    interface Shape extends Cloneable
    {
        public Object clone();    //拷贝
        public void countArea();    //计算面积
    }
    class Circle implements Shape
    {
        public Object clone()
        {
            Circle w=null;
            try
            {
                w=(Circle)super.clone();
            }
            catch(CloneNotSupportedException e)
            {
                System.out.println("拷贝圆失败!");
            }
            return w;
        }
        public void countArea()
        {
            int r=0;
            System.out.print("这是一个圆,请输入圆的半径:");
            Scanner input=new Scanner(System.in);
            r=input.nextInt();
            System.out.println("该圆的面积="+3.1415*r*r+"
    ");
        }
    }
    class Square implements Shape
    {
        public Object clone()
        {
            Square b=null;
            try
            {
                b=(Square)super.clone();
            }
            catch(CloneNotSupportedException e)
            {
                System.out.println("拷贝正方形失败!");
            }
            return b;
        }
        public void countArea()
        {
            int a=0;
            System.out.print("这是一个正方形,请输入它的边长:");
            Scanner input=new Scanner(System.in);
            a=input.nextInt();
            System.out.println("该正方形的面积="+a*a+"
    ");
        }
    }
    class ProtoTypeManager
    {
        private HashMap<String, Shape>ht=new HashMap<String,Shape>(); 
        public ProtoTypeManager()
        {
            ht.put("Circle",new Circle());
               ht.put("Square",new Square());
        } 
        public void addshape(String key,Shape obj)
        {
            ht.put(key,obj);
        }
        public Shape getShape(String key)
        {
            Shape temp=ht.get(key);
            return (Shape) temp.clone();
        }
    }
    public class ProtoTypeShape
    {
        public static void main(String[] args)
        {
            ProtoTypeManager pm=new ProtoTypeManager();    
            Shape obj1=(Circle)pm.getShape("Circle");
            obj1.countArea();          
            Shape obj2=(Shape)pm.getShape("Square");
            obj2.countArea();     
        }
    }


    运行结果如下所示:

     原文链接:http://c.biancheng.net/view/1343.html

  • 相关阅读:
    JAVA基础——编程练习(二)
    JAVA基础——面向对象三大特性:封装、继承、多态
    JVM内存
    50. Pow(x, n) (JAVA)
    47. Permutations II (JAVA)
    46. Permutations (JAVA)
    45. Jump Game II (JAVA)
    43. Multiply Strings (JAVA)
    42. Trapping Rain Water (JAVA)
    41. First Missing Positive (JAVA)
  • 原文地址:https://www.cnblogs.com/morganlin/p/12037877.html
Copyright © 2011-2022 走看看