{
for(int i=0; i
os << GetLineData(i);
os << "\n";
}
}
然后考虑实现CPic_String
class CPic_String: public CPic_Base
{
public:
CPic_String(char* p[], int nCount);
virtual int GetWidth() const;
virtual int GetHeight() const;
virtual std::string GetLineData(int nLineIndex) const;
protected:
std::vector
};
这个类里存储真正的字符串图像数据,里面方法的实现也很简单,和最开始的的第一种实现类似,就不详写了。
再考虑实现CPic_Frame
class CPic_Frame: public CPic_Base
{
public:
CPic_Frame(CRefPtr
virtual int GetWidth() const;
virtual int GetHeight() const;
virtual std::string GetLineData(int nLineIndex) const;
virtual CRefPtr
protected:
CRefPtr
};
可以看到这里我们引用了一个其他的图像数据,而不是真正存储这些数据,方法实现也很简单, 主要依赖于m_pic所指向的图像类,同时m_pic是个基于引用计数的智能指针, 所以赋值时也没有内存拷贝, 注意GetUnFrame这个方法只有这里返回非NULL,表示只有这种对象支持去边框。
CPic_Frame::CPic_Frame(CRefPtr
: m_pic(pic)
{
_ASSERTE(!m_pic.IsNull());
}
int CPic_Frame::GetWidth() const
{
return m_pic->GetWidth() + 2;
}
int CPic_Frame::GetHeight() const
{
return m_pic->GetHeight() + 2;
}
string CPic_Frame::GetLineData(int nLineIndex) const
{
int nWidth = GetWidth();
int nHeight = GetHeight();
_ASSERTE(nLineIndex < nHeight && nLineIndex >= 0);
if(nLineIndex == 0 //first line and last line
|| nLineIndex == nHeight - 1)
{
int nPadding = nWidth - 2;
return string("+") + string(nPadding, '-') + string("+");
}
else
{
return string("|") + m_pic->GetLineData(nLineIndex - 1) + string("|");
}
}
再考虑实现CPic_VCat
class CPic_VCat: public CPic_Base
{
public:
CPic_VCat(CRefPtr
virtual int GetWidth() const;
virtual int GetHeight() const;
virtual std::string GetLineData(int nLineIndex) const;
protected:
CRefPtr
CRefPtr
};
他里面存储了上下2个图像对象,方法实现是也不复杂,就不具体写了。
另外CPic_HCat也是类似:
class CPic_HCat: public CPic_Base
{
public:
CPic_HCat(CRefPtr
virtual int GetWidth() const;
virtual int GetHeight() const;
virtual std::string GetLineData(int nLineIndex) const;
protected:
CRefPtr
CRefPtr
};
有了上面的实现,现在我们可以这么实现我们需要的功能了:
Int main()
{
char* init1[] = {"Paris", "in the", "Spring"};
CRefPtr
CRefPtr
CRefPtr
P3->Print(cout);
CRefPtr
}
这时我们发现这样对于客户调用很不友好,因为我们内部实现的类层次都暴露给客户了,而这些信息对客户来说应该都是透明的,我们应该再封装一个更简单的界面类给客户。
于是有了如下的设计,其实接口类似我们的第一种实现。
class CPicture
{
public:
CPicture(char* p[], int nCount);
CPicture(CPicture& p1, CPicture& p2, bool bVerCat);
void Frame();
bool UnFrame();
friend std::ostream& operator << (std::ostream& os, const CPicture& pic);
protected:
CRefPtr
};
std::ostream& operator << (std::ostream& os, const CPicture& pic);
这样对客户来说他们只需要和CPicture打交道,根本不用关心内部的实现。
这个类的实现也很简单:
CPicture::CPicture(char* p[], int nCount)
{
m_pic = new CPic_String(p, nCount);
}
CPicture::CPicture(CPicture& pic1, CPicture& pic2, bool bVerCat)
{
if(!bVerCat)
{
m_pic = new CPic_HCat(pic1.m_pic, pic2.m_pic);
}
else
{
m_pic = new CPic_VCat(pic1.m_pic, pic2.m_pic);
}
}
void CPicture::Frame()
{
m_pic = new CPic_Frame(m_pic);
}
bool CPicture::UnFrame()
{
CRefPtr
if(!p.IsNull())
{
m_pic = p;
}
return !p.IsNull();
}
std::ostream& operator << (std::ostream& os, const CPicture& pic)
{
pic.m_pic->Print(os);
return os;
}
下面是我们使用这个类的代码:
char* init1[] = {"Paris", "in the", "Spring"};
char* init2[] = {"Hello world", "every", "thing", "is", "OK!"};
int main(int argc, char* argv[])
{
CPicture p1(init1, 3);
CPicture p2(init2, 5);
// // // //
std::cout << p1;
cout <
std::cout << p2;
cout <
p2.Frame();
cout << p2;
cout <
p1.F