原型模式
程序员文章站
2022-06-12 21:47:24
...
定义:通过克隆对象减少创建对象的成本。
优点及使用:
[list]
[*]当很多子类仅仅是类型不同的时候使用
[*]当一个系统需要独立于创建,整合和显示的时候
[*]动态绑定或者动态加载方法
[*]只是通过改变实力的状态或者参数就可以完成任务
[*]运行时添加或者删除对象
[*]通过改变结构指定新对象
[*]用类动态配置应用程序
[*]相关模式包括:
抽象工厂:与原型模式一起使用,抽象工厂存储多种原型
混合模式:与原型模式一起使用完成整体部分关系
挂件模式:给原型添加另外的一些功能
[/list]
例子:
动态加载是典型的面向对象特点和原型模式的例子,例如,重载方法就是一种原型模式。
如果想让代码更有可读性或者做更多的事情,我们可以像下边这样编码
paint方法在运行时可以有各种形状的参数,draw方法根据运行时类型被调用。
重载方法也是一种原型。
draw方法根据参数被调用画出对应的形状。
原型主要用来克隆一个对象,也就是说做一个对象的拷贝。当创建对象时很复杂或者很费时间,这时候我们就可以选择原型模式来克隆这些对象。假设复杂类创建时候比较复杂,你需要实现Cloneable接口并且覆盖clone方法(protected clone())。
克隆是原对象的影子拷贝,如果被克隆的对象变了,原来的对象也会跟着做同样的改变。
为了避免这种负面影响,你需要深度拷贝来替代影子拷贝,下边是对上边修改的例子,注意Complex没有实现Cloneable接口。
优点及使用:
[list]
[*]当很多子类仅仅是类型不同的时候使用
[*]当一个系统需要独立于创建,整合和显示的时候
[*]动态绑定或者动态加载方法
[*]只是通过改变实力的状态或者参数就可以完成任务
[*]运行时添加或者删除对象
[*]通过改变结构指定新对象
[*]用类动态配置应用程序
[*]相关模式包括:
抽象工厂:与原型模式一起使用,抽象工厂存储多种原型
混合模式:与原型模式一起使用完成整体部分关系
挂件模式:给原型添加另外的一些功能
[/list]
例子:
动态加载是典型的面向对象特点和原型模式的例子,例如,重载方法就是一种原型模式。
interface Shape {
public void draw();
}
class Line implements Shape {
public void draw() {
System.out.println("line");
}
}
class Square implements Shape {
public void draw() {
System.out.println("square");
}
}
class Circle implements Shape {
public void draw() {
System.out.println("circle");
}
}
class Painting {
public static void main(String[] args) {
Shape s1 = new Line();
Shape s2 = new Square();
Shape s3 = new Circle();
paint(s1);
paint(s2);
paint(s3);
}
static void paint(Shape s) {
s.draw();
}
}
如果想让代码更有可读性或者做更多的事情,我们可以像下边这样编码
static void paint(Shape s){
if ( s instanceof Line)
s.draw();
//more job here
if (s instanceof Square)
s.draw();
//more job here
if (s instanceof Circle)
s.draw();
//more job here
}
paint方法在运行时可以有各种形状的参数,draw方法根据运行时类型被调用。
重载方法也是一种原型。
class Painting {
public void draw(Point p, Point p2) {
//draw a line
}
public void draw(Point p, int x, int y) {
//draw a square
}
public void draw(Point p, int x) {
//draw a circle
}
}
draw方法根据参数被调用画出对应的形状。
原型主要用来克隆一个对象,也就是说做一个对象的拷贝。当创建对象时很复杂或者很费时间,这时候我们就可以选择原型模式来克隆这些对象。假设复杂类创建时候比较复杂,你需要实现Cloneable接口并且覆盖clone方法(protected clone())。
class Complex implements Cloneable {
int[] nums = {1,2,3,4,5};
public Object clone() {
try {
return super.clone();
}catch(CloneNotSupportedException cnse) {
System.out.println(cnse.getMessage());
return null;
}
}
int[] getNums() {
return nums;
}
}
class Test {
static Complex c1 = new Complex();
static Complex makeCopy() {
return (Complex)c1.clone();
}
public static void main(String[] args) {
Complex c1 = makeCopy();
int[] mycopy = c1.getNums();
for(int i = 0; i < mycopy.length; i++)
System.out.print(mycopy[i]);
}
}
克隆是原对象的影子拷贝,如果被克隆的对象变了,原来的对象也会跟着做同样的改变。
class Complex implements Cloneable {
int[] nums = {1,2,3,4,5};
public Object clone() {
try {
return super.clone();
}catch(CloneNotSupportedException cnse) {
System.out.println(cnse.getMessage());
return null;
}
}
int[] getNums() {
return nums;
}
}
class Test {
Complex c1 = new Complex();
Complex makeCopy() {
return (Complex)c1.clone();
}
public static void main(String[] args) {
Test tp = new Test();
Complex c2 = tp.makeCopy();
int[] mycopy = c2.getNums();
mycopy[0] = 5;
System.out.println();
System.out.print("local array: ");
for(int i = 0; i < mycopy.length; i++)
System.out.print(mycopy[i]);
System.out.println();
System.out.print("cloned object: ");
for(int ii = 0; ii < c2.nums.length; ii++)
System.out.print(c2.nums[ii]);
System.out.println();
System.out.print("original object: ");
for(int iii = 0; iii < tp.c1.nums.length; iii++)
System.out.print(tp.c1.nums[iii]);
}
为了避免这种负面影响,你需要深度拷贝来替代影子拷贝,下边是对上边修改的例子,注意Complex没有实现Cloneable接口。
class Complex {
int[] nums = {1,2,3,4,5};
public Complex clone() {
return new Complex();
}
int[] getNums() {
return nums;
}
}
class Test2 {
Complex c1 = new Complex();
Complex makeCopy() {
return (Complex)c1.clone();
}
public static void main(String[] args) {
Test2 tp = new Test2();
Complex c2 = tp.makeCopy();
int[] mycopy = c2.getNums();
mycopy[0] = 5;
System.out.println();
System.out.print("local array: ");
for(int i = 0; i < mycopy.length; i++)
System.out.print(mycopy[i]);
System.out.println();
System.out.print("cloned object: ");
for(int ii = 0; ii < c2.nums.length; ii++)
System.out.print(c2.nums[ii]);
System.out.println();
System.out.print("original object: ");
for(int iii = 0; iii < tp.c1.nums.length; iii++)
System.out.print(tp.c1.nums[iii]);
}
}
上一篇: 原型模式(Prototype):