前面提到抽象工厂的实现,这里说说抽象工厂的原型实现,与工厂方法的实现不同,原型实现有他自己的优点和缺点

原型的优点:

1. 效率:clone是native方法,比new的效率高,当使用复杂循环嵌套对象是尤为明显

2. 不需要为每一个新增的product创造一个具体factory

缺点:

1. 如果需要深复制,则需要手写所有包含循环引用对象的类的clone方法,因为需要手动在clone方法里对引用对象进行clone,否则是浅复制

2. 当需要改变一个克隆实例内部的值时,由于clone方法是无参方法,只能在clone完以后手动调用改变值得方法,且如果这个值是一个类的引用,则克隆应该建立在深复制的前提下,否则会污染原型数据

3. 原型工厂有可能被初始化成不兼容组件的组合,例如 CatHead和DogBody的组合,实际上这也是原型的一个灵活性的体现之一

4. 就Java而言,它的clone方法是protected方法,我们需要手动实现Clonable接口以后重写clone()方法将其改为public方法才能调用

下面是一个例子

工厂类,不在需要具体的工厂子类,而是通过构造方法设置原型来产生不同的工厂

package factory;

import product.Body;
import product.Eye;
import product.Head; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:33
* To change this template use File | Settings | File Templates.
*/
public class ModuleFactory {
private static ModuleFactory factory = new ModuleFactory();
private static Head _head; // 原型组件
private static Body _body;
private static Object lockObj = new Object(); // 设置原型
public static ModuleFactory createFactory(Head newHead, Body newBody) {
if (newHead == null || newBody == null)
throw new RuntimeException("Param newHead and newBody cannot be null"); // 为简单起见,不考虑多线程问题,不使用延迟加载
_head = newHead;
_body = newBody; return factory;
} public Head createHead() throws CloneNotSupportedException {
Head head = (Head) _head.clone();
return head;
} // 重载方法
public Head createHead(Eye eye) throws CloneNotSupportedException {
Head head = (Head) _head.clone();
// 必须在clone之后手动调用修改成员的方法
head.setEye(eye);
return head;
} public Body createBody() throws CloneNotSupportedException {
return (Body) _body.clone();
}
}

产品类

package product;

/**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:24
* To change this template use File | Settings | File Templates.
*/
public abstract class Head implements Cloneable {
private Eye eye = new Eye("defaultEye"); public Eye getEye() {
return eye;
} public void setEye(Eye eye) {
this.eye = eye;
} @Override
public Object clone() throws CloneNotSupportedException {
Head head = (Head) super.clone();
// 对内部对象进行深复制
head.setEye((Eye) eye.clone());
return head;
} public abstract void eat();
} package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:29
* To change this template use File | Settings | File Templates.
*/
public class DogHead extends Head {
@Override
public void eat() {
System.out.println("A dooog's head is eating with its eye " + getEye().getName());
}
} package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:29
* To change this template use File | Settings | File Templates.
*/
public class CatHead extends Head {
@Override
public void eat() {
System.out.println("A caaat's head is eating fast");
}
} package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:48
* To change this template use File | Settings | File Templates.
*/
public class Eye implements Cloneable{
private String name; @Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
} public Eye(String name) {
this.name = name;
} public void setName(String name) {
this.name = name;
} public String getName() {
return name;
}
} package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:24
* To change this template use File | Settings | File Templates.
*/
public abstract class Body implements Cloneable {
public abstract void dance(); // 此处必须将clone方法重新声明为public方法
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
} package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:27
* To change this template use File | Settings | File Templates.
*/
public class CatBody extends Body {
@Override
public void dance() {
System.out.println("A caaat's body is dancing crazily!!");
}
} package product; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:27
* To change this template use File | Settings | File Templates.
*/
public class DogBody extends Body {
@Override
public void dance() {
System.out.println("A dooog's body is dancing!");
}
}

测试类

import factory.ModuleFactory;
import product.*; /**
* Created with IntelliJ IDEA.
* User: zhenwei.liu
* Date: 13-8-1
* Time: 上午12:35
* To change this template use File | Settings | File Templates.
*/
public class Test { // 通过原型工厂克隆得到新的实例
// 与具体实现无关的解耦代码
private static void act(ModuleFactory factory) throws CloneNotSupportedException {
Head head = factory.createHead();
Body body = factory.createBody();
head.eat();
body.dance();
} public static void main(String[] args) throws CloneNotSupportedException {
Head head = new DogHead();
head.getEye().setName("customEye");
ModuleFactory factory = ModuleFactory.createFactory(head, new DogBody());
factory.createHead().eat(); // 测试深浅复制
Head head2 = (Head) head.clone();
head2.getEye().setName("smallEye");
head2.eat();
head.eat(); // 这里的输出发现eye并没有变成smallEye,所以可以确定eye是深复制 System.out.println();
factory = ModuleFactory.createFactory(new CatHead(), new CatBody());
act(factory);
}
}

输出

A dooog's head is eating with its eye customEye
A dooog's head is eating with its eye smallEye
A dooog's head is eating with its eye customEye A caaat's head is eating fast
A caaat's body is dancing crazily!!

从原型模式(Prototype Pattern)到 Clone的更多相关文章

  1. Net设计模式实例之原型模式( Prototype Pattern)

    一.原型模式简介(Brief Introduction) 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. Specify the kin ...

  2. 二十四种设计模式:原型模式(Prototype Pattern)

    原型模式(Prototype Pattern) 介绍用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象.示例有一个Message实体类,现在要克隆它. MessageModel usin ...

  3. 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)

    原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...

  4. 设计模式系列之原型模式(Prototype Pattern)——对象的克隆

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  5. 六个创建模式之原型模式(Prototype Pattern)

    定义: 使用原型实例指定创建对象的种类,并通过拷贝这个原型的属性创建新的对象. 结构图: Prototype:抽象原型类,声明克隆方法的接口,并是所有原型类的公共父类.在Java中,Object类为该 ...

  6. 原型模式(Prototype Pattern)

    用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. 它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的. 原型模式多用于创建复杂 ...

  7. C#设计模式——原型模式(Prototype Pattern)

    一.概述 在软件开发中,经常会碰上某些对象,其创建的过程比较复杂,而且随着需求的变化,其创建过程也会发生剧烈的变化,但他们的接口却能比较稳定.对这类对象的创建,我们应该遵循依赖倒置原则,即抽象不应该依 ...

  8. 2.6 《硬啃设计模式》第8章 复制不是很难 - 原型模式(Prototype Pattern)

    案例: 某即时战略游戏,你训练出来各种很强的战士. 为了增加游戏的可玩性,增加了一种复制魔法.实施该魔法,可以复制任意的战士. 你会怎样考虑这个设计? 在继续阅读之前,请先认真思考并写出你的设计,这样 ...

  9. 原型模式(Prototype Pattern)--对象的克隆

    定义:使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象; 原型类的核心在于如何实现克隆方法: 能够实现克隆的Java类必须实现一个标识接口Cloneable,表示这个类支持被复制; 通 ...

随机推荐

  1. MVC、MVP和MVVM的异同

    No1: Model一般用来保持程序的数据状态,比如数据存储.网络请求等 No2: Android开发中应用到MVC的地方:比如ListView与Adapter,如果把ListView看作View层, ...

  2. maven的统一版本管理实践

    为什么要使用maven的统一版本管理? 在进行项目开发的时候,我们使用maven来做项目的构建和管理.为了方便项目中各个模块之间的复用,项目通常会有多个模块构成.不同的模块,会各自应用自己需要的jar ...

  3. 理解事件(Event)

    Overview 在前几章,我们已经对委托有了一个完整的了解了,本章将会对事件进行一下介绍: 相对于委托,事件再是我们更加频繁的接触的,比如 鼠标的click 事件,键盘的 keydown 事件等等. ...

  4. iOS Sprite Kit教程之真机测试以及场景的添加与展示

    iOS Sprite Kit教程之真机测试以及场景的添加与展示 IOS实现真机测试 在进行真机测试之前,首先需要确保设备已经连在了Mac(或者Mac虚拟机)上,在第1.9.1小节开始,设备就一直连接在 ...

  5. 时间插件datetimepicker

    相关datetimepicker用法查看官网http://eonasdan.github.io/bootstrap-datetimepicker/ {% load staticfiles %} < ...

  6. wpf企业应用之主从结构列表

    主从结构在企业级应用中相当常见,这里结合我的例子谈一下wpf中主从结构列表展示的常用做法,具体效果见 wpf企业级开发中的几种常见业务场景. 首先,Model有两种,主表对应model(假设为mode ...

  7. 【十月のA Letter to 后辈菌】

    文化课没什么好说的,那就不说了吧(^▽^) 以下送给下两级的学弟学妹们: 马上就要NOIP了,现在自己从戏中人变成了看戏人.不管高一还是高二,我感觉只要能走到这一步就很了不起了,不管结果如何,比赛过程 ...

  8. 【20181102T1】优美的序列【二分+ST表】

    题面 [正解] 相当于是 \(GCD_{i=L}^{R} A_i = min_{i=L}^{R} \{A_i\}\) 然后GCD可以用ST表实现\(O(log A_i)\)查询 并且GCD是递减的,所 ...

  9. OI刷题记录(Updating)

    [Counter] [AGC]:0/96 [ARC]:0/70 [2016年省选]:0/69 [2017年省选]:22/75 [2018年省选]:0/63 [ZROI2018]:0/30 [ZROI2 ...

  10. 王彪-20162321-Java程序设计与数据结构2nd-第十周学习总结

    学习目标 讨论有向图和无向图 定义带权图并讨论它们的应用 定义图的广度优先遍历和深度优先遍历 定义最小生成树 讨论图的实现策略 书中图的基本定义 图是由结点及结点间的连接组成的,结点称为顶点,结点间的 ...