23种设计模式 -----Day01:简单工厂模式

发布于:2023-02-09 ⋅ 阅读:(724) ⋅ 点赞:(0)

目录

前言

        1.设计模式(Design pattern)定义

        2.为什么要使用设计模式(使用设计模式的意义)

        3.设计原则

                a、单一职责原则

                b、开放封闭原则

                c、里氏代换原则

                d、迪米特法则

                e、依赖倒转原则

                f、合成 /聚合复用原则

        4.设计模式的分类

1.简单工厂模式

        基本简介

        实现方式

        角色及其职能

        工厂角色

        抽象产品角色

        具体产品角色

        优点

        缺点

        使用场景  

        实例1

                头文件

                源文件

                主函数

        实例2       

        simpleFactory头文件

        simpleFactory源文件

        客户端代码


前言

        1.设计模式(Design pattern)定义

        一套被反复使用,多数人知晓的,代码设计经验的总结。使用设计模式的目的是为了可重用代码,让代码更容易被他人理解,保证代码的可靠性。

        通俗的说,就是解决问题的方法,是前辈们归纳总结出来的便于人们理解使用,增加代码的可维护性、可复用性、可扩展性。

        2.为什么要使用设计模式(使用设计模式的意义)

        众所周知,一款软件是否优秀在它的设计阶段就已经决定了,软件设计的好坏,关系到最终的结果。所以开发经验是必不可少的,而设计模式恰恰是开发经验的传承于总结。

        3.设计原则

        设计模式的使用根本原因是为了实现代码的复用、增加可维护性。那么怎么才能实现代码复用呢?面向对象有六大原则是必不可少的。

                a、单一职责原则

        不要存在多于一个导致类更变的原因。通俗的说,即一个类只负责一项职责。

                b、开放封闭原则

        一个软件实体、类、模块或者函数就应该对扩展开放,就修改关闭。简单的就是说可以增加供能,而不允许修改功能。

                c、里氏代换原则

        子类型必须能够替换他们的父类型,简单就是说“父债子还”。

                d、迪米特法则

        一个对象应该对其他对象保持最少的了解。简单来说就是对象之间不依赖与关系来保证运行的。

                e、依赖倒转原则

        高层模块不应该依赖低层模块,二者都应该依赖于其抽象;抽象不应该依赖细节,细节依赖抽象。简单的说就是依赖接口编程,不要对实现编程。即只要结果不顾过程。

                f、合成 /聚合复用原则

        合成聚合复用原则,尽量使用合成/聚合,尽量不要使用类继承。

※耦合度:是指一程序中,模块与模块之间信息或参数依赖的程度。 低耦合度:松散耦合

        4.设计模式的分类

总体来说设计模式分为三大类:

        创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

        结构型模式,共七种:适配器模式、装饰模式​​​​​​​、代理模式、外观模式、桥接模式、组合模式、享元模式。

        行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

1.简单工厂模式

        基本简介

        从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

UML图

        实现方式

         简单工厂模式的实质是由一个工厂类根据传入的参数动态决定应该创建哪个产品类的实例(这些产品类继承自一个父类或接口)

        角色及其职能

        包括三种角色:工厂角色、抽象产品角色、具体产品角色

        工厂角色

        简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。

        抽象产品角色

        简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

        具体产品角色

        是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

        优点

        工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。

        缺点

        由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。

        当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;

        使用场景  

        工厂类负责创建的对象比较少;客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。

        实例1

                头文件

#pragma once
#include<iostream>
#include<string>
using namespace std;
/// <summary>
/// 运算类
/// </summary>
class Operation {
public:
	Operation();
	Operation(double numA, double numB);
	double getNumberA() const;
	void setNumberA(double numA);
	double getNumberB() const;
	void setNumberB(double numB);
	/// <summary>
	/// 虚函数、运算函数
	/// </summary>
	/// <returns>运算后的值</returns>
	virtual double GetResult();
protected:
	double _numberA;
	double _numberB;
};

/// <summary>
/// 加
/// </summary>
class OperationAdd:public Operation
{
public:
	OperationAdd();
	OperationAdd(double numA, double numB);
	/// <summary>
	/// 重写父类的虚函数
	/// </summary>
	/// <returns>运算后的值</returns>
	double GetResult();
};

/// <summary>
/// 减
/// </summary>
class OperationSub :public Operation
{
public:
	OperationSub();
	OperationSub(double numA, double numB);
	/// <summary>
	/// 重写父类的虚函数
	/// </summary>
	/// <returns>运算后的值</returns>
	double GetResult();
};

/// <summary>
/// 乘
/// </summary>
class OperationMul :public Operation
{
public:
	OperationMul();
	OperationMul(double numA, double numB);
	/// <summary>
	/// 重写父类的虚函数
	/// </summary>
	/// <returns>运算后的值</returns>
	double GetResult();
};


/// <summary>
/// 除
/// </summary>
class OperationDiv :public Operation
{
public:
	OperationDiv();
	OperationDiv(double numA, double numB);
	/// <summary>
	/// 重写父类的虚函数
	/// </summary>
	/// <returns>运算后的值</returns>
	double GetResult();
};

/// <summary>
/// 乘方
/// </summary>
class OperationM :public Operation
{
public:
	OperationM();
	OperationM(double numA, double numB);
	/// <summary>
	/// 重写父类的虚函数
	/// </summary>
	/// <returns>运算后的值</returns>
	double GetResult();

};

/// <summary>
/// 简单工厂模式:定义一个创建对象的接口、让子类自己决定实例化哪个工厂类
/// 简单运算工厂类
/// </summary>
class OperationFactory
{
public:
	static Operation* createOperate(char operate);
};

                源文件

#include "OperationFactory.h"
Operation::Operation()
{
	this->_numberA = 0;
	this->_numberB = 0;
}

Operation::Operation(double numA, double numB)
{
	this->_numberA = numA;
	this->_numberB = numB;
}

double Operation::getNumberA() const
{
	return this->_numberA;
}

void Operation::setNumberA(double numA)
{
	this->_numberA = numA;
}

double Operation::getNumberB() const
{
	return this->_numberB;
}

void Operation::setNumberB(double numB)
{
	this->_numberB = numB;
}

double Operation::GetResult()
{
	double result = 0;
	return result;
}

OperationAdd::OperationAdd() :Operation()
{
}

OperationAdd::OperationAdd(double numA, double numB):Operation(numA,numB)
{
}

double OperationAdd::GetResult()
{
	double result = 0;
	result = _numberA + _numberB;
	return result;
}

OperationSub::OperationSub():Operation()
{
}

OperationSub::OperationSub(double numA, double numB):Operation(numA,numB)
{
}

double OperationSub::GetResult()
{
	double result=0;
	result = _numberA - _numberB;
	return result;
}

OperationMul::OperationMul():Operation()
{
}

OperationMul::OperationMul(double numA, double numB):Operation(numA,numB)
{
}

double OperationMul::GetResult()
{
	return _numberA*_numberB;
}

OperationDiv::OperationDiv():Operation()
{
}

OperationDiv::OperationDiv(double numA, double numB):Operation(numA,numB)
{
}

double OperationDiv::GetResult()
{
	if (_numberB == 0) {
		throw "被除数不能为0";
	}
	return _numberA/_numberB;
}

Operation* OperationFactory::createOperate(char operate)
{
	Operation* oper = nullptr;
	switch (operate)
	{
	case '+':
		oper = new OperationAdd;
		break;
	case '-':
		oper = new OperationSub;
		break;
	case '*':
		oper = new OperationMul;
		break;
	case '/':
		oper = new OperationDiv;
		break;
	case '^':
		oper = new OperationM;

	default:
		break;
	}
	return oper;
}

OperationM::OperationM():Operation()
{
}

OperationM::OperationM(double numA, double numB):Operation(numA,numB)
{
}

double OperationM::GetResult()
{
	double res = 1;	
	for (int i = 0; i < _numberB; i++) {
		res *= _numberA;
	}
	return res;
}

                主函数

#include<iostream>
using namespace std;
#include"OperationFactory.h"

int main(int argc, char* argv[]) {
	Operation *oper= OperationFactory::createOperate('^');
	oper->setNumberA(2);
	oper->setNumberB(3);
	double res = oper->GetResult();
	cout << res << endl;
	system("pause");
	return 0;
}

        实例2       

        商场促销---商场收银软件 (基于qt实现)

         simpleFactory头文件

/**
  * @brief 简单工厂实现
  * @param
  * @return
*/
#ifndef SIMPLEFACTORY_H
#define SIMPLEFACTORY_H
#include<QString>
/**
  * @brief 现金收费抽象类、抽象基类
  * @param
  * @return
*/
class CashSuper{
public:
    /**
  * @brief 现金收取类的纯虚函数,收取现金
  * @param 原价
  * @return 当前价
*/
    virtual double AcceptCash(double money)=0;
};

/**
  * @brief 正常收费子类
  * @param
  * @return
*/
class CashNormal:public CashSuper{
public:
    //正常收费,原价返回
   double AcceptCash(double money) override;
};

/**
  * @brief 打折收费子类
  * @param
  * @return
*/
class CashRebate:public CashSuper{
public:
    CashRebate(double moneyRebate);//打折收费,初始化时输入折扣率
    double AcceptCash(double money) override;

private:
    double moneyRate=1;
};
/**
  * @brief 返利收费子类,初始化时输入返利条件和返利值
  * @param 返利条件moneyCondition 返利值moneyReturn
  * @return
*/
class CashReturn:public CashSuper{
public:
    CashReturn(double moneyCondition,double moneyReturn);
    double AcceptCash(double money) override;
private:
    double moneyCondition=0.0;
    double moneyReturn=0.0;
};
/**
  * @brief 现金收费工厂类
  * @param
  * @return
*/
class CashFactory{
public:
    static CashSuper* CreateCashAccept(int type);
};

#endif // SIMPLEFACTORY_H

        simpleFactory源文件

#include "simplefactory.h"
double CashNormal::AcceptCash(double money)
{
    return money;
}
CashRebate::CashRebate(double moneyRebate)
{
    if(moneyRebate>1||moneyRebate<0){
        throw "rate error";
    }
    this->moneyRate=moneyRebate;
}
double CashRebate::AcceptCash(double money)
{
    return money*moneyRate;
}
CashReturn::CashReturn(double moneyCondition, double moneyReturn)
{
    this->moneyCondition=moneyCondition;
    this->moneyReturn=moneyReturn;
}
double CashReturn::AcceptCash(double money)
{
    double result=money;
    if(money>=moneyCondition){
        result=money-moneyReturn;
    }
    return result;
}
CashSuper* CashFactory::CreateCashAccept(int type)
{//type  现金收取工厂
    CashSuper *cs=nullptr;
    switch (type) {//根据条件返回相应的对象
    case 0:
        cs=new CashNormal();
        break;
    case 1:
        cs=new CashReturn(300,100);
        break;
    case 2:
        cs=new CashRebate(0.8);
        break;
    case 3:
        cs=new CashRebate(0.5);
        break;
    case 4:
        cs=new CashReturn (500,200);
        break;
    default:
        break;
    }
    return cs;
}

        客户端代码

void Widget::on_btn_ok_clicked()//点击确定槽函数
{
    double total=0.00;//声明一个double变量total来计算总计
    double price=ui->line_Price->text().toDouble();//lineEdit获取price
    double num=ui->line_Num->text().toDouble();//lineEdit获取num
    total=num*price;//获取合计
    CashSuper* csuper=CashFactory::CreateCashAccept(ui->comboBox->currentIndex());
    total=csuper->AcceptCash(total);

    ui->listWidget->addItem("单价:"+ui->line_Price->text()+
                            " 数量:"+ui->line_Num->text()+
                            " "+ui->comboBox->currentText()+
                            " 合计:"+QString::number(total));//添加到啊listWidget中
    ui->labShowPrice->setText(QString::number(total));//显示到lab中。
}


网站公告

今日签到

点亮在社区的每一天
去签到