软件设计模式指南 创新设计模式:原型

设计模式第5部分

软件设计模式指南 创新设计模式:原型

Photo by Alex wong on Unsplash

原型模式是通过克隆现有实例来创建新对象时使用的五个创建模式之一。

用简单的英语来说,这仅表示您不使用new关键字来创建新实例,而是对现有对象进行了深克隆。 使用此模式有几个原因,但最重要的一个方法是避免在某些应用程序中以标准方式创建新对象的昂贵成本,例如,使用" new"关键字。

某些应用程序从数据源加载数据,它可以是数据库,文件等中的任何数据……如果您的应用程序需要加载数据,则每次创建新对象时加载相同的信息可能既费时又费力。 密集取决于大小。 这就是原型模式派上用场的地方。

例如,您的任务是设计和实施一个创建Staff的程序包。 工作人员包括教授,助理,保管人,实习生等……您的工作人员对象必须能够返回所有工作人员的姓名,并按姓名进行查找。 我们假设数据源中的所有名称都是唯一的。 现在想象一下,每次创建新对象时都必须打电话来加载工作人员的数据。 那可能是相当昂贵的操作。 我们可以使用原型模式来解决这个问题。

为了使对象可克隆,它需要实现Cloneable接口。 我们需要重写clone方法以对要克隆的对象执行深层复制。 如果您不熟悉克隆概念,建议您查看"浅拷贝与深拷贝"之间的区别。

我们不会从示例中的数据源中读取数据,而是为了简洁起见,我们将对一些值进行硬编码。 Staff类的代码如下所示。

<code>public class Staff implements Cloneable {    private List<string> staffNames;public Staff(){        this.staffNames = new ArrayList<>();        loadStaffNames();    }//simulates a database call to get all staff names    private void loadStaffNames(){        this.staffNames.add("Michael Bublé");        this.staffNames.add("Frank Sinatra");        this.staffNames.add("Mile Davis");        this.staffNames.add("Louis Armstrong");        this.staffNames.add("Nat King Cole");    }    public List<string> getStaffNames(){        return this.staffNames;    }        public String findStaffByName(String name){        return this.staffNames                .stream()                .filter(x -> x.equalsIgnoreCase(name))                .findFirst()                .orElse(null);    }    @Override    public Object clone() throws CloneNotSupportedException{        Staff copiedStaff = (Staff)super.clone();        this.staffNames.stream().forEach(                x -> copiedStaff.staffNames.add(x));        return copiedStaff;    }}/<string>/<string>/<code>


在此Staff类中,昂贵的操作在loadStaffNames方法中执行,该方法是一个私有方法,每次使用new关键字创建对象时都会调用该方法。 因此,如果需要使用相同的数据创建对象,则无需再次重新加载数据。 该模式提供了一种通过克隆现有对象来创建实例的方法。

在findStaffByName方法中,我们还使用相同的加载数据执行搜索。 如果您的应用程序需要一种从数据库或正在使用的数据源重新加载数据的方法,则您的类可以提供一种方法来执行此操作。

您仍然需要使用new关键字创建至少一个对象。 克隆某些对象意味着存在原始对象或现有对象。 一旦有了一个现有的对象,就可以在需要一个类的另一个实例时克隆它,而不必从头开始创建一个新的实例。 您想要这样做,是因为在我们的案例中,创建一个新数据库将再次调用数据库-或您试图限制的任何昂贵操作。

然后,您可以使用Staff类,克隆就是这样。

<code>public static void main(String[] args)  {    try {        Staff staff = new Staff();        System.out.println("number of staff in: "                    + staff.getStaffNames().size());        Staff copiedStaff = (Staff)staff.clone();        System.out.println("number of staff: "                    + copiedStaff.getStaffNames().size());        System.out.println(staff.hashCode());            System.out.println(copiedStaff.hashCode());    } catch (CloneNotSupportedException e) {        e.printStackTrace();    }}//---------------output----------------number of staff: 5number of staff: 521148892731025799482/<code>


每种解决方案始终各有利弊。 永远记住,解决所有问题的解决方案不只是一种。 因此,在考虑此模式时请使用最佳判断。

谢谢您的努力。 快乐的编码。


(本文翻译自Petey的文章《Creational Design Pattern: Prototype》,参考:https://medium.com/swlh/creational-design-pattern-prototype-9ee91bf111c8)


分享到:


相關文章: