原型模式(Prototype)

1、什么是原型模式

当我们要生成一个实例的时候,我们会怎么做呢?

new Some()

在上面这个语句中,我们需要指定一个类名“some”来创建这个实例,但在这个设计模式中,我们可以在不指定类名的情况下生成实例,而是根据现有的实例来生成实例,即通过“实例”生成“实例”,在模式中,可以借助clone方法与Cloneable接口实现。

2、何时需要原型模式

在我们一开始的不太复杂JAVA编程中,我们会对每个需求不同的实例都编写一个类来用new来生成他的实例。但当程序越来越复杂,所需要的类会越来越多,实际上,当你遇到以下几种情况,都可以使用原型设计模式。

1)对象种类多,无法整合到一个类中

当一个对象需要满足许多不同的需求,而你又无法整合到一个类中的时候,你必然要重新分作一个类,而这样必然导致你要编写很多个类文件。

2)难以根据类生成实例时

当某个类能通过用户进行操作而得到的另一个类时,即这个对象所需要的类是我们无法预计的,无法在事先设计出来一个一模一样的类,比如当某个对象是用户通过某些操作后的修改过得到的实例,现在需要创造一个能生成和这个修改过的实例完全一样的实例的类时,虽然听上去有点绕,但这个时候我们就可以使用原型设计模式。

用一个例子来说,用某张试卷当作原件,打印出来后通过学生填写。再将这份已经填写的试卷当作原件来打印。

3)想解耦框架与生成的实例时

这种情况是我们想让生成实例的框架不依赖于具体的类。用2)中的例子来说,就是想用这份已经填写的试卷,让其他学生对试卷进行补充,而不再依赖空白的原卷。将框架与生成的实例解耦。

3、示例程序

需求一:需要存储用于创建“以任意字符为方框输出任意字符串的实例”的对象。 需求二:需要存储用于创建“以任意字符为下划线输出任意字符串实例”的对象。

总体:定义一个有use方法的product抽象类,而实例中应该有自带的实现clone方法,Manager类对继承抽象类product的子类进行注册和创建。product中有不可重写的方法createclone来返回克隆自身的实例。因为两个需求的实现方式不一样,一个需要方框,一个需要下划线,所以需要分别用两个不同的类MessageBox和UnderlinePen来继承product将use重写。

类名作用类型
Product声明了抽象方法use和实现createClone的抽象类abstract
Manager调用createClone方法复制实例的类class
MessageBox方框内显示字符串,继承Product重写use方法class
UnderlinePen下划线显示字符串,继承Product重写use方法class
Prototype_main程序测试入口main
public abstract class Product implements Cloneable {
    public abstract void use(String s);
    public final Product createClone() {
        Product p = null;
        try{
            p = (Product)clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return p;
    }
}
public class Manager {
    private HashMap showcase = new HashMap();
    public void register(String name,Product proto){
        showcase.put(name,proto);
    }
    public Product create(String protoname){
        Product p = (Product)showcase.get(protoname);
        return p.createClone();
    }
}
public class MessageBox extends Product {
    private char decochar;
    public MessageBox(char decochar){
        this.decochar = decochar;
    }
    @Override
    public void use(String s) {
        int length = s.getBytes().length;
        for (int i = 0;i<length + 4;i++){
            System.out.print(decochar);
        }
        System.out.println("");
        System.out.println(decochar + " " + s + " " + decochar);
        for ( int i = 0;i<length+4;i++){
            System.out.print(decochar);
        }
        System.out.println("");
    }
}
public class UnderlinePen extends Product {
    private char ulchar;
    public UnderlinePen(char ulchar){
        this.ulchar = ulchar;
    }
    @Override
    public void use(String s) {
        int length = s.getBytes().length;
        System.out.println("\"" + s + "\"");
        System.out.print(" ");
        for(int i = 0; i < length;i++){
            System.out.print(ulchar);
        }
        System.out.println("");
    }
}
public class Prototype_main {
    public static void main(String []args){
        Manager manager = new Manager();
        UnderlinePen upen = new UnderlinePen('~');
        MessageBox mbox = new MessageBox('*');
        MessageBox sbox = new MessageBox('/');
        manager.register("strong message",upen);
        manager.register("warning box",mbox);
        manager.register("slash box",sbox);

        Product p1 = manager.create("strong message");
        Product p2 = manager.create("warning box");
        Product p3 = manager.create("slash box");

        p1.use("Hello, world");
        p2.use("Hello, world");
        p3.use("Hello, world");
    }
}

运行结果

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×