原型模式 -- Prototype

2017-03-19 22:52:53   最后更新: 2017-03-19 22:52:53   访问数量:276




原型模式指的是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

也有时被人称为多例模式,通过对一个“原型”实例的克隆完成对象的创建

 

  1. 要实例化的类是在运行时指定的
  2. 需要创建一个与产品类层次平行的工厂类层次
  3. 一个类实例只能有几个不同状态组合中的一种

针对上述三种情况,我们只需要建立所需相应数目的原型并在运行时克隆他们,这样要比每次手工实例化该类更方便一些

 

 

 

如上图所示,Prototype 模式由下列组件构成:

  • Prototype -- 声明一个自身克隆接口的抽象类
  • ConcretePrototype -- 实现自身克隆操作的类
  • Client -- 调用原型的克隆操作从而实现一个新的对象

 

  1. ConcretePrototype 类向 client 隐藏了具体的产品类和创建细节,从而使客户端无需做任何改变即可使用与特定应用相关的类
  2. 允许只通过用户注册原型实例就可以讲一个新的具体产品类并入系统,因此比其他创建模式要灵活
  3. ConcretePrototype 中可以根据实际情况选择创建新的对象实例还是直接返回已有对象实例
  4. Prototype 模式应用最常见的就是 Spring 框架中 bean 的创建,虽然默认的 bean 是以单例模式创建的,但是我们可以通过指定 scope="Prototype" 来改变默认的创建方式,如果指定了以 Prototype 创建 bean,那么 web 框架会在运行时动态的通过克隆的方式创建类实例,这样可以极大地减少系统所需要的对象数目
  5. 通过克隆的方式创建对象,而不是通过一个工厂方法去产生一个新的对象,减少了 Creator 类层次,使结构更加简单清晰
  6. 克隆的过程中,可以动态地将配置信息装载到应用中,如果有这样的需求,就无法通过静态引用类的构造器来创建类了

 

但是,类内部包含一些不支持拷贝或有循环引用的对象时,实现克隆可能是很困难的

对于拥有实例变量的对象,又存在浅拷贝和深拷贝的问题,所谓的“浅拷贝”指的是只拷贝对象,而不拷贝他的实例变量,拷贝生成的对象与原对象共享这些实例变量,这样的实现是最简单的,但是可能具有安全性问题,而“深拷贝”则是指完全拷贝对象的所有成员,这样虽然复杂度大为提高,并且可能出现循环拷贝的问题,但是却保证了生成的对象的绝对独立,spring 框架的 Prototype 模式就是采用“深拷贝”的方式进行实例创建的

对于复杂的情况,创建出来的类可能需要根据实际情况进行不同的初始化,因此还需要提供一个 initialize 操作来完成他们独特的初始化工作

 

我们仍然采用此前的 MazeGame 作为我们的例子,我们将采用 AbstractFactory 与 Prototype 结合的模式,因此首先我们需要修改我们被用于拷贝的类,增加 clone 操作以及 initialize 操作(如果需要的话)

 

AbstractModel

package com.techlog.designpattern.mazegame.model; /** * 2017/3/12. * Created by techlog */ public abstract class AbstractModel { public abstract void enter(); public abstract AbstractModel clone(); }

 

 

Door

package com.techlog.designpattern.mazegame.model; import com.techlog.designpattern.mazegame.constant.DirectionEnum; import java.util.HashMap; import java.util.Map; import static com.techlog.designpattern.mazegame.constant.DirectionEnum.*; /** * 2017/3/12. * Created by techlog */ public class Door extends AbstractModel { @Override public void enter() { if (isOpen) { System.out.println("Enter Room Success"); } else { System.out.println("Enter Denied"); } } private void initialize(Room room1, Room room2, boolean isOpen) { this.room1 = room1; this.room2 = room2; this.isOpen = isOpen; } @Override public AbstractModel clone() { return new Door(); } public Door(Room room1, Room room2, boolean isOpen) { this.room1 = room1; this.room2 = room2; this.isOpen = isOpen; } public Door() { } public Room getRoom1() { return room1; } public void setRoom1(Room room1) { this.room1 = room1; } public Room getRoom2() { return room2; } public void setRoom2(Room room2) { this.room2 = room2; } public boolean isOpen() { return isOpen; } public void setOpen(boolean open) { isOpen = open; } private Room room1; private Room room2; private boolean isOpen; }

 

 

Room

package com.techlog.designpattern.mazegame.model; import com.techlog.designpattern.mazegame.constant.DirectionEnum; import java.util.Map; /** * 2017/3/12. * Created by techlog */ public class Room extends AbstractModel { public Room(int roomNO) { this.roomNO = roomNO; } public Room() { } private void initialize(int roomNO) { this.roomNO = roomNO; } @Override public AbstractModel clone() { return new Room(); } @Override public void enter() { System.out.println("enter room " + roomNO); } public AbstractModel getSide(DirectionEnum directionEnum) { return sides == null ? null : sides.get(directionEnum); } public void setSides(Map<DirectionEnum, AbstractModel> sides) { this.sides = sides; } public void setRoomNO(int roomNO) { this.roomNO = roomNO; } public int getRoomNO() { return roomNO; } private Map<DirectionEnum, AbstractModel> sides; private int roomNO; }

 

 

Wall

package com.techlog.designpattern.mazegame.model; /** * 2017/3/12. * Created by techlog */ public class Wall extends AbstractModel { @Override public void enter() { System.out.println("Enter Denied"); } @Override public AbstractModel clone() { return new Wall(); } }

 

 

可以看到,上面的代码中,在 Door 和 Room 中添加了 initialize 方法,因为他们需要使用运行时指定的参数作为创建参数

 

MazePrototypeFactory

那么,接下来我们就需要通过创建工厂方法来生成我们通过克隆而实例化的对象:

package com.techlog.designpattern.mazegame.factory; import com.techlog.designpattern.mazegame.model.Door; import com.techlog.designpattern.mazegame.model.Maze; import com.techlog.designpattern.mazegame.model.Room; import com.techlog.designpattern.mazegame.model.Wall; /** * 2017/3/19. * Created by techlog */ public class MazePrototypeFactory implements MazeFactory { @Override public Maze makeMaze() { return __prototypeMaze.clone(); } @Override public Wall makeWall() { return (Wall) __prototypeWall.clone(); } @Override public Room makeRoom(int roomNo) { Room room = (Room) __prototypeRoom.clone(); room.initialize(roomNo); return room; } @Override public Door makeDoor(Room room1, Room room2, boolean isOpen) { Door door = (Door) __prototypeDoor.clone(); door.initialize(room1, room2, isOpen); return door; } public MazePrototypeFactory (Maze __prototypeMaze, Door __prototypeDoor, Room __prototypeRoom, Wall __prototypeWall) { this.__prototypeMaze = __prototypeMaze; this.__prototypeDoor = __prototypeDoor; this.__prototypeRoom = __prototypeRoom; this.__prototypeWall = __prototypeWall; } private Maze __prototypeMaze; private Door __prototypeDoor; private Room __prototypeRoom; private Wall __prototypeWall; }

 

 






技术帖      龙潭书斋      java      面向对象      oop      spring      prototype      设计模式      模式      design pattern      原型      软件工程     


京ICP备15018585号