设计模式示例(C++实现)

软考软件设计师下午真题-面向对象的程序设计与实现-原型设计模式(2013年上半年试题六))Java代码讲解 考试代码讲解 阅读详情

最近参加了软考,在准备考试过程中发现其中给出设计类图让通过指定的设计模式进行设计的题目对于练习C++和软件开发是一种不错的的方式,因为学校中的C++课程只讲C++语言,虽然也讲了封装、继承、多态等特性,但是缺少相应的练习,使得没有深入的认识和理解。同时类似于程序设计、软件工程的课程设计,其中概要设计、详细设计也都是文档写的很好看,最后编码从没按照设计中的内容来写。最终导致了学完C++,用的时候却不知从何下手。所以这里总结了全国计算机技术与软件专业技术资格(水平)考试参考用书系列中的部分题目,希望可以达到以下两个目的:

* 练习C++,掌握理解更多的特性,而不是只停留在掌握语法的阶段

* 提高软件开发方面的能力,主要是熟悉、学习基本的设计模式,学会如何设计并按照设计实现相应的编码

但需要特别指出的是设计模式还是推荐阅读这方面的经典书籍:设计模式 可复用面向对象软件的基础。我只是总结软考中的题目是因为题目可以让我们快速的对问题有所了解,并且我暂时也只是想练习C++,但如果想要对问题有系统、详细的了解还是需要读书。

Command(命令)模式

例:某灯具厂商欲生产一个灯具遥控器,该遥控器具有7个可编程的插槽,每个插槽都有开关按钮,对应着一个不同的灯。利用该遥控器能够统一控制房间内该厂商所有品牌灯具的开关,现采用Command(命令)模式实现该遥控器的软件部分。Command模式的类图如图所示。

commandpattern

/*************************************************
* Command Pattern
* Author : robocoder
* Date : 2016 - 11 - 13
* HomePage : https://robocoderhan.github.io/
* Email : robocoder@foxmail.com
*************************************************/

#include <iostream>
#include <string>

using namespace std;

class Light{
private:
    string name;
public:
    Light(string name){ this->name = name; }
    void on(){ cout << name + " on" << endl; }
    void off(){ cout << name + " off" << endl; }
};

class Command{
public:
    virtual void execute(){}
};

class LightOnCommand :public Command{
private:
    Light* light;
public:
    LightOnCommand(Light* light){ this->light = light; }
    void execute(){ light->on(); }
};

class LightOffCommand :public Command{
private:
    Light* light;
public:
    LightOffCommand(Light* light){ this->light = light; }
    void execute(){ light->off(); }
};

class RemoteControl{
private:
    Command* onCommands[7];
    Command* offCommands[7];
public:
    RemoteControl(){}
    void setCommand(int slot, Command* onCommand, Command* offCommand){
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }
    void onButtonWasPushed(int slot){ onCommands[slot]->execute(); }
    void offButtonWasPushed(int slot){ offCommands[slot]->execute(); }
};

int main() {
    RemoteControl* remoteControl = new RemoteControl();
    Light* livingRoomLight = new Light("Living Room");
    Light* kitchenLight = new Light("Kitchen");
    LightOnCommand* livingRoomLightOn = new LightOnCommand(livingRoomLight);
    LightOffCommand* livingRoomLightOff = new LightOffCommand(livingRoomLight);
    LightOnCommand* kitchenLightOn = new LightOnCommand(kitchenLight);
    LightOffCommand* kitchenLightOff = new LightOffCommand(kitchenLight);
    remoteControl->setCommand(0, livingRoomLightOn, livingRoomLightOff);
    remoteControl->setCommand(1, kitchenLightOn, kitchenLightOff);
    remoteControl->onButtonWasPushed(0);
    remoteControl->offButtonWasPushed(0);
    remoteControl->onButtonWasPushed(1);
    remoteControl->offButtonWasPushed(1);
    return 0;
}

Observer(观察者)模式

例:某实验室欲建立一个实验室环境监测系统,以显示实验室的温度、湿度以及洁净度等环境数据。当获取到最新的环境测量数据时,显示的环境数据能够更新。现在采用观察者(Observer)模式来开发该系统,观察者模式的类图如图所示。

observerpattern

/*************************************************
* Observer Pattern
* Author : robocoder
* Date : 2016 - 11 - 13
* HomePage : https://robocoderhan.github.io/
* Email : robocoder@foxmail.com
*************************************************/

#include <iostream>
#include <vector>

using namespace std;

class Observer{
public:
    virtual void update(float temp, float humidity, float cleanness) = 0;
};

class Subject{
public:
    virtual void registerObserver(Observer* o) = 0;
    virtual void removeObserver(Observer* o) = 0;
    virtual void notifyObserver() = 0;
};

class EnvironmentData : public Subject{
private:
    vector<Observer*> observers;
    float temperature, humidity, cleanness;
public:
    void registerObserver(Observer* o){ observers.push_back(o); }
    void removeObserver(Observer* o){}
    void notifyObserver(){
        for (vector<Observer*>::const_iterator it = observers.begin(); it != observers.end(); it++)
        {
            (*it)->update(temperature, humidity, cleanness);
        }
    }
    void measurementsChanged(){ notifyObserver(); }
    void setMeasurements(float temperature, float humidity, float cleanness){
        this->temperature = temperature;
        this->humidity = humidity;
        this->cleanness = cleanness;
        measurementsChanged();
    }
};

class CurrentConditionsDisplay : public Observer{
private:
    float temperature, humidity, cleanness;
    Subject* envData;
public:
    CurrentConditionsDisplay(Subject* envData){
        this->envData = envData;
        this->envData->registerObserver(this);
    }
    void update(float temperature, float humidity, float cleanness){
        this->temperature = temperature;
        this->humidity = humidity;
        this->cleanness = cleanness;
        display();
    }
    void display(){
        cout << temperature << " " << humidity << " " << cleanness << endl;
    }
};

int main(){
    EnvironmentData* envData = new EnvironmentData();
    CurrentConditionsDisplay* currentDisplay = new CurrentConditionsDisplay(envData);
    envData->setMeasurements(80, 65, 30.4f);
    return 0;
}

Bridge(桥接)模式

例:欲开发一个绘图软件,要求使用不同的绘图程序绘制不同的图形。以绘制直线和圆形为例,对应的绘图程序如表所示。

^-^DP1DP2
绘制直线draw_a_line(x1,y1,x2,y2)drawline(x1,y1,x2,y2)
绘制圆draw_a_circle(x,y,r)drawcircle(x,y,r)

该绘制软件的扩展性要求,将不断扩充新的图形和新的绘图程序。为了避免出现类爆炸的情况,现采用桥接(Bridge)模式来实现上述要求,得到如图所示的类图。

bridgepattern

/*************************************************
* Bridge Pattern
* Author : robocoder
* Date : 2016 - 11 - 15
* HomePage : https://robocoderhan.github.io/
* Email : robocoder@foxmail.com
*************************************************/

#include <iostream>

using namespace std;

class DP1{
public:
    static void draw_a_line(double x1, double y1, double x2, double y2){ cout << "DP1 draw_a_line" << endl; }
    static void draw_a_circle(double x, double y, double r){ cout << "DP1 draw_a_circle" << endl; }
};

class DP2{
public:
    static void drawline(double x1, double y1, double x2, double y2){ cout << "DP2 drawline" << endl; }
    static void drawcircle(double x, double y, double r){ cout << "Dp2 drawcircle" << endl; }
};

class Drawing{
public:
    virtual void drawLine(double x1, double y1, double x2, double y2) = 0;
    virtual void drawCircle(double x, double y, double r) = 0;
};

class V1Drawing : public Drawing{
public:
    void drawLine(double x1, double y1, double x2, double y2){ DP1::draw_a_line(x1, y1, x2, y2); cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl; }
    void drawCircle(double x, double y, double r){ DP1::draw_a_circle(x, y, r); cout << x << " " << y << " " << r << endl; }
};

class V2Drawing : public Drawing{
public:
    void drawLine(double x1, double y1, double x2, double y2){ DP2::drawline(x1, y1, x2, y2); cout << x1 << " " << y1 << " " << x2 << " " << y2 << endl; }
    void drawCircle(double x, double y, double r){ DP2::drawcircle(x, y, r); cout << x << " " << y << " " << r << endl; }
};

class Shape{
public:
    Shape(Drawing* dp){ _dp = dp; }
    void drawLine(double x1, double y1, double x2, double y2){ _dp->drawLine(x1, y1, x2, y2); }
    void drawCircle(double x, double y, double r){ _dp->drawCircle(x, y, r); }
private:
    Drawing* _dp;
};

class Rectangle : public Shape{
private:
    double _x1, _y1, _x2, _y2;
public:
    Rectangle(Drawing* dp, double x1, double y1, double x2, double y2) : Shape(dp){ _x1 = x1; _y1 = y1; _x2 = x2; _y2 = y2; }
    void draw(){ drawLine(_x1, _y1, _x2, _y2); }
};

class Circle : public Shape{
private:
    double _x, _y, _r;
public:
    Circle(Drawing* dp, double x, double y, double r) : Shape(dp){ _x = x; _y = y; _r = r; }
    void draw(){ drawCircle(_x, _y, _r); }
};

int main(){
    V1Drawing* dp1 = new V1Drawing();
    V2Drawing* dp2 = new V2Drawing();
    Rectangle* rectangle1 = new Rectangle(dp1, 0, 1, 1, 1);
    rectangle1->draw();
    Rectangle* rectangle2 = new Rectangle(dp2, 0, 1, 1, 1);
    rectangle2->draw();
    Circle* circle1 = new Circle(dp1, 0, 1, 1);
    circle1->draw();
    Circle* circle2 = new Circle(dp2, 0, 1, 1);
    circle2->draw();
    return 0;
}

Prototype(原型)模式

例:现要求实现一个能够自动生成求职简历的程序,简历的基本内容包括求职者的姓名、性别、年龄及工作经历。希望每份简历中的工作经历有所不同,并尽量减少程序中的重复代码。
现采用原型模式(Prototype)来实现上述要求,得到如图所示的类图。

prototypepattern

/*************************************************
* Prototype Pattern
* Author : robocoder
* Date : 2016 - 11 - 15
* HomePage : https://robocoderhan.github.io/
* Email : robocoder@foxmail.com
*************************************************/
#include <iostream>
#include <string>

using namespace std;

class Cloneable{
public:
    virtual Cloneable* clone() = 0;
};

class WorkExperience : public Cloneable{
private:
    string workDate;
    string company;
public:
    Cloneable* clone(){
        WorkExperience* obj = new WorkExperience();
        obj->workDate = this->workDate;
        obj->company = this->company;
        return obj;
    }
    void setWorkDate(string wd){ 
        workDate = wd; 
    }
    void setCompany(string comp){ 
        company = comp; 
    }
    string toString(){
        return workDate + company;
    }
};

class Resume : public Cloneable{
private:
    string name, sex, age;
    WorkExperience* work;
    Resume(WorkExperience* work){
        this->work = (WorkExperience*)work->clone();
    }
public:
    Resume(string name){ 
        work = new WorkExperience(); 
        this->name = name; 
    }
    void setPersonalInfo(string sex, string age){ 
        this->sex = sex; 
        this->age = age; 
    }
    void setWorkExperience(string workDate, string company){ 
        work->setWorkDate(workDate); 
        work->setCompany(company); 
    }
    Cloneable* clone(){
        Resume* obj = new Resume(this->work);
        obj->name = this->name;
        obj->sex = this->sex;
        obj->age = this->age;
        return obj;
    }
    string toString(){
        return name + sex + age + work->toString();
    }
};

int main(){
    Resume* a = new Resume("张三");
    a->setPersonalInfo("男", "29");
    a->setWorkExperience("1998-2000", "A company");
    cout << a->toString() << endl;
    Resume* b = (Resume*)a->clone();
    b->setWorkExperience("2001-2006", "B company");
    cout << b->toString() << endl;
    cout << a->toString() << endl;
    return 0;
}

Abstract Factory(抽象工厂)模式

例:现欲开发一个软件系统,要求能够同时支持多种不同的数据库,为此采用抽象工厂模式设计该系统。以SQL Server和Access两种数据库以及系统中的数据库表Department为例,其类图如图所示。

abstractfactorypattern

/*************************************************
* Abstract Factory Pattern
* Author : robocoder
* Date : 2016 - 11 - 16
* HomePage : https://robocoderhan.github.io/
* Email : robocoder@foxmail.com
*************************************************/
#include <iostream>

using namespace std;

//数据库表
class Department{};

class IDepartment{
public:
    virtual void insert(Department* department) = 0;
    virtual Department* getDepartment(int id) = 0;
};

class SqlserverDepartment :public IDepartment{
public:
    void insert(Department* department){
        cout << "Insert a record into Department in SQL Server!\n";
    }
    Department* getDepartment(int id){ return new Department(); }
};

class AccessDepartment :public IDepartment{
public:
    void insert(Department* department){
        cout << "Insert a record into Department in ACCESS!\n";
    }
    Department* getDepartment(int id){ return new Department(); }
};

class IFactory{
public:
    virtual IDepartment* creatDepartment() = 0;
};

class SqlserverFactory :public IFactory{
public:
    IDepartment* creatDepartment(){
        return new SqlserverDepartment();
    }
};

class AccessFactory :public IFactory{
public:
    IDepartment* creatDepartment(){
        return new AccessDepartment();
    }
};

int main(){
    SqlserverFactory* sqlFactory = new SqlserverFactory();
    SqlserverDepartment* sqlDepartment = (SqlserverDepartment*)sqlFactory->creatDepartment();
    Department* a = new Department();
    sqlDepartment->insert(a);

    AccessFactory* accessFactory = new AccessFactory();
    AccessDepartment* accessDepartment = (AccessDepartment*)accessFactory->creatDepartment();
    accessDepartment->insert(a);
    return 0;
}

Decorator(装饰)模式

例:某咖啡店在卖咖啡时,可以根据顾客的要求在其中加入各种配料,咖啡店会根据所加入的配料来计算费用。咖啡店所供应的咖啡及配料的种类和价格如表所示。

咖啡价格/杯(¥)配料价格/杯(¥)
蒸馏咖啡(Espresso)25摩卡(Mocha)10
深度烘焙咖啡(DarkRoast)20奶泡(Whip)8

现采用装饰器(Decorator)模式来实现计算费用的功能,得到如图所示的类图。

decoratorpattern

/*************************************************
* Decorator Pattern
* Author : robocoder
* Date : 2016 - 11 - 16
* HomePage : https://robocoderhan.github.io/
* Email : robocoder@foxmail.com
*************************************************/
#include <iostream>
#include <string>

using namespace std;

const int ESPRESSO_PRICE = 25;
const int DARKROAST_PRICE = 20;
const int MOCHA_PRICE = 10;
const int WHIP_PRICE = 8;

//饮料
class Beverage{
protected:
    string description;
public:
    virtual string getDescription(){
        return description;
    }
    virtual int cost() = 0;
};

//配料
class CondimentDecorator :public Beverage{
protected:
    Beverage* beverage;
};

//蒸馏咖啡
class Espresso :public Beverage{
public:
    Espresso()
    {
        description = "Espresso";
    }
    int cost(){
        return ESPRESSO_PRICE;
    }
};

//深度烘焙咖啡
class DarkRoast :public Beverage{
public:
    DarkRoast()
    {
        description = "DarkRoast";
    }
    int cost(){
        return DARKROAST_PRICE;
    }
};

//摩卡
class Mocha :public CondimentDecorator{
public:
    Mocha(Beverage* beverage){
        this->beverage = beverage;
    }
    string getDescription(){
        return beverage->getDescription() + ",Mocha";
    }
    int cost(){
        return MOCHA_PRICE + beverage->cost();
    }
};

//奶泡
class Whip :public CondimentDecorator{
public:
    Whip(Beverage* beverage){
        this->beverage = beverage;
    }
    string getDescription(){
        return beverage->getDescription() + ",Whip";
    }
    int cost(){
        return WHIP_PRICE + beverage->cost();
    }
};

int main(){
    Beverage* beverage = new DarkRoast();
    beverage = new Mocha(beverage);
    beverage = new Whip(beverage);
    cout << beverage->getDescription() << "¥" << beverage->cost() << endl;
    return 0;
}

Composition(组合)模式

例:某饭店在不同的时段提供多种不同的餐饮,其菜单的结构图如图所示。

composition

现在采用组合(Composition)模式来构造该饭店的菜单,使得饭店可以方便地在其中增加新的餐饮形式,得到如图所示的类图。其中MenuComposition为抽象类,定义了添加(add)新菜单和打印饭店所有菜单信息(print)的方法接口。类Menu表示饭店提供的每种餐饮形式的菜单,如煎饼屋菜单、咖啡屋菜单。每种菜单中都可以添加子菜单,例如图中的甜点菜单。类MenuItem表示菜单中的菜式。

compositionpattern

/*************************************************
* Composition Pattern
* Author : robocoder
* Date : 2016 - 11 - 16
* HomePage : https://robocoderhan.github.io/
* Email : robocoder@foxmail.com
*************************************************/
#include <iostream>
#include <list>
#include <string>

using namespace std;

class MenuComponent{
protected:
    string name;
public:
    MenuComponent(string name){
        this->name = name;
    }
    string getName(){
        return name;
    }
    virtual void add(MenuComponent* menuComponent) = 0; //添加新菜单
    virtual void print() = 0; //打印菜单信息
};

class MenuItem :public MenuComponent{
private:
    double price;
public:
    MenuItem(string name, double price) :MenuComponent(name){ this->price = price; }
    double getPrice(){ return price; }
    void add(MenuComponent* menuComponent){ return ; }
    void print(){
        cout << " " << getName() << "," << getPrice() << endl;
    }
};

class Menu :public MenuComponent{
private:
    list<MenuComponent*> menuComponents;
public:
    Menu(string name) :MenuComponent(name){}
    void add(MenuComponent* menuComponent){
        menuComponents.push_back(menuComponent); 
    }
    void print(){
        cout << "\n" << getName() << "\n-----------------------------" << endl;
        std::list<MenuComponent*>::iterator iter;
        for (iter = menuComponents.begin(); iter != menuComponents.end();iter++)
        {
            (*iter)->print();
        }
    }
};

int main(){
    MenuComponent* allMenus = new Menu("ALL MENUS");
    MenuComponent* dinerMenu = new Menu("DINER MENU");
    MenuComponent* coffee = new MenuItem("Espresso", 20);
    allMenus->add(coffee);
    MenuComponent* dumpling = new MenuItem("Dumpling", 30);
    dinerMenu->add(dumpling);
    allMenus->add(dinerMenu);
    allMenus->print();
    return 0;
}

State(状态)模式

例:某大型商场内安装了多个简易的纸巾售卖机,自动出售2元钱一包的纸巾,且每次仅售出一包纸巾。纸巾售卖机的状态图如图所示。

state

采用状态(State)模式来实现该纸巾售卖机,得到如图所示的类图。其中类State为抽象类,定义了投币、退币、出纸巾等方法接口。类SoldState、SoldOutState、NoQuarterState和HasQuarterState分别对应图中纸巾售卖机的4种状态:售出纸巾、纸巾售完、没有投币、有2元钱。

statepattern

/*************************************************
* State Pattern
* Author : robocoder
* Date : 2016 - 11 - 17
* HomePage : https://robocoderhan.github.io/
* Email : robocoder@foxmail.com
*************************************************/
#include <iostream>

using namespace std;

class TissueMachine;

class State{
public:
    virtual void insertQuarter() = 0;//投币
    virtual void ejectQuarter() = 0;//退币
    virtual void turnCrank() = 0;//按下“出纸巾”按钮
    virtual void dispense() = 0;//出纸巾
};

//没有投币
class NoQuarterState :public State{
private:
    TissueMachine* tissueMachine;
public:
    NoQuarterState(TissueMachine* tissueMachine){ this->tissueMachine = tissueMachine; }
    void insertQuarter();
    void ejectQuarter();
    void turnCrank();
    void dispense();
};

//有2元钱(已投币)
class HasQuarterState :public State{
private:
    TissueMachine* tissueMachine;
public:
    HasQuarterState(TissueMachine* tissueMachine){ this->tissueMachine = tissueMachine; }
    void insertQuarter();
    void ejectQuarter();
    void turnCrank();
    void dispense();
};

//售出纸巾
class SoldState :public State{
private:
    TissueMachine* tissueMachine;
public:
    SoldState(TissueMachine* tissueMachine){ this->tissueMachine = tissueMachine; }
    void insertQuarter();
    void ejectQuarter();
    void turnCrank();
    void dispense();
};

//纸巾售完
class SoldOutState :public State{
private:
    TissueMachine* tissueMachine;
public:
    SoldOutState(TissueMachine* tissueMachine){ this->tissueMachine = tissueMachine; }
    void insertQuarter();
    void ejectQuarter();
    void turnCrank();
    void dispense();
};

class TissueMachine{
private:
    State *soldOutState, *noQuarterState, *hasQuarterState, *soldState, *state;
    int count;
public:
    TissueMachine(int numbers){
        soldOutState = new SoldOutState(this);
        noQuarterState = new NoQuarterState(this);
        hasQuarterState = new HasQuarterState(this);
        soldState = new SoldState(this);
        this->count = numbers;
        if (count > 0)
        {
            this->state = noQuarterState;
        }
    }

    void insertQuarter(){ state->insertQuarter(); }
    void ejectQuarter(){ state->ejectQuarter(); }
    void turnCrank(){
        state->turnCrank();
        state->dispense();
    }
    void setState(State* state){ this->state = state; }
    State* getHasQuarterState(){ return hasQuarterState; }
    State* getNoQuarterState(){ return noQuarterState; }
    State* getSoldState(){ return soldState; }
    State* getSoldOutState(){ return soldOutState; }
    void setCount(int numbers){ this->count = numbers; }
    int getCount(){ return count; }
};

void SoldOutState::insertQuarter(){ cout << "机器无纸巾,已退回硬币!" << endl; }
void SoldOutState::ejectQuarter(){ cout << "自动售货机根本没有硬币!" << endl; }
void SoldOutState::turnCrank(){ cout << "机器无纸巾,请不要操作机器" << endl; }
void SoldOutState::dispense(){}

void NoQuarterState::insertQuarter(){
    tissueMachine->setState(tissueMachine->getHasQuarterState());
    cout << "已投币!" << endl;
}
void NoQuarterState::ejectQuarter(){ cout << "自动售货机根本没有硬币!" << endl; }
void NoQuarterState::turnCrank(){ cout << "请投币" << endl; }
void NoQuarterState::dispense(){}

void HasQuarterState::insertQuarter(){ cout << "已投币!请不要重复投币!已退回重复投币!" << endl; }
void HasQuarterState::ejectQuarter(){
    tissueMachine->setState(tissueMachine->getNoQuarterState());
    cout << "已取币!" << endl;
}
void HasQuarterState::turnCrank(){
    tissueMachine->setState(tissueMachine->getSoldState());
    cout << "请等待自动售货机出纸巾!" << endl;
}
void HasQuarterState::dispense(){}

void SoldState::insertQuarter(){ cout << "请等待自动售货机出纸巾!请不要投币!已退回投币!" << endl; }
void SoldState::ejectQuarter(){
    tissueMachine->setState(tissueMachine->getNoQuarterState());
    cout << "请等待自动售货机出纸巾!无法取回已消费的硬币!" << endl;
}
void SoldState::turnCrank(){ cout << "请等待自动售货机出纸巾!已响应你的操作!" << endl; }
void SoldState::dispense(){
    if (tissueMachine->getCount() > 0){
        tissueMachine->setState(tissueMachine->getNoQuarterState());
        tissueMachine->setCount(tissueMachine->getCount() - 1);
        cout << "你的纸巾,请拿好!" << endl;
    }
    else{
        tissueMachine->setState(tissueMachine->getSoldOutState());
        cout << "已退回你的硬币!纸巾已卖光,等待进货!" << endl;
    }
}

int main(){
    TissueMachine *tissueMachine = new TissueMachine(1);
    cout << "纸巾数:" << tissueMachine->getCount() << endl;
    tissueMachine->insertQuarter();
    tissueMachine->turnCrank();
    cout << "纸巾数:" << tissueMachine->getCount() << endl;
    tissueMachine->turnCrank();
    cout << "纸巾数:" << tissueMachine->getCount() << endl;
    tissueMachine->insertQuarter();
    tissueMachine->turnCrank();
    return 0;
}

Chain of Responsibility(责任链)模式

例:已知某企业的采购审批是分级进行的,即根据采购金额的不同由不同层次的主管人员来审批,主任可以审批5万元以下(不包括5万元)的采购单,副董事长可以审批5万元至10万元(不包括10万元)的采购单,董事长可以审批10万元至50万元(不包括50万元)的采购单,50万元及以上的采购单就需要开会讨论决定。

采用责任链设计模式(Chain of Responsibility)对上述过程进行设计后得到的类图如图所示。

chainofresponsibilitypattern

/*************************************************
* Chain of Responsibility Pattern
* Author : robocoder
* Date : 2016 - 11 - 17
* HomePage : https://robocoderhan.github.io/
* Email : robocoder@foxmail.com
*************************************************/
#include <iostream>
#include <string>

using namespace std;

//采购单
class PurchaseRequest{
public:
    double amount;//采购金额
    int number;//采购单编号
    string purpose;//采购目的
};

//审批者
class Approver{
private:
    Approver* successor;
public:
    Approver(){
        successor = NULL;
    }
    virtual void processRequest(PurchaseRequest aRequest){
        if (successor != NULL)
        {
            successor->processRequest(aRequest);
        }
    }
    void setSuccessor(Approver* aSuccessor){
        successor = aSuccessor;
    }
};

//例会
class Congress :public Approver{
public:
    void processRequest(PurchaseRequest aRequest){
        if (aRequest.amount >= 500000){
            cout << "例会正在审批" << endl;
        }
        else
        {
            Approver::processRequest(aRequest);
        }
    }
};

//董事长
class President :public Approver{
public:
    void processRequest(PurchaseRequest aRequest){
        if (aRequest.amount >= 100000 && aRequest.amount < 500000)
        {
            cout << "董事长正在审批" << endl;
        }
        else
        {
            Approver::processRequest(aRequest);
        }
    }
};

//副董事长
class VicePresident :public Approver{
public:
    void processRequest(PurchaseRequest aRequest){
        if (aRequest.amount >= 50000 && aRequest.amount < 100000)
        {
            cout << "副董事长正在审批" << endl;
        }
        else
        {
            Approver::processRequest(aRequest);
        }
    }
};

//主任
class Director :public Approver{
public:
    void processRequest(PurchaseRequest aRequest){
        if (aRequest.amount < 50000)
        {
            cout << "主任正在审批" << endl;
        } 
        else
        {
            Approver::processRequest(aRequest);
        }
    }
};

int main(){
    Congress meeting;
    President Tammy;
    VicePresident Sam;
    Director Larry;
    meeting.setSuccessor(NULL);
    Tammy.setSuccessor(&meeting);
    Sam.setSuccessor(&Tammy);
    Larry.setSuccessor(&Sam);

    PurchaseRequest aRequest;
    cin >> aRequest.amount;
    Larry.processRequest(aRequest);
    return 0;
}

Strategy(策略)模式

例:某游戏公司现欲开发一款面向儿童的模拟游戏,该游戏主要模拟现实世界中各种鸭子的发声特征、飞行特征和外观特征。游戏需要模拟的鸭子种类及其特征如表所示。

鸭子种类发声特征飞行特征外观特征
灰鸭(MallardDuck)发出“嘎嘎”声(Quack)用翅膀飞行(FlyWithWings)灰色羽毛
红头鸭(RedHeadDuck)发出“嘎嘎”声(Quack)用翅膀飞行(FlyWithWings)灰色羽毛、头部红色
棉花鸭(CottonDuck)不发声(QuackNoWay)不能飞行(FlyNoWay)白色
橡皮鸭(RubberDuck)发出橡皮与空气摩擦的声音(Squeak)不能飞行(FlyNoWay)黑白橡皮色

为支持将来能够模拟更多种类鸭子的特性,采用策略(Strategy)模式设计的类图如图所示。

strategy

其中,Duck为抽象类,描述了抽象的鸭子,而类RubberDuck、MallardDuck、CottonDuck和RedHeadDuck分别描述具体的鸭子种类,方法fly()、quack()和display()分别表示不同种类的鸭子都具有飞行特征、发声特征和外观特征;类FlyBehavior与QuackBehavior为抽象类,分别用于表示抽象的飞行行为与发声行为;类FlyNoWay与FlyWithWings分别描述不能飞行的行为和用翅膀飞行的行为;类Quack、Squeak与QuackNoWay分别描述发出“嘎嘎”声的行为、发出橡皮与空气摩擦声的行为与不发声的行为。

/*************************************************
* Strategy Pattern
* Author : robocoder
* Date : 2016 - 11 - 17
* HomePage : https://robocoderhan.github.io/
* Email : robocoder@foxmail.com
*************************************************/
#include <iostream>

using namespace std;

class FlyBehavior{
public:
    virtual void fly() = 0;
};

class QuackBehavior{
public:
    virtual void quack() = 0;
};

class FlyWithWings :public FlyBehavior{
public:
    void fly(){ cout << "使用翅膀飞行" << endl; }
};

class FlyNoWay :public FlyBehavior{
public:
    void fly(){ cout << "不能飞行" << endl; }
};

class Quack :public QuackBehavior{
public:
    void quack(){ cout << "发出\'嘎嘎\'声!" << endl; }
};

class Squeak :public QuackBehavior{
public:
    void quack(){ cout << "发出空气与橡皮摩擦声!" << endl; }
};

class QuackNoWay :public QuackBehavior{
public:
    void quack(){ cout << "不能发声!" << endl; }
};

class Duck{
protected:
    FlyBehavior* flyBehavior;
    QuackBehavior* quackBehavior;
public:
    void fly(){ flyBehavior->fly(); }
    void quack(){ quackBehavior->quack(); }
    virtual void display() = 0;
};

class RubberDuck :public Duck{
public:
    RubberDuck(){
        flyBehavior = new FlyNoWay();
        quackBehavior = new Squeak();
    }
    ~RubberDuck(){
        if (!flyBehavior) delete flyBehavior;
        if (!quackBehavior) delete quackBehavior;
    }
    void display(){}
};

int main(){
    RubberDuck rubberDuck;
    rubberDuck.fly();
    rubberDuck.quack();
    return 0;
}
c++实现工厂方法完整源代码 c++实现工厂方法完整源代码FactoryMethod.hppmain.cpp FactoryMethod.hpp #ifndef __FACTORY_METHOD__ #define __FACTORY_METHOD__ #include <iostream> #include <string.h> using namespace std; // 抽象产品类AbstractProduct class AbstractSportProduct { public: Abstrac 阅读详情

相关推荐

C++笔记之接口`Interface`

Interface。

小勇博客 417

设计模式之原型模式

在做软设真题的时候,2013年上半年也考了原型(Prototype)模式,但是跟答案相差甚远,没想到还有那种强制类型转换的,太操蛋了。如果标准答案,我能得到7分,丢了8分那就太不应该了,今天特意学习记下Prototype模型,虽然是为了应付软考,但其实更加是为了能灵活使用设计模式的应用。

weixin_47954860的博客 622

C++设计模式教程_2024-07-14_07-43-04.Tex

设计模式是软件工程中的一种通用解决方案,用于解决在特定情况下经常出现的设计问题。它们提供了一种在代码中重用设计和架构的方法,而无需重复相同的编码。设计模式可以分为三大类:创建型、结构型和行为型。在C++中,设计模式的实现依赖于语言的特性,如类、模板、继承和多态。

1049

【Java】原型模式

对于设计模式,网上大部分资料都直接抛出一大堆理论,让人难以看明白。其实所谓的“设计模式”,只是怎么把代码写得更好而已,避免大量的代码出现重复而已,如果你不介意,完全可以把某一段代码拷贝粘贴多次,来实现功能,然而,许多地方,甚至软考的软件设计师,都对设计模式进行考察。 下面说说原型模式,其实设计模式,任何语言都能实现,是一种编程思想。 原型模式是:通过复制一个已经存在的实例来创建一个新的实例。被

编程记录,亲测有效 1604

【开源教程25】疯壳·开源编队无人机-定高、定点、悬停

【开源教程25】疯壳·开源编队无人机-定高、定点、悬停

efans_Mike的博客 1650

llama.cpp部署大模型

llama.cpp如何部署大模型

Eddy的博客 974

软考 | 2013年上半年 软件设计师 下午试卷

试题一 某慈善机构欲开发一个募捐系统,以跟踪记录为事业或项目向目标群体进行募捐而组织的集体性活动,该系统的主要功能如下所述。 (1)管理志愿者。根据募捐任务给志愿者发送加入邀请、邀请跟进、工作任务;管理志愿者提供的邀请响应、支援站信息、工作时长、工作结果等。 (2)确定募捐需求和收集所募捐赠(资金及物品)。根据需求提出的募捐任务、活动请求和募捐请求,获取所募集的资金和物品。 (3)组织募捐活动。根据活动请求,确定活动时间范围。根据活动时间,搜索场馆,即向场馆发送场馆可用性请求,获得场馆可用性。然后根据活动时

Albirostris 2399

实用工具抓取youtube热门数据

YouTube作为全球第二大搜索引擎,2024年日均视频播放量突破50亿次,头部创作者单月广告分成可达百万美元量级。但对数据分析者而言,其反爬机制堪称业界最严: ‌反爬技术升级‌:Google部署的Botguard系统可检测异常流量,触发机制包括: 单IP每小时请求超过50次即封禁 检测Headless浏览器指纹(如Chrome的navigator.webdriver属性) 动态加载内容(如评论数据需滚动页面3次后加载) ‌数据价值维度‌:某MCN机构研究显示,前100热门视频的标题关键词复用率高达67%

26万+

软件设计师-案例分析题

由类图可知,类TissueMachine依赖于类State,且类State是接口,接口中定义了投币、退币、按下“出纸巾”按钮、出纸巾等方法。类SoldState、SoldOutState、NoQuarterState和HasQuarterState分别实现了接口State中的方法。纸巾售卖机有4个状态,类TissueMachine中的成员变量state可以表示售卖机的当前状态。空(1)处应填入state.空(2)处和空(3)处考查类NoQuarterState和HasQuarterState中方法的实现。在

r56ffv8的博客 1461

Blender----利用DEM(tif)生成三维模型

利用DEM(tif)生成三维模型

LongJ_Sir的博客 5420

K-L展开 (Karhunen-Loeve expansion)

K-L变换

susan_wang1的博客 2万+

23 种设计模式的通俗解释与简单示例(C++不同版本实现)

设计模式是前辈们总结的代码设计经验,目的是让代码更灵活、可复用、易维护。对于新手来说,可以先理解“什么时候用”,再掌握“怎么实现”。下面用通俗易懂的方式讲解23种设计模式,每种都附C++示例(兼顾C++11及以后的现代写法)。通俗解释:一个类只能创建一个对象(比如全局配置、日志器),像国家只有一个总统。 核心:私有化构造函数,通过静态方法返回唯一实例。实现1:饿汉式(C++98) (程序启动就创建实例,线程安全,但可能浪费内存) 实现2:懒汉式(C++11,线程安全) (用到时才创建,节省内存,C++11静

不经一番寒彻骨,怎得梅花扑鼻香。 1241

基于STM32的可穿戴式多生理参数实时监测与预警系统

针对传统可穿戴健康设备存在的生理参数监测种类单一、数据处理依赖云端导致响应滞后、续航能力弱等问题,设计一种基于STM32的可穿戴式多生理参数实时监测与预警系统。系统以STM32L476RG低功耗微控制器为核心,集成心率血氧传感器、体温传感器、血压传感器,实现人体心率、血氧饱和度、体温、收缩压/舒张压的同步采集;通过边缘端轻量化数据处理算法完成参数异常判定,结合低功耗硬件设计与软件休眠策略,在保证监测精度的同时延长续航。测试结果表明,系统心率监测误差≤2次/分钟,血氧饱和度误差≤2%,体温误差≤±0.2℃,血

m0_74026776的博客 2039

26种设计模式讲解 干货总结,非常干!(每一个都附C++完整代码示例实现)

26种设计模式讲解 干货总结,非常干!(每一个都附C++完整代码示例实现)

Warren++的博客 4474

​​​​手把手教你玩转RT-Thread操作系统专栏--​​​​第5章 设备驱动开发:RT-Thread的设备框架​​​​5.4 I2C/SPI驱动:如何驱动外部传感器(以MPU6050为例)​

通过本节学习,掌握了基于RT-Thread设备模型的I2C/SPI驱动开发流程,包括硬件初始化、寄存器读写、设备注册及应用程序调用。I2C(Inter-Integrated Circuit)和SPI(Serial Peripheral Interface)是嵌入式系统中最常用的两种串行总线协议,广泛用于连接传感器、存储器等外设。函数通过I2C协议读取外设寄存器的数据(如MPU6050的加速度寄存器)。SPI读取需先拉低片选(CS),发送寄存器地址,再读取数据,最后拉高CS。查找I2C设备,并调用。

xiaoheshang_123的博客 122

具身智能:原理、算法与系统 第3章 具身智能的感知-认知-行为框架

具身智能的PCB框架源于对生物智能系统的观察:动物通过感官接收环境信息(感知),基于内部模型进行预测和决策(认知),并通过身体执行动作改变环境(行为),而这一改变又通过感知反馈形成闭环。这一框架在两篇核心文献中得到了深入阐述:提出了系统的数学形式化和工程实现,则从认知科学角度强调了归纳偏置和双过程理论的重要性。

VectorShift的博客 154

【设计模式详解】探秘解释器模式,掌握解释器模式的艺术及其神奇力量【C++代码实现示例】

解释器模式是一种行为型设计模式,它用于定义语言的文法,并且在运行时解释和执行语言中的表达式。该模式通常包含以下几个角色: 抽象表达式(Abstract Expression):定义了一个抽象的接口,用于解释和执行特定的语法规则。 终结符表达式(Terminal Expression):实现了抽象表达式接口,用于表示语言中的终结符(如变量、常量等)。 非终结符表达式(Non-terminal Expression):实现了抽象表达式接口,用于表示语言中的非终结符,通常由多个终结符或非终结符组成。 上下文(C

十年以上编程经验的干货分享 1497

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

C++学习笔记(十一)——PIMPL设计模式

C++学习笔记(十一)——PIMPL设计模式

weixin_39828926的博客 501

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

桥接和享元模式(结构型设计模式)的 C++ 代码示例模板

桥接和享元模式(结构型设计模式)的 C++ 代码示例模板。

夜悊的博客 968

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

设计模式C++实现详解

《设计模式C++实现》是一个GitHub上的开源项目,由Jakub Vojvoda维护,它提供了C++中23种经典设计模式的实现和示例。这个项目的目标是帮助开发者更好地理解和运用这些设计模式,以便在软件开发中提高代码质量、可维护性和可扩展性。这些设计模式源自“Gang of Four”的著作《设计模式:可复用面向对象软件的基础》。 ## 2. 项目快速启动 ### 安装依赖 确保你的系统安装...

gitblog_00338的博客 539

[设计模式] Builder 建造者模式

本文介绍了Builder设计模式,从意图、问题到解决方案,详细讲解其应用场景与实现方法,并分析了优缺点及与其他设计模式的关系。文中通过C++代码示例(main.cc)和执行结果(Output.txt),清晰展示了如何使用Builder模式构建复杂对象

No Game No Life 1868

【免费下载】 探索设计模式的奥秘:23种设计模式 C++ PDF 下载

探索设计模式的奥秘:23种设计模式 C++ PDF 下载 【下载地址】23种设计模式CPDF下载 23种设计模式 C++ PDF 下载 项目地址: https://gitcode.com/Open-source-documenta...

gitblog_06622的博客 1393

【亲测免费】 设计模式C++示例项目介绍

设计模式C++示例项目介绍 基础介绍与编程语言 本项目是《设计模式:可复用面向对象软件的基础》一书的C++实现版本,旨在为C++开发者提供一个清晰、易懂的设计模式实践案例集。该项目主要使用C++语言开发,同时辅助以CMake构建系统,确保代码的可编译性和跨平台性。 核心功能 项目包含了一系列设计模式的基本实现,这些模式是软件工程中的经典解决方案,用于解决在软件开发中重复出现的问题。具体包括但不限于...

gitblog_00078的博客 328

深度解析C++与C语言中的设计模式实现

C++和C语言在设计模式的实现上各有千秋。C++得益于其面向对象的特性,在实现设计模式时更加自然和简洁;而C语言则由于缺乏类和继承等特性,在实现设计模式时往往需要更多的手动管理和复杂的代码逻辑。C++:更适合实现复杂的设计模式,代码更具可读性和可扩展性,尤其在需要多态、继承的场景下表现出色。C:虽然实现设计模式更加繁琐,但在需要极高性能和精细控制的场景下,C语言的优势也不容忽视。在实际开发中,选择哪种语言和设计模式实现方式取决于项目的需求、性能要求以及团队的技术栈。

weixin_52734695的博客 1434

设计模式 (c++实现)

设计模式(c++实现)总述分类创建型模式结构型模式行为型模式六大原则总原则:开闭原则单一职责原则里氏替换原则依赖倒转原则接口隔离原则迪米特法则合成复用原则创建型模式工厂方法模式抽象工厂模式单例模式建造者模式原型模式结构型模式适配器模式装饰器模式代理模式外观模式桥接模式组合模式享元模式行为型模式模板方法模式策略模式观察者模式迭代器模式责任链模式命令模式备忘录模式状态模式访问者模式中介者模式解释器模式 总述 总体来说设计模式分为三大类: 分类 创建型模式 共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式

weixin_45767368的博客 2997

设计模式实现CPP——单例模式

单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。常用于共享资源(如配置信息、线程池、数据库连接等),保证全局一致性。

qq_45835091的博客 485
上一篇: 基础机器学习算法Python实现
robocoder
博客等级 码龄10年 1粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值