设计模式-04原型模式Prototype Pattern
·
原型模式 (Prototype Pattern)
模式概述 (Pattern Overview)
原型模式是一种创建型设计模式,它使你能够复制已有对象,而无需使代码依赖它们所属的类。
意图 (Intent)
用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
适用场景 (When to Use)
- 当系统应该独立于它的产品创建、构成和表示时
- 当要实例化的类是在运行时刻指定时,例如通过动态装载
- 为了避免创建一个与产品类层次平行的工厂类层次时
- 当一个类的实例只能有几个不同状态组合中的一种时
UML类图 (UML Class Diagram)
实现方式 (Implementation Approaches)
1. 浅克隆 (Shallow Clone)
/**
* 原型接口
* Prototype Interface
*/
public interface Prototype {
Prototype clone();
}
/**
* 具体原型类 - 文档
* Concrete Prototype Class - Document
*/
public class Document implements Prototype, Cloneable {
private String title;
private String content;
private List<String> authors;
private Date creationDate;
public Document(String title, String content, List<String> authors) {
this.title = title;
this.content = content;
this.authors = new ArrayList<>(authors);
this.creationDate = new Date();
}
/**
* 浅克隆实现
* Shallow clone implementation
*/
@Override
public Prototype clone() {
try {
// 调用Object的clone方法
Document cloned = (Document) super.clone();
// 注意:authors列表是浅复制
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("克隆失败", e);
}
}
/**
* 深克隆实现
* Deep clone implementation
*/
public Document deepClone() {
try {
Document cloned = (Document) super.clone();
// 深复制authors列表
cloned.authors = new ArrayList<>(this.authors);
// 深复制日期
cloned.creationDate = new Date(this.creationDate.getTime());
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("深克隆失败", e);
}
}
// Getters and setters
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public List<String> getAuthors() { return authors; }
public void setAuthors(List<String> authors) { this.authors = authors; }
public Date getCreationDate() { return creationDate; }
public void setCreationDate(Date creationDate) { this.creationDate = creationDate; }
@Override
public String toString() {
return "Document{" +
"title='" + title + '\'' +
", content='" + content + '\'' +
", authors=" + authors +
", creationDate=" + creationDate +
'}';
}
}
/**
* 客户端代码
* Client Code
*/
public class PrototypeClient {
public static void main(String[] args) {
// 创建原始文档
List<String> authors = Arrays.asList("张三", "李四");
Document originalDoc = new Document("设计文档", "这是一个重要的设计文档", authors);
System.out.println("原始文档: " + originalDoc);
// 浅克隆
Document shallowClone = (Document) originalDoc.clone();
System.out.println("浅克隆文档: " + shallowClone);
// 修改克隆文档的内容
shallowClone.setTitle("修改后的设计文档");
shallowClone.getAuthors().add("王五"); // 这会影响原始文档!
System.out.println("\n修改后:");
System.out.println("原始文档: " + originalDoc);
System.out.println("浅克隆文档: " + shallowClone);
System.out.println("\n--- 深克隆演示 ---\n");
// 深克隆
Document deepClone = originalDoc.deepClone();
deepClone.setTitle("深克隆设计文档");
deepClone.getAuthors().add("赵六"); // 这不会影响原始文档
System.out.println("原始文档: " + originalDoc);
System.out.println("深克隆文档: " + deepClone);
}
}
2. 序列化实现深克隆 (Serialization-based Deep Clone)
import java.io.*;
import java.util.*;
/**
* 使用序列化实现深克隆的工具类
* Utility class for deep cloning using serialization
*/
public class SerializationUtils {
/**
* 深克隆对象
* Deep clone an object
*/
@SuppressWarnings("unchecked")
public static <T extends Serializable> T deepClone(T object) {
try {
// 将对象写入字节数组输出流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(object);
oos.flush();
oos.close();
// 从字节数组输入流读取对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
T clonedObject = (T) ois.readObject();
ois.close();
return clonedObject;
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException("深克隆失败", e);
}
}
}
/**
* 可序列化的复杂对象
* Serializable Complex Object
*/
public class ComplexObject implements Serializable {
private String name;
private int age;
private List<String> hobbies;
private Map<String, Object> attributes;
private NestedObject nestedObject;
public ComplexObject(String name, int age) {
this.name = name;
this.age = age;
this.hobbies = new ArrayList<>();
this.attributes = new HashMap<>();
this.nestedObject = new NestedObject("nested");
}
// 使用序列化工具进行深克隆
public ComplexObject deepClone() {
return SerializationUtils.deepClone(this);
}
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public List<String> getHobbies() { return hobbies; }
public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; }
public Map<String, Object> getAttributes() { return attributes; }
public void setAttributes(Map<String, Object> attributes) { this.attributes = attributes; }
public NestedObject getNestedObject() { return nestedObject; }
public void setNestedObject(NestedObject nestedObject) { this.nestedObject = nestedObject; }
@Override
public String toString() {
return "ComplexObject{" +
"name='" + name + '\'' +
", age=" + age +
", hobbies=" + hobbies +
", attributes=" + attributes +
", nestedObject=" + nestedObject +
'}';
}
}
/**
* 嵌套对象
* Nested Object
*/
class NestedObject implements Serializable {
private String data;
public NestedObject(String data) {
this.data = data;
}
public String getData() { return data; }
public void setData(String data) { this.data = data; }
@Override
public String toString() {
return "NestedObject{" +
"data='" + data + '\'' +
'}';
}
}
/**
* 客户端代码
* Client Code
*/
public class SerializationCloneClient {
public static void main(String[] args) {
// 创建复杂对象
ComplexObject original = new ComplexObject("张三", 25);
original.getHobbies().add("读书");
original.getHobbies().add("游泳");
original.getAttributes().put("city", "北京");
original.getAttributes().put("profession", "工程师");
System.out.println("原始对象: " + original);
// 深克隆
ComplexObject cloned = original.deepClone();
// 修改克隆对象
cloned.setName("李四");
cloned.getHobbies().add("编程");
cloned.getAttributes().put("city", "上海");
cloned.getNestedObject().setData("modified nested");
System.out.println("\n修改后的克隆对象: " + cloned);
System.out.println("原始对象: " + original);
// 验证深克隆成功 - 原始对象不受影响
System.out.println("\n验证深克隆:");
System.out.println("原始对象hobbies数量: " + original.getHobbies().size());
System.out.println("克隆对象hobbies数量: " + cloned.getHobbies().size());
System.out.println("原始对象city: " + original.getAttributes().get("city"));
System.out.println("克隆对象city: " + cloned.getAttributes().get("city"));
}
}
3. 原型注册表 (Prototype Registry)
import java.util.*;
/**
* 原型接口
* Prototype Interface
*/
public interface Shape extends Cloneable {
Shape clone();
void draw();
double getArea();
}
/**
* 具体原型 - 圆形
* Concrete Prototype - Circle
*/
public class Circle implements Shape {
private double radius;
private String color;
public Circle(double radius, String color) {
this.radius = radius;
this.color = color;
}
@Override
public Shape clone() {
try {
return (Circle) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("克隆失败", e);
}
}
@Override
public void draw() {
System.out.println("绘制" + color + "圆形,半径: " + radius);
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
public void setRadius(double radius) { this.radius = radius; }
public void setColor(String color) { this.color = color; }
}
/**
* 具体原型 - 矩形
* Concrete Prototype - Rectangle
*/
public class Rectangle implements Shape {
private double width;
private double height;
private String color;
public Rectangle(double width, double height, String color) {
this.width = width;
this.height = height;
this.color = color;
}
@Override
public Shape clone() {
try {
return (Rectangle) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("克隆失败", e);
}
}
@Override
public void draw() {
System.out.println("绘制" + color + "矩形,宽: " + width + ", 高: " + height);
}
@Override
public double getArea() {
return width * height;
}
public void setWidth(double width) { this.width = width; }
public void setHeight(double height) { this.height = height; }
public void setColor(String color) { this.color = color; }
}
/**
* 原型注册表
* Prototype Registry
*/
public class ShapeRegistry {
private Map<String, Shape> prototypes = new HashMap<>();
/**
* 注册原型
* Register prototype
*/
public void registerPrototype(String key, Shape prototype) {
prototypes.put(key, prototype);
}
/**
* 获取原型
* Get prototype
*/
public Shape getPrototype(String key) {
Shape prototype = prototypes.get(key);
if (prototype == null) {
throw new IllegalArgumentException("未找到原型: " + key);
}
return prototype.clone();
}
/**
* 获取所有原型键
* Get all prototype keys
*/
public Set<String> getPrototypeKeys() {
return prototypes.keySet();
}
}
/**
* 客户端代码
* Client Code
*/
public class PrototypeRegistryClient {
public static void main(String[] args) {
// 创建原型注册表
ShapeRegistry registry = new ShapeRegistry();
// 注册原型
registry.registerPrototype("red-circle", new Circle(5.0, "红色"));
registry.registerPrototype("blue-circle", new Circle(3.0, "蓝色"));
registry.registerPrototype("green-rectangle", new Rectangle(4.0, 6.0, "绿色"));
registry.registerPrototype("yellow-rectangle", new Rectangle(2.0, 3.0, "黄色"));
System.out.println("可用原型: " + registry.getPrototypeKeys());
// 使用原型创建对象
Shape redCircle = registry.getPrototype("red-circle");
redCircle.draw();
System.out.println("面积: " + redCircle.getArea());
// 修改克隆对象
Shape modifiedCircle = registry.getPrototype("red-circle");
modifiedCircle.setRadius(10.0);
modifiedCircle.setColor("紫色");
modifiedCircle.draw();
// 创建多个矩形
for (int i = 0; i < 3; i++) {
Shape rectangle = registry.getPrototype("green-rectangle");
rectangle.setWidth(rectangle.getArea() / (i + 1)); // 修改宽度
rectangle.draw();
}
}
}
知名框架案例 (Framework Examples)
1. Spring Framework - @Scope(“prototype”)
/**
* Spring中原型作用域的使用
* Prototype Scope Usage in Spring
*/
@Component
public class SpringPrototypeExample {
/**
* 原型Bean - 每次注入都创建新实例
* Prototype Bean - New instance created on each injection
*/
@Component
@Scope("prototype")
public static class PrototypeBean {
private final String id = UUID.randomUUID().toString();
private final Date creationTime = new Date();
@PostConstruct
public void init() {
System.out.println("原型Bean创建: " + id + " at " + creationTime);
}
public String getId() { return id; }
public Date getCreationTime() { return creationTime; }
}
/**
* 单例Bean - 使用原型Bean
* Singleton Bean - Using Prototype Bean
*/
@Component
public static class SingletonBean {
@Autowired
private ApplicationContext applicationContext;
public void demonstratePrototype() {
System.out.println("\n=== 演示原型作用域 ===");
// 每次getBean都会创建新的原型实例
PrototypeBean bean1 = applicationContext.getBean(PrototypeBean.class);
PrototypeBean bean2 = applicationContext.getBean(PrototypeBean.class);
PrototypeBean bean3 = applicationContext.getBean(PrototypeBean.class);
System.out.println("Bean1 ID: " + bean1.getId());
System.out.println("Bean2 ID: " + bean2.getId());
System.out.println("Bean3 ID: " + bean3.getId());
// 验证它们是不同的实例
System.out.println("bean1 == bean2: " + (bean1 == bean2));
System.out.println("bean1.equals(bean2): " + bean1.equals(bean2));
}
}
/**
* 原型工厂方法
* Prototype Factory Method
*/
@Configuration
public static class PrototypeConfig {
@Bean
@Scope("prototype")
public RequestContext requestContext() {
return new RequestContext(UUID.randomUUID().toString(), new Date());
}
@Bean
@Scope("prototype")
public ProcessingContext processingContext(String requestId) {
ProcessingContext context = new ProcessingContext();
context.setRequestId(requestId);
context.setStartTime(System.currentTimeMillis());
return context;
}
}
@Data
@AllArgsConstructor
public static class RequestContext {
private String requestId;
private Date timestamp;
}
@Data
public static class ProcessingContext {
private String requestId;
private long startTime;
private Map<String, Object> attributes = new HashMap<>();
}
}
2. Netty - ChannelConfig
/**
* Netty中ChannelConfig的原型模式使用
* Prototype Pattern usage of ChannelConfig in Netty
*/
public class NettyPrototypeExample {
public static void main(String[] args) {
// 创建基础配置
ChannelConfig baseConfig = new DefaultChannelConfig(null);
baseConfig.setOption(ChannelOption.SO_BACKLOG, 128);
baseConfig.setOption(ChannelOption.SO_KEEPALIVE, true);
baseConfig.setOption(ChannelOption.TCP_NODELAY, true);
// 创建ServerBootstrap并复制配置
ServerBootstrap bootstrap1 = new ServerBootstrap();
bootstrap1.option(ChannelOption.SO_BACKLOG, 128)
.option(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.TCP_NODELAY, true);
ServerBootstrap bootstrap2 = new ServerBootstrap();
bootstrap2.option(ChannelOption.SO_BACKLOG, 256) // 不同的配置
.option(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.TCP_NODELAY, true);
// 基于原型创建多个相似的配置
Map<ChannelOption<?>, Object> baseOptions = new HashMap<>();
baseOptions.put(ChannelOption.SO_BACKLOG, 128);
baseOptions.put(ChannelOption.SO_KEEPALIVE, true);
baseOptions.put(ChannelOption.TCP_NODELAY, true);
// 创建多个ServerBootstrap,基于相同的原型配置
for (int i = 0; i < 3; i++) {
final int port = 8080 + i;
ServerBootstrap bootstrap = new ServerBootstrap();
// 复制基础配置
baseOptions.forEach(bootstrap::option);
// 添加特定的配置
bootstrap.option(ChannelOption.SO_RCVBUF, 1024 * (i + 1));
bootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup())
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) {
ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
System.out.println("Port " + port + " received: " + msg);
}
});
}
});
bootstrap.bind(port).addListener(future -> {
if (future.isSuccess()) {
System.out.println("Server started on port " + port);
}
});
}
}
/**
* 自定义原型配置
* Custom Prototype Configuration
*/
public static class PrototypeChannelConfig {
private final Map<ChannelOption<?>, Object> options;
public PrototypeChannelConfig() {
this.options = new HashMap<>();
// 设置默认配置
options.put(ChannelOption.SO_BACKLOG, 128);
options.put(ChannelOption.SO_KEEPALIVE, true);
options.put(ChannelOption.TCP_NODELAY, true);
}
public PrototypeChannelConfig copy() {
PrototypeChannelConfig copy = new PrototypeChannelConfig();
copy.options.putAll(this.options);
return copy;
}
public PrototypeChannelConfig withOption(ChannelOption<?> option, Object value) {
PrototypeChannelConfig copy = this.copy();
copy.options.put(option, value);
return copy;
}
public void applyTo(ServerBootstrap bootstrap) {
options.forEach(bootstrap::option);
}
}
}
3. MyBatis - CacheKey
/**
* MyBatis中CacheKey的原型模式使用
* Prototype Pattern usage of CacheKey in MyBatis
*/
public class MyBatisCacheKeyExample {
/**
* 演示CacheKey的克隆
* Demonstrate CacheKey cloning
*/
public static void demonstrateCacheKeyClone() {
// 创建原始CacheKey
CacheKey originalKey = new CacheKey();
originalKey.update("select * from users");
originalKey.update(1); // 参数1
originalKey.update("active"); // 参数2
System.out.println("原始CacheKey: " + originalKey);
System.out.println("原始CacheKey哈希值: " + originalKey.hashCode());
// 克隆CacheKey
CacheKey clonedKey = originalKey.clone();
System.out.println("克隆CacheKey: " + clonedKey);
System.out.println("克隆CacheKey哈希值: " + clonedKey.hashCode());
System.out.println("CacheKey相等: " + originalKey.equals(clonedKey));
// 修改克隆的CacheKey
clonedKey.update("modified");
System.out.println("修改后的克隆CacheKey: " + clonedKey);
System.out.println("原始CacheKey不受影响: " + originalKey);
}
/**
* 自定义缓存键建造者
* Custom Cache Key Builder
*/
public static class CacheKeyBuilder {
private String statement;
private List<Object> parameters = new ArrayList<>();
private int offset = 0;
private int limit = Integer.MAX_VALUE;
public CacheKeyBuilder statement(String statement) {
this.statement = statement;
return this;
}
public CacheKeyBuilder parameter(Object parameter) {
this.parameters.add(parameter);
return this;
}
public CacheKeyBuilder parameters(Object... params) {
this.parameters.addAll(Arrays.asList(params));
return this;
}
public CacheKeyBuilder pagination(int offset, int limit) {
this.offset = offset;
this.limit = limit;
return this;
}
public CacheKey build() {
CacheKey cacheKey = new CacheKey();
cacheKey.update(statement);
for (Object param : parameters) {
cacheKey.update(param);
}
cacheKey.update(offset);
cacheKey.update(limit);
return cacheKey;
}
public CacheKey buildFromPrototype(CacheKey prototype) {
CacheKey newKey = prototype.clone();
newKey.update(statement);
for (Object param : parameters) {
newKey.update(param);
}
newKey.update(offset);
newKey.update(limit);
return newKey;
}
}
}
4. Logback - LoggingEvent
/**
* Logback中LoggingEvent的原型模式概念
* Prototype Pattern concept in LoggingEvent of Logback
*/
public class LogbackEventExample {
/**
* 自定义日志事件原型
* Custom Logging Event Prototype
*/
public static class LoggingEventPrototype implements Cloneable {
private String loggerName;
private Level level;
private String message;
private long timestamp;
private Map<String, String> mdc;
private List<Object> arguments;
public LoggingEventPrototype(String loggerName, Level level, String message) {
this.loggerName = loggerName;
this.level = level;
this.message = message;
this.timestamp = System.currentTimeMillis();
this.mdc = new HashMap<>();
this.arguments = new ArrayList<>();
}
@Override
public LoggingEventPrototype clone() {
try {
LoggingEventPrototype cloned = (LoggingEventPrototype) super.clone();
// 深复制MDC和参数列表
cloned.mdc = new HashMap<>(this.mdc);
cloned.arguments = new ArrayList<>(this.arguments);
cloned.timestamp = System.currentTimeMillis();
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("克隆失败", e);
}
}
// 建造者模式结合原型模式
public static class Builder {
private String loggerName;
private Level level;
private String message;
private Map<String, String> mdc = new HashMap<>();
private List<Object> arguments = new ArrayList<>();
public Builder loggerName(String loggerName) {
this.loggerName = loggerName;
return this;
}
public Builder level(Level level) {
this.level = level;
return this;
}
public Builder message(String message) {
this.message = message;
return this;
}
public Builder mdc(String key, String value) {
this.mdc.put(key, value);
return this;
}
public Builder argument(Object arg) {
this.arguments.add(arg);
return this;
}
public LoggingEventPrototype build() {
LoggingEventPrototype event = new LoggingEventPrototype(loggerName, level, message);
event.mdc.putAll(this.mdc);
event.arguments.addAll(this.arguments);
return event;
}
public LoggingEventPrototype buildFromPrototype(LoggingEventPrototype prototype) {
LoggingEventPrototype event = prototype.clone();
if (loggerName != null) event.loggerName = loggerName;
if (level != null) event.level = level;
if (message != null) event.message = message;
event.mdc.putAll(this.mdc);
event.arguments.addAll(this.arguments);
return event;
}
}
// Getters
public String getLoggerName() { return loggerName; }
public Level getLevel() { return level; }
public String getMessage() { return message; }
public long getTimestamp() { return timestamp; }
public Map<String, String> getMdc() { return new HashMap<>(mdc); }
public List<Object> getArguments() { return new ArrayList<>(arguments); }
@Override
public String toString() {
return "LoggingEventPrototype{" +
"loggerName='" + loggerName + '\'' +
", level=" + level +
", message='" + message + '\'' +
", timestamp=" + timestamp +
", mdc=" + mdc +
", arguments=" + arguments +
'}';
}
}
public static void main(String[] args) {
// 创建原型
LoggingEventPrototype prototype = new LoggingEventPrototype("com.example", Level.INFO, "应用启动");
prototype.getMdc().put("requestId", "12345");
prototype.getArguments().add("arg1");
System.out.println("原始原型: " + prototype);
// 克隆原型
LoggingEventPrototype cloned = prototype.clone();
cloned.setMessage("应用运行中");
cloned.getMdc().put("userId", "user123");
System.out.println("克隆对象: " + cloned);
System.out.println("原始原型: " + prototype);
}
}
5. Hibernate - Query
/**
* Hibernate中Query的原型模式使用
* Prototype Pattern usage of Query in Hibernate
*/
public class HibernateQueryExample {
/**
* 自定义查询原型
* Custom Query Prototype
*/
public static class QueryPrototype implements Cloneable {
private String hql;
private Map<String, Object> parameters = new HashMap<>();
private int firstResult = 0;
private int maxResults = -1;
private boolean cacheable = false;
private String cacheRegion;
public QueryPrototype(String hql) {
this.hql = hql;
}
@Override
public QueryPrototype clone() {
try {
QueryPrototype cloned = (QueryPrototype) super.clone();
cloned.parameters = new HashMap<>(this.parameters);
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("克隆失败", e);
}
}
// 建造者模式结合原型模式
public static class Builder {
private String hql;
private Map<String, Object> parameters = new HashMap<>();
private int firstResult = 0;
private int maxResults = -1;
private boolean cacheable = false;
private String cacheRegion;
public Builder(String hql) {
this.hql = hql;
}
public Builder parameter(String name, Object value) {
this.parameters.put(name, value);
return this;
}
public Builder parameters(Map<String, Object> params) {
this.parameters.putAll(params);
return this;
}
public Builder firstResult(int firstResult) {
this.firstResult = firstResult;
return this;
}
public Builder maxResults(int maxResults) {
this.maxResults = maxResults;
return this;
}
public Builder cacheable(boolean cacheable) {
this.cacheable = cacheable;
return this;
}
public Builder cacheRegion(String cacheRegion) {
this.cacheRegion = cacheRegion;
return this;
}
public QueryPrototype build() {
QueryPrototype query = new QueryPrototype(hql);
query.parameters.putAll(this.parameters);
query.firstResult = this.firstResult;
query.maxResults = this.maxResults;
query.cacheable = this.cacheable;
query.cacheRegion = this.cacheRegion;
return query;
}
public QueryPrototype buildFromPrototype(QueryPrototype prototype) {
QueryPrototype query = prototype.clone();
if (hql != null) query.hql = hql;
query.parameters.putAll(this.parameters);
if (firstResult != 0) query.firstResult = this.firstResult;
if (maxResults != -1) query.maxResults = this.maxResults;
query.cacheable = this.cacheable;
query.cacheRegion = this.cacheRegion;
return query;
}
}
// Getters and business methods
public String getHql() { return hql; }
public Map<String, Object> getParameters() { return new HashMap<>(parameters); }
public int getFirstResult() { return firstResult; }
public int getMaxResults() { return maxResults; }
public boolean isCacheable() { return cacheable; }
public String getCacheRegion() { return cacheRegion; }
public void setParameter(String name, Object value) {
this.parameters.put(name, value);
}
public void execute() {
System.out.println("执行查询: " + hql);
System.out.println("参数: " + parameters);
System.out.println("分页: " + firstResult + ", " + maxResults);
System.out.println("缓存: " + cacheable + ", " + cacheRegion);
}
@Override
public String toString() {
return "QueryPrototype{" +
"hql='" + hql + '\'' +
", parameters=" + parameters +
", firstResult=" + firstResult +
", maxResults=" + maxResults +
", cacheable=" + cacheable +
", cacheRegion='" + cacheRegion + '\'' +
'}';
}
}
public static void main(String[] args) {
// 创建基础查询原型
QueryPrototype baseQuery = new QueryPrototype("FROM User u WHERE u.status = :status");
baseQuery.setParameter("status", "active");
baseQuery.setCacheable(true);
System.out.println("基础查询原型: " + baseQuery);
// 基于原型创建不同的查询
QueryPrototype pagedQuery = baseQuery.clone();
pagedQuery.setParameter("page", 1);
pagedQuery.setFirstResult(0);
pagedQuery.setMaxResults(10);
QueryPrototype cachedQuery = baseQuery.clone();
cachedQuery.setCacheRegion("user-cache");
cachedQuery.setParameter("sort", "name");
System.out.println("分页查询: " + pagedQuery);
System.out.println("缓存查询: " + cachedQuery);
System.out.println("基础查询原型: " + baseQuery);
}
}
优缺点分析 (Pros and Cons Analysis)
优点 (Advantages)
- 性能提升:避免重复创建相似对象的开销
- 简化对象创建:隐藏对象创建的细节
- 运行时灵活性:可以在运行时动态创建对象
- 减少子类数量:避免创建大量相似的子类
- 动态配置:可以动态地添加或删除原型
缺点 (Disadvantages)
- 深克隆复杂性:实现深克隆可能很复杂
- 循环引用问题:需要处理循环引用的情况
- 初始化复杂性:每个原型都需要适当的初始化
- 内存开销:需要维护原型注册表
- 克隆限制:某些对象可能无法克隆
使用场景 (Use Cases)
适用场景
- 系统需要独立于产品的创建、构成和表示时
- 要实例化的类在运行时刻指定时
- 避免创建与产品类层次平行的工厂类层次时
- 类的实例只能有几个不同状态组合中的一种时
- 对象创建成本高,需要重复使用相似对象时
不适用场景
- 对象的创建成本很低
- 对象的状态变化频繁
- 对象包含循环引用且无法处理
- 系统不需要运行时动态创建对象
最佳实践 (Best Practices)
- 使用Cloneable接口:确保对象正确实现Cloneable接口
- 处理深克隆:正确实现深克隆以避免共享引用
- 考虑序列化:对于复杂的深克隆,考虑使用序列化
- 原型注册表:使用注册表管理原型对象
- 初始化状态:确保原型对象有合适的初始状态
- 性能考虑:在性能敏感的场景下评估克隆成本
与其他模式的关系 (Relationship with Other Patterns)
与工厂模式的关系
- 工厂模式:基于继承,通过子类创建对象
- 原型模式:基于克隆,通过复制现有对象创建新对象
与建造者模式的关系
- 建造者模式可以用来创建复杂的原型对象
与单例模式的关系
- 原型注册表通常使用单例模式实现
总结 (Summary)
原型模式是一种强大的创建型设计模式,它通过复制现有对象来创建新对象,而不是通过实例化类。这种模式特别适合以下场景:创建对象成本高、需要动态指定对象类型、避免创建大量相似子类、以及对象状态组合有限的情况。
在Spring、Netty、MyBatis等知名框架中,原型模式被广泛应用于管理对象生命周期、配置复制、缓存键创建等场景。理解原型模式的实现原理和适用场景,对于编写高效、灵活的Java应用程序至关重要。正确使用原型模式可以显著提高系统性能和可维护性。
更多推荐


所有评论(0)