设计模式(Java)—Prototype模式

在Java中,我们可以使用new关键字指定类名来生成类的实例,像这样使用new来生成实例时,是必须指定类名的。但是,在开发过程中,有时候也会有”在不指定类名的前提下生成实例的需求”,例如,在以下情况下我们就不能根据类来生成实例,而是根据现有的实例来生成新的实例。
(1)对象种类繁多,无法将它们整合到一个类中时
(2)难以根据类生成实例时
生成实例的过程太过复杂,很难根据类来 生成实例,通常,在想生成一个和之前用户通过操作所创建出来的实例完全一样的实例的时候,我们会事先将用户通过操作所创建出来的实例保存起来,然后在需要时通过复制来生成新的实例。
(3)想解耦框架与生成的实例时
想要让生成实例的框架不依赖于具体的类,这时,不能指定类名来生成实例,要事先”注册一个原型的“实例,然后通过复制该实例来生成新的实例。
在Java中可以使用clone创建出实例的副本。
根据实力原型、实力模型来生成新的实例的模型就是Prototype模型。

示例程序:
将字符串放入方框中显示出来或是加上下划线显示出来。
这里写图片描述

Product接口:Product接口是复制功能的接口,该接口继承了java.lang.Cloneable接口(此接口是一个标记接口,其子类的实例都可使用clone方法来自动复制实例)

package Prototype;

//接口实现Cloneable接口,实现标记接口,实现的子类实例可使用clone方法
public interface Product extends Cloneable {
    public abstract void use(String s);
    public abstract Product creactClone();

}

Manager类:此类使用Product类接口来复制实例。showcase字段是java.util.HashMap类型,它保存了实例的名字和实例之间的对应关系。

package Prototype;

import java.util.HashMap;

//外部复制实例的接口,先注册,将实例对保存在HashMap中,再通过名称去除实例完成复制
public class Manager {
    private HashMap showcase = new HashMap();
    public void register(String name,Product p){
        showcase.put(name, p);
    }
    public Product create(String name){
        Product product = (Product)showcase.get(name);
        return product.creactClone();
    }

}

注:在Product接口和Manager类的代码中完全没有出现MessageBox类和UnderlinePen类的名字,这也意味着我们可以独立修改Product接口和Manager类,不受MessageBox类和UnderlinePen类的影响,这是非常重要的,因为一旦在类中使用到了类名,就意味着该类与其他类紧密地耦合在了一起。Product类接口成为了连接Manager类与其他具体类之间的桥梁。

MessageBox类:实现了Product接口

package Prototype;

//实现Product接口,实现具体的方法
public class MessageBox implements Product {
    private char decochar;
    public MessageBox(char decochar) {
        // TODO Auto-generated constructor stub
        this.decochar = decochar;
    }
    @Override
    public void use(String s) {
        // TODO Auto-generated method stub
        int lenght = s.getBytes().length;
        for(int i=0;i<lenght+4;i++){
            System.out.print(decochar);
        }
        System.out.println("");
        System.out.println(decochar+""+s+""+decochar);
        for(int i=0;i<lenght+4;i++){
            System.out.print(decochar);
        }
        System.out.println("");

    }

    @Override
    public Product creactClone() {
        // TODO Auto-generated method stub
        Product p = null;
        try {
            p = (Product)clone();
        } catch (CloneNotSupportedException e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return p;
    }

}

UnderlinePen类:实现了product接口

package Prototype;

public class UnderlinePen implements Product {
    private char ulchar;
    public UnderlinePen(char ulchar) {
        // TODO Auto-generated constructor stub
        this.ulchar = ulchar;
    }

    @Override
    public void use(String s) {
        // TODO Auto-generated method stub
        int lenght = s.getBytes().length;
        System.out.println("\""+s+"\"");
        for(int i=0;i<lenght;i++){
            System.out.print(ulchar);
        }
        System.out.println("");

    }

    @Override
    public Product creactClone() {
        // TODO Auto-generated method stub
        Product p = null;
        try {
            p = (Product)clone();
        } catch (CloneNotSupportedException e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return p;
    }

}

Main类:主程序接口

package Prototype;

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //创建manager实例,完成实例注册
        Manager manager = new Manager();
        UnderlinePen uPen = new UnderlinePen('~');
        MessageBox mBox1 = new MessageBox('*');
        MessageBox mBox2 = new MessageBox('/');
        manager.register("strong name", uPen);
        manager.register("warning box", mBox1);
        manager.register("slash box", mBox2);

        //通过注册信息中的实例复制实例,然后才能使用实例功能
        Product p1 = manager.create("strong name");
        p1.use("hello world");
        Product p2 = manager.create("warning box");
        p2.use("hello world");
        Product p3 = manager.create("slash box");
        p3.use("hello world");


    }

}

注:

浅复制(浅克隆)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

clone()方法:
1.首先我们需要知道Object类中一个clone()的方法,并且是protected关键字修饰的本地方法(使用native关键字修饰),我们完成克隆需要重写该方法。
注意:按照惯例重写的时候一个要将protected修饰符修改为public,这是JDK所推荐的做法,但是我测试了一下,
复写的时候不修改为public也是能够完成拷贝的。但是还是推荐写成public。

2.我们重写的clone方法一个要实现Cloneable接口。虽然这个接口并没有什么方法,但是必须实现该标志接口。
如果不实现将会在运行期间抛出:CloneNotSupportedException异常

3.Object中本地clone()方法,默认是浅拷贝

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值