1. 原型模式(Prototype pattern)的定义
(1)用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
①通过克隆来创建新的对象实例
②新的对象实例复制原型实例属性的值
(2)原型模式的结构和说明
①Prototype:声明一个克隆自身的接口,用来约束想要克隆自己的类,要求他们都要实现这里定义的克隆方法。
②ConcretePrototype:实现Prototype接口的类,这些类真正实现了隆自身的功能。
③Client:使用原型的客户端,首先要获取到原型实例对象,然后通过原型实例的克隆自身来创建新的对象实例。
(3)思考原型模式
①原型模型的本质:克隆生成对象
②原型模式可以用来解决“只知接口而不知实现的问题”,出现一种“接口造接口”的假象。
③原型模式的重心还是在创建新的对象实例。至于创建出来的对象,其属性的值是否一定要和原型对象完全一样,这并没有强制规定,但一般会拷贝成一样的。
④通过克隆出来实例是原型实例是两个完全独立的实例,他们之间没有关联。
【编程实验】订单拆分处理
//创建型模式:原型模式 //订单处理: /* 功能需求:因每个工作小组的处理能力上限是1000,现要求每当订单预定产品数量超过1000时, 把订单拆分为两份来保存,如果还是超过1000,那就继续拆分,直到不超过1000. */ #include <iostream> #include <string> #include <sstream> using namespace std; //*************************辅助类:************************ //定义产品原型的接口,这个产品是为了演示深拷贝 class ProductPrototype { public: virtual ProductPrototype* clone() = 0; }; class Product :public ProductPrototype { private: string productId; //产品编号 string name; //产品名称 public: string& getName(){return name;} void setName(string name){this->name = name;} string& getProductId(){return productId;} void setProductId(string productId){this->productId = productId;} string toString() { return "ProductId="+productId+", productName="+name; } //克隆方法 ProductPrototype* clone() { //创建一个新的订单,然后把本实例的数据复制过去 Product* product = new Product(); product->setProductId(productId); product->setName(name); return product; } }; //*************************订单原型************************** //订单的接口,声明了可以克隆自身的方法 class OrderApi { public: virtual string toString() = 0; virtual int getOrderProductNum()=0; virtual void setOrderProductNum(int num) = 0; virtual OrderApi* clone() = 0; }; //个人订单对象 class PersonalOrder : public OrderApi { private: Product* product; public: PersonalOrder():orderProductNum(0){product = NULL;} string toString() { ostringstream oss; oss << orderProductNum; return ("PersonalOrder's Order="+customerName+" "+ "productName="+product->getName()+" "+ "productId="+product->getProductId()+" "+ "OrderNum="+oss.str()); } OrderApi* clone() { PersonalOrder* order = new PersonalOrder(); order->setName(customerName); order->setProduct((Product*)product->clone());//深度克隆 order->setOrderProductNum(orderProductNum); return order; } int getOrderProductNum() { return orderProductNum; } void setOrderProductNum(int num) { orderProductNum = num; } string& getName() { return customerName; } void setName(string name) { customerName = name; } Product* getProduct(){return product;} void setProduct(Product* product) { this->product = product; } private: string customerName; string productId; int orderProductNum; }; //企业订单对象 class EnterpriseOrder : public OrderApi { private: Product* product; public: EnterpriseOrder():orderProductNum(0){product = NULL;} string toString() { ostringstream oss; oss << orderProductNum; return ("EnterpriseOrder's Order="+enterpriseName+" " "productName="+product->getName()+" "+ "productId="+product->getProductId()+" "+ "OrderNum="+oss.str()); } OrderApi* clone() { EnterpriseOrder* order = new EnterpriseOrder(); order->setName(enterpriseName); order->setProduct((Product*)product->clone()); order->setOrderProductNum(orderProductNum); return order; } int getOrderProductNum() { return orderProductNum; } void setOrderProductNum(int num) { orderProductNum = num; } string& getName() { return enterpriseName; } void setName(string name) { enterpriseName = name; } Product* getProduct(){return product;} void setProduct(Product* product) { this->product = product; } private: string enterpriseName; string productId; int orderProductNum; }; //*********************************订单拆分过程******************** //处理订单 class OrderBusiness { public: //saveOrder传入的是订单接口类型的对象实例,这里只知道 //订单接口的类型,并不知道其具体类型是个人订单还是企业订单 void saveOrder(OrderApi& order) { //1:判断当前的预定产品数量是否大于1000 while(order.getOrderProductNum()> 1000) { //2.如果大于,还需要继续拆分 //2.1 再新建一份订单,跟传入的订单除了数量不一样外, //其他都相同 //如果不采用克隆的方式,下面这行是不知道如何new一个 //对象的,因为order只是个接口,不能直接实例化。而 //Clone的作用在运行时order这个具体的对象是知道自己的类型的 //所以可以通过自身克隆出一个新的对象。 OrderApi* newOrder = order.clone(); //然后进行赋值,产品数量为1000 newOrder->setOrderProductNum(1000); //2.2 原来的订单保留,把数量减少1000 order.setOrderProductNum(order.getOrderProductNum()-1000); //然后是业务处理功能,省略了,打印输出看一下 cout << "split order="+newOrder->toString()<<endl; } //3.不超过,那就直接业务功能处理,省略了,打印输出看一下 cout << "order="+order.toString()<<endl; } }; int main() { //客户端调用例子 //创建订单对象,这里为了演示简单,直接new了 PersonalOrder* op = new PersonalOrder(); //EnterpriseOrder* op = new EnterpriseOrder(); //设置产品 Product* product = new Product(); product->setName("Product1"); product->setProductId("P0001"); //设置订单数据 op->setProduct(product); op->setOrderProductNum(2925); op->setName("SantaClaus"); //这里获取业务处理的类,也直接new了 OrderBusiness* ob = new OrderBusiness(); // //调用业务来保存订单对象 ob->saveOrder(*op); return 0; }