【重读设计模式】原型模式

原型模式,设计模式中难懂的模式之一,了解js的人都知道prototype,我猜测js中的对象就是通过原型模式创建的。现实的系统中也很少有使用原型模式的,因为它的使用场景比较特殊。下面就来分析一下原型模式。


定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的实例。换句话说,原型模式就是通过复制现在已经存在的对象来创建一个新的对象。

定义解释:有的时候,在某些特定的系统中,当创建一个实例的过程比较复杂或者说是昂贵时(比如创建实例的构造函数非常的复杂,在执行这个构造函数时会消耗较长的时间),同时这个构造函数中的一些信息又没有什么变化(也就是说创建第一个实例时初始化信息是这样的,创建第二个实例时初始化信息还是还是这样的),这种情况下使用new创建一个实例的成本就很高,在这种情况下使用克隆会更快。克隆的意思就是复制现有的实例来创建新的实例,这样有什么好处呢?第一,客户端根本就不知道具体要实例化的是哪一个类,它只知道是复制了,但具体的实例化情况,它却是一无所知的,这样便对客户端进行了隐藏,第二,复制一个对象一般情况下会比创建一个对象性能更高(当然有时候也不一定,只是一般情况而已)。而这种实现的方式就是原型模式。


使用场景:

(1)创建一个实例的过程比较复杂或者昂贵时,一般指使用较长的时间或空间。

(2)每个对象内容之间变化很小,绝大多数内容都是相同的。


类图:

image




例子:

一般画图的软件使用方法都是,在他提供的toolbar上通过拖拽的方式画出自己需要的图形,比如需要画一个矩形就在toolbar上选择一个矩形然后拖拽到画板上。这样就在画板上生成了一个矩形,同时软件支持对所有的图形有拖大缩小、移动、着色、填充等功能。也就是说,用户需要创建一个矩形,只需要将toolbar上有的矩形克隆到自己的画板上,而不需要构造怎么画出一个矩形,如何设计他的移动、放大缩小、着色等功能。一方面,如果是通过new矩形的化,则构造函数的成本很高(逻辑复杂,时间久),另一方面,用户也无需知道如何构造,只知道需要一个矩形即可。


设计:

我们使用原型模式来设计该toolbar,所有的图形我们都作为一种原型,这样用户就可以拖拽来生成自己的对象。另外一方面,为了使所有的图形都支持放大缩小、移动、着色等相同的功能,我们定义基类chart封装所有的相同操作。

用户需要生成的任何图形,都通过拖拽toolbar上的图形生成,我们设计矩形类Rectangle是原型,提供抽象的clone方法,同时拖拽之后生成的类为DrawRecTangle类,该类是实现类,根据用户的行为生成具体的实例。


实现:

//============================================================================
// Name        : prototype.cpp
// Author      : tester
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================


#include <iostream>
using namespace std;


class Rectangle
{
public:
void show()
{
cout << "I am a rectangle." << endl;
}


virtual Rectangle* clone() = 0;
virtual ~Rectangle(){};
};


class UserRectangle
{
public:
void show()
{
cout << "I am a user rectangle." << endl;
cout << "high:" << m_high << endl;
cout << "width:" << m_width << endl;
}


void set_size(const int high, const int width)
{
m_high = high;
m_width = width;
}


UserRectangle()
{
m_high = 50;
m_width = 60;
}


UserRectangle(const UserRectangle& other)
{
m_high = other.m_high;
m_width = other.m_width;
}


UserRectangle* clone()
{
return new UserRectangle(*this);
}


private:
int m_high;
int m_width;
};


int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!


UserRectangle* prototype = new UserRectangle;
prototype->show();


UserRectangle* prototype2 = prototype->clone();
prototype2->set_size(300,500);
prototype2->show();


return 0;
}


结果:

!!!Hello World!!!
I am a user rectangle.
high:50
width:60
I am a user rectangle.
high:300
width:500


总结:

当一个对象的创建非常复杂或者难度很大,同时该对象的其他相同类的实例没有太大区别时就可以考虑使用原型模式,原型模式使用当前已有对象去实例化新的对象,大多数情况下降低了对象创建的成本,并减少了客户端和实例对象之间的耦合。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值