大话设计模式(3)

**单一职责原则(SRP):**就一个类而言,应该仅有一个引起它变化的原因。
**开放-封闭原则:**是说软件实体(类、模块、函数等)应该可以扩展,但是不可修改。
对于扩展是开放的(open for extension),对于更改是封闭的(closed for modification)。
**依赖倒转原则:**抽象不应该依赖细节,细节应该依赖于抽象。就是针对接口编程,不要对实现编程。
高层模块不应该依赖底层模块,两个都应该依赖抽象。
**装饰模式(Decorator):**动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

装饰模式

给人搭配衣服的代码(服装搭配)

面向过程
#include <iostream>
using namespace std;

class Person {
public:
	Person(string name) {
		this->m_Name = name;
	}
	void wearTShirts() {
		cout << "大T恤 ";
	}
	void wearBigTrouser() {
		cout << "垮裤 ";
	}
	void wearSneakers() {
		cout << "破球鞋 ";
	}
	void wearSuit() {
		cout << "西装 ";
	}
	void wearTie() {
		cout << "领带 ";
	}
	void wearLeatherShoes() {
		cout << "皮鞋 ";
	}
	void show() {
		cout << "装扮的" << m_Name << endl;
	}
private:
	string m_Name;
};

void test01() {
	Person xc = Person("小菜");
	cout << "第一种装扮:" << endl;
	xc.wearTShirts();
	xc.wearBigTrouser();
	xc.wearSneakers();
	xc.show();

	cout << "第二种装扮:" << endl;
	xc.wearSuit();
	xc.wearTie();
	xc.wearLeatherShoes();
	xc.show();
}

int main() {
	test01();
	
	return 0;
}
面向对象
#include <iostream>
using namespace std;

class Person {
public:
	Person(string name) {
		this->m_Name = name;
	}
	void show() {
		cout << "装扮的" << m_Name << endl;
	}
private:
	string m_Name;
};

class AbstractFinery {
public:
	virtual void show() = 0;
};
class TShirts :public AbstractFinery{
public:
	void show() {
		cout << "大T恤 ";
	}
};
class BigTrouser :public AbstractFinery {
public:
	void show() {
		cout << "垮裤 ";
	}
};
class Sneakers :public AbstractFinery {
public:
	void show() {
		cout << "破球鞋 ";
	}
};
class Suit :public AbstractFinery {
public:
	void show() {
		cout << "西装 ";
	}
};
class Tie :public AbstractFinery {
public:
	void show() {
		cout << "领带 ";
	}
};
class LeatherShoes :public AbstractFinery {
public:
	void show() {
		cout << "皮鞋 ";
	}
};

void test01() {
	Person xc = Person("小菜");
	cout << "第一种装扮:" << endl;
	AbstractFinery* dtx = new TShirts;
	AbstractFinery* kk = new BigTrouser;
	AbstractFinery* pqx = new Sneakers;
	
	dtx->show();
	kk->show();
	pqx->show();
	xc.show();

	cout << "第二种装扮:" << endl;
	AbstractFinery* xz = new Suit;
	AbstractFinery* ld = new Tie;
	AbstractFinery* px = new LeatherShoes;

	xz->show();
	ld->show();
	px->show();
	xc.show();
}

int main() {
	test01();
	
	return 0;
}

仔细看这段代码

	dtx->show();
	kk->show();
	pqx->show();
	xc.show();

大鸟说:“这样写就好比:光着身子,当着大家的面,先穿T恤,再穿裤子,再穿鞋,就像在众目睽睽下穿衣服”
那是不是应该在内部组装完毕,然后再显示出来?用建造者模式?
不是的,建造者模式要求建造过程必须是稳定的,而当前的例子,建造过程是不稳定的,服饰组合可以有无数种方案,并非固定的。而我们需要把所需的功能按照正确的顺序串联起来进行控制

装饰模式(Decorator):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活

在这里插入图片描述

Component 是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent 是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator 装饰抽象类,继承了Component,从外类来扩展Component 类的功能,但对于Component 来说,是无需知道Decorator 的存在的。至于ConcreteDecorator 就是具体的装饰对象,起到给Component 添加职责的功能。

装饰模式是利用SetComponent 来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。

对于服装搭配的例子,“人”类是Component 还是ConcreteComponent呢?
如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。同样的道理,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。
所以,就没有必要有Component类了,直接让服装类Decorator继承人类ConcreteComponent就可
在这里插入图片描述

#include<iostream>
using namespace std;

class Person {
public:
	Person(){}  //注意必须有构造函数
	Person(string name) {
		this->name = name;
	}
	virtual void show() {
		cout << "装扮的" << name << endl;
	}
private:
	string name;
};

class Finery :public Person {
public:
	void Decorate(Person* component) {
		this->component = component;
	}
	void show() {
		if (component != NULL) {
			component->show();
		}
	}
protected:
	Person* component = NULL;
};
class Tshirts :public Finery {
public:
	void show() {
		cout << "大T恤 ";
		Finery::show();
	}
};
class BigTrouser :public Finery {
public:
	void show() {
		cout << "垮裤 ";
		Finery::show();
	}
};

void test01() {
	Person* xc = new Person("小菜");
	cout << "第一种装扮:" << endl;

	Tshirts* dtx = new Tshirts;
	BigTrouser* kk = new BigTrouser;

	dtx->Decorate(xc);
	kk->Decorate(dtx);
	kk->show();
	delete kk;
	delete dtx;
	delete xc;
}

int main() {
	test01();
	
	return 0;
}

另附博文:装饰模式C++实现

实例
给定两种初始的汽车类,例如丰田和沃尔沃,利用装饰模式分别给它们添加新的功能,其中丰田可以导航和自动驾驶,沃尔沃可以导航和语音控制。
UML图
在这里插入图片描述
代码与函数
Component:Car类
ConcreteComponent:TOYOTA、VOLOVO类
Decorator:Function类
ConcreteDecorator:Navigator、SelfDrive、VoiceControl类
代码

#include<iostream>
using namespace std;
 
/*
给定两种初始的汽车类,例如丰田和沃尔沃,
利用装饰模式分别给它们添加新的功能,
其中丰田可以导航和自动驾驶,沃尔沃可以导航和语音控制。
*/
 
class Car{//Component
public:
    virtual void showInfo() = 0;
};
 
class TOYOTA: public Car{
public:
    TOYOTA(){}
    TOYOTA(string name){
        this->name = name;
    }
    void showInfo(){
        cout<<name<<endl;
    }
private:
    string name;
};
 
class  VOLOVO: public Car{
public:
    VOLOVO(){}
    VOLOVO(string name){
        this->name = name;
    }
    void showInfo(){
        cout<<name<<endl;
    }
private:
    string name;
};
 
class Function: public Car{//Decorator
protected:
    Car* car;
public:
    void Decorate(Car* car){
        this->car = car;
    }
    void showInfo(){
        if(car != NULL)car->showInfo();
    }
};
 
//其中丰田可以导航和自动驾驶,沃尔沃可以导航和语音控制。
 
class Navigator: public Function{
public:
    void showInfo(){
        cout<<"导航 ";
        Function::showInfo();
    }
};
 
class SelfDrive: public Function{
public:
    void showInfo(){
        cout<<"自动驾驶 ";
        Function::showInfo();
    }
};
 
class VoiceControl: public Function{
public:
    void showInfo(){
        cout<<"语音控制 ";
        Function::showInfo();
    }
};
 
//其中丰田可以导航和自动驾驶,沃尔沃可以导航和语音控制。
int main(){
    Car* toyota = new TOYOTA("丰田卡罗拉");
    Navigator* na = new Navigator();
    SelfDrive* sd = new SelfDrive();
    na->Decorate(toyota);
    sd->Decorate(na);
    sd->showInfo();
    cout<<endl;
    
    Car* volovo = new VOLOVO("沃尔沃S90");
    Navigator* na2 = new Navigator();
    VoiceControl* vc = new VoiceControl();
    na2->Decorate(volovo);
    vc->Decorate(na2);
    vc->showInfo();
 
    return 0;
}

总结
①本次实验通过Car的实例掌握并编码了装饰模式。
②注意如果只有一个ConcreteComponent类而没有Component类,那么Decorator类可以是ConcreteComponent的一个子类。在本次实验中,有TOYOTA和VOLOVO两个具体的类,因此需要一个Component的Car类来定义接口。
③由②可知,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator合并成一个类。在本次实验中有Navigator、SelfDrive、VoiceControl三个具体的装饰类。
④在客户端中,要最后一个添加的职责,用来是包装好了的车对象,因此需要由最后一个装饰的实例显示结果。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值