创建型设计模式有: 共6种
简单工厂模式
功能:主要用于创建对象。新添加类时,不会影响以前的系统代码。核心思想是用一个工厂来根据输入的条件产生不同的类,然后根据不同类的virtual函数得到不同的结果。
优点: 适用于不同情况创建不同的类时
缺点: 客户端必须要知道基类和工厂类,耦合性差
模式结构:
模式应用:
C++举例:
//基类 class COperation { public: int m_nFirst; int m_nSecond; virtual double GetResult() { double dResult=0; return dResult; } };
//加法 class AddOperation : public COperation { public: virtual double GetResult() { return m_nFirst+m_nSecond; } };
//减法 class SubOperation : public COperation { public: virtual double GetResult() { return m_nFirst-m_nSecond; } }; //工厂类 class CCalculatorFactory { public: static COperation* Create(char cOperator); //基类和工厂类是关联关系 }; COperation* CCalculatorFactory::Create(char cOperator) { COperation *oper; switch (cOperator) { case '+': oper=new AddOperation(); break; case '-': oper=new SubOperation(); break; default: oper=new AddOperation(); break; } return oper; } //客户端 int main() { int a,b; cin>>a>>b; COperation * op=CCalculatorFactory::Create('-'); //静态函数直接调用 op->m_nFirst=a; op->m_nSecond=b; cout<<op->GetResult()<<endl; return 0; }
Java举例:
工厂方法模式(多态工厂模式)
功能:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
优点:
缺点:
模式应用:
JDBC中的工厂方法
举例:
日志记录器:
某系统日志记录器要求支持多种日志记录方式,如文件记录、数据库记录等,且用户可以根据要求动态选择日志记录方式, 现使用工厂方法模式设计该系统。
C++举例:
#include <string> #include <iostream> using namespace std; //实例基类,相当于Product(为了方便,没用抽象) class LeiFeng { public: virtual void Sweep() { cout<<"雷锋扫地"<<endl; } }; //学雷锋的大学生,相当于ConcreteProduct(具体产品1) class Student: public LeiFeng { public: virtual void Sweep() { cout<<"大学生扫地"<<endl; } }; //学雷锋的志愿者,相当于ConcreteProduct(具体产品2) class Volenter: public LeiFeng { public : virtual void Sweep() { cout<<"志愿者"<<endl; } }; ----------------------------- //工场基类Creator class LeiFengFactory { public: virtual LeiFeng* CreateLeiFeng() //返回值体现依赖关系 { return new LeiFeng(); } }; //工场具体类1(创建大学生产品的具体工厂) class StudentFactory : public LeiFengFactory { public : virtual LeiFeng* CreateLeiFeng() //返回值体现依赖关系 { return new Student(); } }; //工场具体类2(创建志愿者产品的具体工厂) class VolenterFactory : public LeiFengFactory { public: virtual LeiFeng* CreateLeiFeng() { return new Volenter(); //返回值体现依赖关系 } }; ----------------------------- //客户端 int main() { LeiFengFactory *sf=new StudentFactory(); //由客户端选创建什么产品 LeiFeng *s=sf->CreateLeiFeng(); s->Sweep(); delete s; delete sf; return 0; }
Java举例:
抽象工厂模式(Kit模式)
功能:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
优点:
缺点:
模式应用:
在很多软件系统中需要更换界面主题,要求界面中的按钮、文本框、背景色等一起发生改变时,可以使用抽象工厂模式进行设计。
C++举例:
#include <string> #include <iostream> #include <vector> using namespace std; //用户抽象接口(抽象产品A) class IUser { public : virtual void GetUser()=0; virtual void InsertUser()=0; }; //部门抽象接口(抽象产品B) class IDepartment { public: virtual void GetDepartment()=0; virtual void InsertDepartment()=0; }; //ACCESS用户(抽象产品A的产品1) class CAccessUser : public IUser { public: virtual void GetUser() { cout<<"Access GetUser"<<endl; } virtual void InsertUser() { cout<<"Access InsertUser"<<endl; } }; //ACCESS部门(抽象产品B的产品1) class CAccessDepartment : public IDepartment { public: virtual void GetDepartment() { cout<<"Access GetDepartment"<<endl; } virtual void InsertDepartment() { cout<<"Access InsertDepartment"<<endl; } }; //SQL用户(抽象产品A的产品2) class CSqlUser : public IUser { public: virtual void GetUser() { cout<<"Sql User"<<endl; } virtual void InsertUser() { cout<<"Sql User"<<endl; } }; //SQL部门类(抽象产品B的产品2) class CSqlDepartment: public IDepartment { public: virtual void GetDepartment() { cout<<"sql getDepartment"<<endl; } virtual void InsertDepartment() { cout<<"sql insertdepartment"<<endl; } }; //抽象工厂 class IFactory { public: virtual IUser* CreateUser()=0; virtual IDepartment* CreateDepartment()=0; }; //ACCESS工厂 class AccessFactory : public IFactory { public: virtual IUser* CreateUser() { return new CAccessUser(); } virtual IDepartment* CreateDepartment() { return new CAccessDepartment(); } }; //SQL工厂 class SqlFactory : public IFactory { public: virtual IUser* CreateUser() { return new CSqlUser(); } virtual IDepartment* CreateDepartment() { return new CSqlDepartment(); } }; //客户端: int main() { IFactory* factory= new SqlFactory(); IUser* user=factory->CreateUser(); IDepartment* depart = factory->CreateDepartment(); user->GetUser(); depart->GetDepartment(); return 0; }
Java举例:
建造者模式(生成器模式)
功能:将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
优点:
缺点:
模式应用:
很多游戏软件中,地图包括天空、地面、背景等组成部分,人物角色包括人体、服装、装备等组成部分,可以使用建造者模式对其进行设计,通过不同的具体建造者创建不同类型的地图或人物。
举例: KFC套餐
套餐是一个复杂对象,一般包含主食(如汉堡、鸡肉卷等)和饮料(如果汁、 可乐等)等部分,不同的套餐有不同的组成部分,而KFC的服务员可以根据顾客的要求,一步一步装配这些组成部分,构造一份完整的套餐,然后返回给顾客。
C++举例:
#include <string> #include <iostream> #include <vector> using namespace std; //最终的产品类 class Product { private: vector<string> m_product; public: void Add(string strtemp) { m_product.push_back(strtemp); } void Show() { vector<string>::iterator p=m_product.begin(); while (p!=m_product.end()) { cout<<*p<<endl; p++; } } }; //建造者基类 class Builder { public: virtual void BuilderA()=0; virtual void BuilderB()=0; virtual Product* GetResult()=0; }; //第一种建造方式 class ConcreteBuilder1 : public Builder { private: Product* m_product; //体现依赖关系 public: ConcreteBuilder1() { m_product=new Product(); } virtual void BuilderA() { m_product->Add("one"); } virtual void BuilderB() { m_product->Add("two"); } virtual Product* GetResult() { return m_product; } }; //第二种建造方式 class ConcreteBuilder2 : public Builder { private: Product * m_product; //体现依赖关系 public: ConcreteBuilder2() { m_product=new Product(); } virtual void BuilderA() { m_product->Add("A"); } virtual void BuilderB() { m_product->Add("B"); } virtual Product* GetResult() { return m_product; } }; //指挥者类 class Direct { public: void Construct(Builder* temp) //构建一个使用Builder接口的对象 { temp->BuilderA(); temp->BuilderB(); } }; //客户端 int main() { Direct *p=new Direct(); Builder* b1=new ConcreteBuilder1(); Builder* b2=new ConcreteBuilder2(); p->Construct(b1); //调用第一种建造方式 Product* pb1 = b1->GetResult(); pb1->Show(); p->Construct(b2); //调用第二种建造方式 Product * pb2 = b2->GetResult(); pb2->Show(); return 0; }
单例模式
功能:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
优点:
缺点:
模式应用:
一个具有自动编号主键的表可以有多个用户同时使用,但数据库中只能有一个地方分配下一个主键编号,否则会出现主键重复,因此该主键编号生成器必须具备唯一性,可以通过单例模式来实现。
举例:
在OS中,打印池(Print Spooler)是一个用于管理打印任务的应用程序,通过打印池用户可以删除、中止或者改变打印任务的优先级,在一个系统中只允许运行一个打印池对象,如果重复创建打印池则抛出异常。现使用单例模式来模拟实现打印池的设计。
C++举例:
懒汉式单例:
#include <iostream> #include <string> #include <vector> using namespace std; class Singelton { private: Singelton(){ } //构造函数私有堵死了外界创建副本的可能!!! static Singelton* singel; //私有的静态全局变量来保存该类的唯一实例 public: static Singelton* GetInstance() //获得本类实例的唯一全局访问点 { if(singel == NULL) { singel = new Singelton(); } return singel; } }; Singelton* Singelton::singel = NULL;//注意静态变量类外初始化 //客户端: int main() { Singelton* s1=Singelton::GetInstance(); Singelton* s2=Singelton::GetInstance(); if(s1 == s2) //比较两次实例化后的结果是实例相同!!! cout<<"ok"<<endl; else cout<<"no"<<endl; return 0; }
Java举例:
原型模式
功能:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。原型模式其实就是从一个对象创建另外一个可定制的对象,而且不需知道任何创建的细节。
优点:
一般在初始化的信息不发生变化的情况下,克隆是最好的办法,既隐藏了对象创建细节,又提高性能。其等于是不用重新初始化对象,而是动态地获得对象运行时的状态。
缺点:
模式应用:
C++举例
#include<iostream> #include <vector> #include <string> using namespace std; //抽象基类 class Prototype { private: string m_strName; public: Prototype(string strName){ m_strName = strName; } Prototype() { m_strName = " "; } void Show() { cout<<m_strName<<endl; } virtual Prototype* Clone() = 0 ; //关键就在于这样一个抽象方法 } ; // class ConcretePrototype1 class ConcretePrototype1 : public Prototype { public: ConcretePrototype1(string strName) : Prototype(strName){} ConcretePrototype1(){} virtual Prototype* Clone() { ConcretePrototype1 *p = new ConcretePrototype1() ; *p = *this ; //复制对象 return p ; } } ; // class ConcretePrototype2 class ConcretePrototype2 : public Prototype { public: ConcretePrototype2(string strName) : Prototype(strName){} ConcretePrototype2(){} virtual Prototype* Clone() { ConcretePrototype2 *p = new ConcretePrototype2() ; *p = *this ; //复制对象 return p ; } } ; //客户端 int main() { ConcretePrototype1* test = new ConcretePrototype1("小王"); ConcretePrototype2* test2 = (ConcretePrototype2*)test->Clone(); test->Show(); test2->Show(); return 0; }