锘??xml version="1.0" encoding="utf-8" standalone="yes"?>
Only some thinking to help to think about the Builder Pattern, but it's not so intuitive.
Suppose that we want to save data to files.
class File { /*abstract file*/ };
class FileBuilder
{
public:
virtual bool buildFileHeader() =0;
virtual bool buildFileBody() =0;
virtual bool buildFileTail() =0;
virtual File* getFile() =0;
};
class BmpFile : public File { .... };
class GifFile : public File { .... };
class JpegFile : public File { .... };
//other kinds of files
class BmpFileBuilder : public FileBuilder
{
};
class GifFileBuilder : public FileBuilder
{
};
class JpegFileBuilder : public FileBuilder
{
};
//builders above implement those interfaces from FileBuilder
//other kinds of file builders
//usage
File* buildFile(FileBuilder* fb)
{
fb.buildFileHeader();
fb.buildFileBody();
fb.buildFileTail();
return fb.GetFile();
}
void func()
{
FileBuilder* fb = new SomeFileBuilder();
File* f = buildFile(fb);
//use f
....
}
Key Points:
1. Each builder is responsible for its buildXXX()
2. Each builder builds one kind of File
3. the File would be created in builder's constructor
]]>
// interface
class People
{
public:
virtual void doWhat() =0;
virtual string type() const =0;
};
class Male : public People
{
public:
virtual void doWhat();
virtual string type() const;
static People* creator();
};
class Female : public People
{
public:
virtual void doWhat();
virtual string type() const;
static People* creator();
};
// interface
typedef People* (*CreateFcn)();
class PeopleFactory
{
public:
static People* producePeople(const string& type);
static addCreateFcn(const string& type, CreateFcn creator);
private:
static map<string, CreateFcn> createFcns;
};
People* PeopleFactory::producePeople(const string& type)
{
//***1
CreateFcn creator= createFcns[type];
return creator();
}
---- test ----
void f()
{
//***2
const string t("Male"); //or "Female"
People* p = PeopleFactory::producePeople(t);
p->doWhat();
delete p;
}
---- extension ----
class Hemophrodite : public People
{
virtual void doWhat();
virtual string type() const;
static People* creator();
};
void g()
{
//***3
const string newType = "Hemophrodite";
PeopleFactory::addCreateFcn(newType, Hemophrodite::creator);
// usage
const string t("Hemophrodite");
People* p = PeopleFactory::producePeople(t);
p->doWhat();
delete p;
}
Cool!! OCP!!
---------
Key point:
1. How does the Factory Method create the instance
of classes through their type names?
How could this method follow the OCP?
2. Where does the type name come from?
-- config file
-- registry
-- other method
3. About extension
----------
Interface classes:
People & PeopleFactory