工厂模式介绍
通过一个加工厂,在这个工厂中添加对应材料,我们就可以得到想要的东西,在程序设计中,这种模式就叫做工厂模式,工厂生成出的产品就是某个类的实例,也就是对象。
关于工厂模式一共有三种,分别是:简单工厂模式、工厂模式、抽象工厂模式。
简单工厂模式
比如说你要生产一些物品,生产的方法都是一样的只是原材料不同。你可以设计一个基类,提供生产方法。然后将要生产的对象材料加入到生产类中即可。后面可以再定义一个对象工厂类,用来创建对应材料。
创建一个新的类, 可以将这个类称之为工厂类。对于简单工厂模式来说,需要的工厂类只有一个。工厂类中添加一个公共的成员函数,通过这个函数来创建我们需要的对象,通过这个对象调用工厂函数,这样就可以生产出一个指定类型的实例对象了。这里可以使用c++中的多态来完成。
例如:先定义一个基类,将其方法定义为虚函数。
class Product
{
public:Product(){;}virtual void produce(){cout << "进行生产" << endl;}virtual ~Product(){cout << "资源释放" << endl;}
};
定义要实例化的对象
class Milk :public Product
{
public:void produce(){cout << "生产了牛奶" << endl;}~Milk(){cout << "delete Milk" << endl;}
};class Apple :public Product
{
public:void product(){cout << "生产了apple" << endl;}~Apple(){cout << "delete apple" << endl;}
};
定义物品工厂类,用来生产对应材料
enum class Type :char { milk,apple };
class Factory
{
public:Product* p = nullptr;Product* create(Type T){switch (T){case Type::milk:p = new Milk;break;case Type::apple:p = new Apple;break;default:break;}return p;}
};
int main()
{Factory* f = new Factory;Product* p = f->create(Type::milk);//需要生产材料,就对其参数进行修改p->produce();delete p;return 0;
}
工厂类模式
如果要可以生成更多种类的物品,需要添加更多的物品对象,同时还要在工厂函数的switch语句中添加更多的case,很明显这违背了封闭原则。
简单工厂模式是只有一个工厂类,而工厂模式是有很多的工厂类。
- 一个基类,包含一个虚工厂函数,用于实现多态。
- 多个子类,重写父类的工厂函数。每个子工厂类负责生产某种物品,这相当于再次解耦,如果要生产新物品,那么只需要添加对应的工厂类,无需修改原有的代码。
代码:
class Product
{
public:virtual void produce(){cout << "进行生产" << endl;}virtual ~Product(){cout << "资源释放" << endl;}
};class Milkpro :public Product
{
public:void produce(){cout << "生产了牛奶" << endl;}~Milkpro(){cout << "delete Milk" << endl;}
};class Applepro :public Product
{
public:void product(){cout << "生产了apple" << endl;}~Applepro(){cout << "delete apple" << endl;}
};class Factory//并没有在这个类中直接生产材料,而是定义为抽象类
{
public:virtual Product* creat() = 0;virtual ~Factory(){;}
};class Milk :public Factory
{
public:Product* creat(){return new Milkpro;}~Milk(){cout << "delete Milk" << endl;}
};
class Apple :public Factory
{
public:Product* creat(){return new Applepro;}~Apple(){cout << "delete Apple" << endl;}
};
int main()
{Factory* f = new Milk;Product* p= f->creat();p->produce();delete p;return 0;
}
抽象工厂类
假如要生产一艘船,该船的组成为:
船体,船的动力系统,船中配备的武器。
船体的选择:木材 合金
动力系统的选择:人力驱动,核反应驱动
武器的选择:枪,自动机关炮
这样一共就有8种选则。
船体,因为船体材料的这个属性是可变的,所以还需要给它提供一个抽象类,在这个抽象类的子类中就可以去更换不同的船体材料。
class ShipBody
{
public:virtual string getShipBody() = 0;virtual ~ShipBody() {}
};class WoodBody : public ShipBody
{
public:string getShipBody() override{return string("用<木材>制作轮船船体...");}
};class MetalBody : public ShipBody
{
public:string getShipBody() override{return string("用<合金>制作轮船船体...");}
};
动力系统与武器也是一样:
// 动力
class Engine
{
public:virtual string getEngine() = 0;virtual ~Engine() {}
};class Human : public Engine
{
public:string getEngine() override{return string("使用<人力驱动>...");}
};
class Nuclear : public Engine
{
public:string getEngine() override{return string("使用<核能驱动>...");}
};// 武器
class Weapon
{
public:virtual string getWeapon() = 0;virtual ~Weapon() {}
};class Gun : public Weapon
{
public:string getWeapon() override{return string("配备的武器是<枪>");}
};class Cannon : public Weapon
{
public:string getWeapon() override{return string("配备的武器是<自动机关炮>");}
};
一首船需要3个组成部分,这里用3个变量来表示:
class Ship
{
public:Ship(ShipBody* body, Weapon* weapon, Engine* engine) :m_body(body), m_weapon(weapon), m_engine(engine){}string getProperty(){
// 这也是多态实现,获取对应船组成部分的材料string info = m_body->getShipBody() + m_weapon->getWeapon() + m_engine->getEngine();return info;}~Ship(){delete m_body;delete m_engine;delete m_weapon;}
private:ShipBody* m_body = nullptr;Weapon* m_weapon = nullptr;Engine* m_engine = nullptr;
};
工厂类与上面一样,不直接进行提供船部件,而是定义为抽象类,让子类去提供船的部件。
/ 工厂类
class AbstractFactory
{
public:virtual Ship* createShip() = 0;virtual ~AbstractFactory() {}
};class BasicFactory : public AbstractFactory//定义木头,枪,人力的船
{
public:Ship* createShip() override{Ship* ship = new Ship(new WoodBody, new Gun, new Human);cout << "<基础型>战船生产完毕, 可以下水啦..." << endl;return ship;}
};
结果:
int main()
{AbstractFactory* factroy = new BasicFactory;Ship* ship = factroy->createShip();cout << ship->getProperty();delete ship;delete factroy;return 0;
}
对比:
- 简单工厂模式不能遵守开放-封闭原则,该工厂类没有设置为抽象类,要在该类中直接添加生产对象。
- 工厂模式创建的对象 对应的类不需要提供抽象类,需要创建什么对象,直接提供对应的子类
- 抽象工厂模式创建的对象 对应的类有抽象的基类,创建的对象有多种不同的组合方法。
观察者模式
一个简单的例子:交叉路口的红绿灯。过往的车辆就是观察者或则是订阅者,信号灯就是消息的发布者。当车辆到了该路口,车辆就会观测路灯,当路灯为红灯时,车辆即可通行。当车辆远离该路口时,车辆就不需要观察路灯的信号了。
其他例子:购买的商品被送到菜鸟驿站,会收到驿站发送的提示信息。
这里以报刊为例,报刊可以发布多种类型的消息给不同的人。
发布者,需要满足以下的需求:
- 添加订阅者,将所有的订阅者存储起来
- 删除订阅者,将其从订阅者列表中删除
- 将消息发送给订阅者(发通知)
发布者
发布者未必是一种类型的,不同的发布者可以发布不同种类的消息。先创建出一个发布者的抽象类。
class Observer;//订阅者抽象类
class NewsAgency//发布者抽象类
{
public:
void attach(Observer* ob)
{
m_list.push_back(ob);//增加订阅者
}
void deatch(Observer* ob)
{
m_list.remove(ob);//删除订阅者
}
virtual void notify(string msg) = 0;//通知
virtual ~NewsAgency() {};
protected:
list<Observer*> m_list; // 订阅者列表
};class News_A :public NewsAgency
{
public:
void notify(string msg) override
{
cout << "这是NewA新闻报刊" << endl;
for (auto ch : m_list)
{
ch->update(msg);
}
}
};
class News_B :public NewsAgency
{
public:
void notify(string msg) override
{
cout << "这是NewB新闻报刊" << endl;
for (auto ch : m_list)
{
ch->update(msg);
}
}
};
订阅者
观察者也未必只是一种对象,给所有的观察者定义一个抽象的基类。
// 抽象的订阅者类
class Observer
{
public://通过构造函数给观察者类提供一个信息的发布者
Observer(string name, NewsAgency* news) :m_name(name), m_news(news)
{
m_news->attach(this);//发布者对象将观察者对象存储了起来,可以收到发布的消息
}
void unsubscribe()
{
m_news->deatch(this);//订阅者取消订阅
}
virtual void update(string msg) = 0;
virtual ~Observer() {}
protected:
string m_name;
NewsAgency* m_news;
};class Observer_A : public Observer//订阅者A
{
public:
using Observer::Observer;
void update(string msg) override
{
cout << "订阅者A收到新消息: " << msg << endl;
}
};class Observer_B : public Observer//订阅者B
{
public:
using Observer::Observer;
void update(string msg) override
{
cout << "订阅者B收到新消息: " << msg << endl;
}
};
过程
int main()
{News_A* New_a = new News_A;News_B* New_b = new News_B;Observer_A* obser_a = new Observer_A("observer_A",New_a);Observer_B* obser_b = new Observer_B("observer_B",New_b);New_a->notify("明天会下雨哦*************");New_b->notify("明天广场会进行发布会活动,请大家参加");return 0;
}