原型模式

74 阅读2分钟

背景

原型(prototype)模式可以在不指定类名的前提下生成实例

以下情况不能根据类来生成实例,要根据现有的实例来生成实例

  1. 对象种类繁多,无法将它们整合到一个类中

需要处理的对象过多,如果将它们分别作为一个类,必须要编写很多歌类文件

  1. 难以根据类生成实例时

生成实例的过程太过复杂,很难根据类来生成实例

  1. 想解耦框架与生成的实例时

要想让生成实例的框架不依赖于具体的类,这时,不能指定类名来生成实例,而要先“注册”一个原型实例,然后通过复制来生成该新的实例

登场角色

Prototype 原型

负责定义用于复制现有的实例生成新实例的方法

ConcretePrototype 具体的原型

ConcretePrototype 负责实现 用于复制现有的实例生成新实例的方法

Client 使用者

Client 角色负责使用复制实例的方法生成新的实例

示例代码

示例代码为以不同的形式来显示字符串

Product

/**
 * 产品的接口
 */
public interface Product {

    void use(String s);

    Product createClone();
}

MessageBox

public class MessageBox implements Product, Cloneable {
    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; i++) {
            System.out.print(decochar);
        }
        System.out.println();
        System.out.println(decochar + " " + s + " " + decochar);
        for (int i = 0; i < length + 4; i++) {
            System.out.println(decochar);
        }
        Object o = new Object();

        System.out.println();
    }

    @Override
    public Product createClone() {
        Product p = null;
        try {
            p = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}

UnderlinePen

public class UnderlinePen implements Product, Cloneable {
    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.println(ulchar);
        }

        System.out.println("");
    }

    @Override
    public Product createClone() {
        Product p = null;

        try {
            p = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}

Manager

public class Manager {

    private HashMap<String, Product> hashMap = new HashMap<>();


    public void register(String name, Product product) {
        hashMap.put(name, product);
    }

    public Product create(String name) {
        Product product = hashMap.get(name);
        return product.createClone();
    }
}

Main

public class Main {
    public static void main(String[] args) {
        Manager manager = new Manager();

        UnderlinePen underlinePen = new UnderlinePen('~');
        MessageBox sbox = new MessageBox('*');
        MessageBox mbox = new MessageBox('/');

        // 注册
        manager.register("strong message", underlinePen);
        manager.register("warning box", sbox);
        manager.register("slash box", mbox);

        // 生成
        Product p1 = manager.create("strong message");
        p1.use("hello world");
        Product p2 = manager.create("warning box");
        p2.use("hello world");
        Product p3 = manager.create("slash box");
        p3.use("hello world");
    }
}

类图

功能分析

  1. 当类的数量十分庞大时,源程序的管理也会变得十分困难,而原型模式可以将这些类集中在一起解决;
  2. 将框架从类名的束缚中解脱出来,因为一旦在代码中出现要使用的类的名字,就无法与该类分离开来,也无法实现复用;
  3. clone 方法实现的是浅复制,即字段对字段的复制;