第一章

1.1什么是设计模式

每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动。

一个模式有四个基本要素:

  1. 模式名称(pattern name) 一个助记名,它用一两个词来描述模式的问题、解决方案和效果。
  2. 问题(problem) 描述了应该在何时使用模式。
  3. 解决方案(solution) 描述了设计的组成成分,它们之间的相互关系及各自的职责和协作方式。
  4. 效果(consequences) 描述了模式应用的效果及使用模式应权衡的问题。

1.6 设计模式怎样解决设计问题

1.6.1 寻找合适的对象

面向对象程序由对象组成, 对象 包括数据和对数据进行操作的过程,过程通常称为方法或操作。对象在收到客户的请求(或消息)后,执行相应的操作。

面向对象设计方法学的设计方法:

  • 挑出名词和动词,进而创建响应的类和操作
  • 关注于系统的协作和职责模式
  • 对现实世界建模,再将分析时发现的对象转换至设计中。

例题1

一头母牛从出生后,每两年可以生下一头母牛,即在第二年和第四年分别可产下一头母牛,出生后第五年将会死去。假设农场现有一头母牛,N年后农场的母牛数目是多少,编写程序实现

分析:选择牛为对象,年龄是属性,过一年是方法,该方法确定今年牛应该生牛还是死亡。

class CCow
{
public:
    CCow()
    {
        m_iAge = 0;
    }

    CCow* PassYear()
    {
        m_iAge++;
        if (m_iAge == 2 || m_iAge == 4)
        {
            return new CCow;
        }

        if (m_iAge == 5)
        {
            return NULL;
        }

        return this;
    }

private:
    int m_iAge;
};

int Call(int iYear)
{
    CPtrList list;
    list.AddTail(new CCow);

    for (int i = 1; i <= iYear; i++)
    {
        int iCount = list.GetCount();
        POSITION pos = list.GetHeadPosition();
        for (int i = 0; i < iCount; i++)
        {
            CCow* pCur = (CCow*)list.GetNext(pos);
            CCow* pRet = pCur->PassYear();
            if (pRet == NULL)
            {
                delete list.RemoveHead();
            }
            else if (pCur != pRet)
            {
                list.AddTail(pRet);
            }
        }

    }

    int iCount = list.GetCount();
    while (!list.IsEmpty())
    {
        delete list.RemoveHead();
    }
    return iCount;
}

其它实现方法:

size_t func(int years)
{
    size_t tab[5] = {1};
    size_t i, total = 1;
    for (i = 1; i <= years; ++i)
    {
        total += (tab[1] + tab[3] - tab[4]);
        //printf("%d years later total = %I64dn", i, total);
        memmove(tab + 1, tab, (sizeof(tab) / sizeof(tab[0]) - 1) * sizeof(tab[0]));
        tab[0] = tab[2] + tab[4];
    }
    return total;
}

size_t func1(int years)
{
    size_t i, tab[5] = {1};
    for (i = 1; i <= years; ++i)
    {
        memmove(tab + 1, tab, (sizeof(tab) / sizeof(tab[0]) - 1) * sizeof(tab[0]));
        tab[0] = tab[2] + tab[4];
    }
    return tab[0] + tab[1] + tab[2] + tab[3] + tab[4];
}

double GetCowCnt(int n)
{
    if (n%2 == 1)
    {
        return (pow((1+sqrt(5.0)) / 2, (n+1)/2+1) - pow((1-sqrt(5.0)) / 2, (n+1)/2+1)) / sqrt(5.0);
    }
    else
    {
        return 2*((pow((1+sqrt(5.0)) / 2, (n)/2+1) - pow((1-sqrt(5.0)) / 2, (n)/2+1)) / sqrt(5.0));
    }
}

例题2

大数学家高斯有个好习惯:无论如何都要记日记。
他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210
后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?
高斯出生于:1777年4月30日。
高斯获得博士学位的那天日记上标着:8113
请你算出高斯获得博士学位的年月日。

分析 :日记做为对象,日期是属性,翻页作为方法。

class CDiary
{
public:

    int iYear;
    int iMonth;
    int iDay;

    CDiary()
    {
        iYear = 1777;
        iMonth = 4;
        iDay = 30;
    }

    void PassDay()
    {
        iDay++;
        int iMonthDay = 31;
        if (iMonth == 4 || iMonth == 6 || iMonth == 9 || iMonth == 11)
        {
            iMonthDay = 30; 
        }
        if (iMonth == 2)
        {
            int bLeapYear = iYear % 100 == 0 ? iYear % 400 == 0 : iYear % 4 == 0;
            iMonthDay = bLeapYear + 28;
        }

        if (iDay > iMonthDay)
        {
            iDay = 1;
            iMonth++;
            if (iMonth > 12)
            {
                iMonth = 1;
                iYear++;
            }                
        }
    }
};

void main()
{
    CDiary di;
    for (int i = 1; i < 8113; i++)
    {
        di.PassDay();
    }

    int j = 0;
}

1.6.2 决定对象的粒度

1.6.3 指定对象接口

对象声明的每一个操作指定操作名、作为参数的对象和返回值,这就是所谓的操作的型构( s i g n a t u r e )。对象操作所定义的所有操作型构的集合被称为该对象的接口( i n t e r f a c e )。对象接口描述了该对象所能接受的全部请求的集合,任何匹配对象接口中型构的请求都可以发送给该对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值