刷题 | 设计模式

本文详细介绍了设计模式的三大类别:创建型模式包括单例、原型、工厂方法等;结构型模式涉及代理、适配器、装饰者等;行为型模式如策略、观察者模式等。通过实例解析了工厂模式、单例模式、装饰者模式和策略模式等,强调了模式在多线程安全、对象扩展和类间协作中的应用。

分类

 1、创建型模式:作用于对象的创建,将对象的创建与使用分离。其中囊括了单例、原型、工厂方法、抽象工厂、建造者5 种创建型模式。

 2、结构型模式:将类或对象按某种布局组成更大的结构,其中以代理、适配器、桥接、装饰、外观、享元、组合 7 种结构型模式为主。

 3、行为型模式:作用于类或对象之间相互协作共同完成单个对象无法单独完成的任务,以及怎样分配职责。主要包含了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。


工厂模式:一个抽象类+多个具体的实现类+一个工厂类

也可以说是在多态上增加了一个工厂,工厂的作用是根据需求创建不同的对象

// 抽象类 说明包含的方法
class Shape {
public:
    virtual void sayself() = 0;
};

// 具体实现类 说明方法各自的实现方式
class Circle :public Shape {    
public:    
    void sayself() {cout << "A circle" << endl;}    
};
class Square :public Shape {    
public:    
    void sayself() {cout << "A Square" << endl;}    
};

// 工厂类 负责new
class Factory {
public:
    Shape *GetShape(string shape) {
        Shape *someshape = NULL;
        if (shape == "circle") {
            someshape = new Circle();
        }
        if (shape == "square") {
            someshape = new Square();
        }
        return someshape;
    }
};

// 客户端 main函数
Factory *fac = new Factory();        // 创建一个工厂
Shape *shape = NULL;                 // 创建一个抽象的shape
shape = fac->GetShape("circle");     // 通过工厂,获得具体shape对象
shape = fac->GetShape("square");
 


工厂方法模式:一个抽象类+多个具体的实现类+一个抽象工厂类+多个具体工厂类


// 抽象工厂类 
class Factory {
public:
    virtual Shape *GetShape() = 0;
};

// 具体工厂类
class CircleFactory :class Factory{
public:
    Shape *GetShape() {
        Shape *someshape = NULL;
        someshape = new Circle();
        return someshape;
    }
};

// 客户端 main函数
Factory *fac = NULL;         // 创建一个抽象工厂
Shape *shape = NULL;         // 创建一个抽象的shape

fac = new CircleFactory();   // 创建具体的工厂
shape = fac->GetShape();     // 通过工厂,获得具体shape对象

fac = new SquareFactory();
shape = fac->GetShape("square");
 


抽象工厂模式:(一个抽象类+多个具体的实现类)*n + 一个抽象工厂类+多个具体工厂类

在工厂方法模式的基础上add(1+n)*n


单例模式:只能有一个实例、只能由自己创建这个实例,因此客户端只会对唯一的实例进行修改


class Singleton {
public:
	static Singleton* getInstance() {   // 用于将实例释放给客户端
		if (instance == NULL){
			instance = new Singleton(); // 调用构造函数
		}
		return instance;
	}
private:
	Singleton(){}                // 一个私有的构造函数
 
	static Singleton* instance;  // 一个静态的(全局的)私有实例
};
 
Singleton* Singleton::instance = NULL;
 
// 客户端main
Singleton *s1 = Singleton::getInstance();
Singleton *s2 = Singleton::getInstance(); // 只会创建一个实例

补充:多线程如何保证安全地使用实例?

在get instance() 里面加lock。


装饰者模式:一个抽象主构件+多个具体主构件+一个抽象装饰类+多个具体装饰类

每个构件都能配上不同的装饰,即,将某个对象不断扩大扩展

代码待续


策略模式:一个抽象策略类+多个具体策略实现类+一个上下文类

上下文类用于根据不同的需求使用不同的策略,关键:
1. 私有变量是抽象类的指针
2. 通过setxxx( )函数,根据输入的不同对象,来使抽象类指针指向具体子类的对象
3. 然后调用虚函数方法即可获得子类不同方法的实现

// 抽象策略类
class Strategy {
public:
	Strategy(){}
	virtual void sort(int arr[], int N) = 0;
};

// 具体策略:选择排序的实现
class SelectionSort :public Strategy {
public:
	void sort(int arr[], int N){ ..... }
};

// 上下文类
class Context {
public:
    // 2个构造函数
	/*Context(){
		arr = NULL;
		N = 0;
	}
	Context(int iArr[], int iN){
		this->arr = iArr;
		this->N = iN;
	}*/

    // 初始化 确定该对象
    void setSortStrategy(Strategy* iSortStrategy){
		this->sortStrategy = iSortStrategy;
	}
    void setInput(int iArr[], int iN){
		this->arr = iArr;
		this->N = iN;
	}

    // 实现sort
	void sort(){
		this->sortStrategy->sort(arr, N);
	}
	
private:
	Strategy* sortStrategy;
	int* arr;
	int N;
};
 
int main() {
	Context* ctx = new Context();
	int arr[] = { 10, 23, -1, 0, 300, 87, 28, 77, -32, 2 };
	ctx->setInput(arr, sizeof(arr)/sizeof(int));

	// 选择排序
	ctx->setSortStrategy(new SelectionSort());
	ctx->sort();
 
	// 插入排序
	ctx->setSortStrategy(new InsertSort());
	ctx->sort();
}

适配器模式:一个抽象的目标类 + 一个适配器类 + n个和目标没关系的单独类

目的是为了能让目标类和一堆毫无关系的类连接起来,无需改变这些类里面的代码,只需增加一个适配器的类用来适配源和目标,关键:
1. 在适配器的私有成员中,存放各个源类指针
2. 并在构造函数中创建对象(几个源类就创几个)
3. 然后重写目标类的方法,在方法中调用源类对象自己的方法

// 目标抽象类
class Controller {
public:
	Controller(){}
	virtual ~Controller(){}
	virtual void func() = 0;
};

// 多个需要被适配的源
class file1 {
public:
	file1(){}
	void f1(){ cout << "read file1" << endl; }
};
 
class file2 {
public:
	file2(){}
	void f2(){ cout << "write file2" << endl; }
};

// 适配器
class Adapter:public Controller {
public:
	Adapter(){
        // 将两个源类对象变成私有的,并在构造函数中new这两个对象
		the_file1 = new file1();
		the_file2 = new file2();
	}
	~Adapter(){
		delete file1;
		delete file2;
	}
	Adapter(const Adapter& other) = delete;
	Adapter& operator=(const Adapter& ) = delete;
	void func(){    // 重写base类的func
		file1->f1();
		file2->f2();
	}
private:
	file1 *the_file1;
	file2 *the_file2;
};

 
int main(){
	Controller *controller = new Adapter();
	controller->func();    // 输出read file1 write file2
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值