设计模式可分为三大类:
- 创建型模式 (Creational Patterns)
- 结构性模式 (Structural Patterns)
- 行为型模式 (Behavioral Patterns)
模式描述 | 包括 |
---|---|
创建型模式 | 工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern) |
结构型模式 | 适配器模式(Adapter Pattern) 桥接模式(Bridge Pattern) 过滤器模式(Filter、Criteria Pattern) 组合模式(Composite Pattern) 装饰器模式(Decorator Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) |
行为型模式 | 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 访问者模式(Visitor Pattern) |
我们将详细阐述一下三大类其中比较常用的设计模式,并简要分析一下利弊。
文章目录
- 创建型模式
- 工厂模式
- 简单工厂模式(Simple Factory Pattern)
- 工厂方法模式(Factory Method Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 单例模式(Singleton Pattern)
创建型模式
工厂模式
什么是工厂模式呢?首先我们来看一下工厂模式的定义:
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
-
该模式的动机在于:
定义一个创建对象的接口,通过不同的参数传递,让其子类决定具体创建哪一类型的实例,工厂模式让对象的创建过程延迟到了子类过程创建。对用户来讲,不用关心对象是怎么创建的,只需要知道不同的参数条件便可触发创建不同的实例即可。 -
应用场景:
1.日志记录器:对于用户来讲,日志可以保存到本地硬盘、系统事件、远程服务器,而为了将日志记录器和系统的其他功能解耦合,故可用日志记录器,只暴露一个接口传递参数,让工厂类创建实例即可。
2.数据库访问:对于用户来讲,用户可能不知道系统最终会选择什么数据库,以及数据库可能产生变化时,故可使用工厂模式,隐藏数据库创建过程,暴漏接口供系统调用。
3.设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。
可以拿富士康工厂来举例。
简单工厂模式(Simple Factory Pattern)
-
工厂说明
在富士康中会生产很多类型的手机,比如苹果、三星、诺基亚等等牌子的手机,工厂可随意指定生产线生产某一个品牌的手机。 -
UML图
-
结构组成
模式结构包括如下:- Factory:工厂角色
工厂角色负责实现创建所有实例的内部逻辑 - Product:抽象产品角色
抽象产品角色是所创建的所有对象的父类,负责描述所有实例所共有的公共接口 - ConcreteProduct:具体产品角色
具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。
- Factory:工厂角色
-
简单工厂的缺点
扩展性非常差,当需要添加新的产品时,需要更改工厂类,违背了开放-封闭原则(软件实体(类、模块、函数等等)应该可以扩展,但是不可以修改。) -
简单工厂代码
Phone()为抽象类,用于子类的共同函数,开放接口为show(),用于显示品牌信息。
ApplePhone()、SamsungPhone()、NokiaPhone()为子类,具体类实现过程在此类中实现。
#include <iostream>
#include <string>
class Phone{
public:
virtual ~Phone() {}
virtual void show() = 0;
};
class ApplePhone : public Phone {
public:
void show() {
std::cout << "ApplePhone created" << std::endl;
}
};
class SamsungPhone : public Phone {
public:
void show() {
std::cout << "SamsungPhone created" << std::endl;
}
};
class NokiaPhone : public Phone {
public:
void show() {
std::cout << "NokiaPhone created" << std::endl;
}
};
enum PhoneType
{
APPLE,
SAMSUNG,
NOKIA
};
class PhoneFactory {
public:
Phone* createPhone(PhoneType phone_type) {
switch (phone_type)
{
case APPLE:
return new ApplePhone();
case SAMSUNG:
return new SamsungPhone();
case NOKIA:
return new NokiaPhone();
default:
return nullptr;
}
}
};
int main()
{
PhoneFactory phoneFactory;
Phone* pApplePhone = phoneFactory.createPhone(APPLE);
if (pApplePhone) {
pApplePhone->show();
delete pApplePhone;
pApplePhone = nullptr;
}
return 0;
}
运行结果:
ApplePhone created
工厂方法模式(Factory Method Pattern)
-
模式动机
现在对该系统进行修改,不再设计一个工厂类来统一负责所有产品的创建,而是将具体手机的创建过程交给专门的工厂子类去完成,我们先定义一个抽象的手机工厂类,再定义具体的工厂类来生成苹果手机、三星手机、诺基亚手机等,它们实现在抽象手机工厂类中定义的方法。这种抽象化的结果使这种结构可以在不修改具体工厂类的情况下引进新的产品,如果出现新的手机类型,只需要为这种新类型的按钮创建一个具体的工厂类就可以获得该新牌子手机的实例,这一特点无疑使得工厂方法模式具有超越简单工厂模式的优越性,更加符合“开闭原则”。
工厂方法模式和简单工厂模式的区别在于,工厂方法将创建具体实例的过程封装到了具体工厂类中,由具体的工厂类来实现某一个产品的创建。当有新的产品需要创建时,只需添加新的工厂类即可。 -
模式定义
工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。 -
XML结构图
-
模式结构:
- Product:抽象产品 Phone()
- ConcreteProduct:具体产品
- Factory:抽象工厂PhoneFactory()
- ConcreteFactory:具体工厂
-
优点:
- 用户只需关注具体某一种产品的实现,对其他产品的实例化过程进行隐藏。
- 所有具体类都共用同一个抽象类
- 当有新的产品需求时,只需增加新的具体产品类和新的具体工厂类,不用对抽象类进行删改。满足了开放-封闭原则
-
缺点:
- 在增加新的产品时,需要同时增加具体产品类和具体工厂类,增加了系统的编译负担。
- 在创建实例时,需要将抽象类暴漏给用户,因为有太多抽象类,不容易让用户理解。
-
工厂方法模式代码
#include <iostream>
#include <string>
class Phone {
public:
virtual ~Phone() {}
virtual void show() = 0;
};
class ApplePhone : public Phone {
public:
void show() {
std::cout << "ApplePhone created" << std::endl;
}
};
class SamsungPhone : public Phone {
public:
void show() {
std::cout << "SamsungPhone created" << std::endl;
}
};
class NokiaPhone : public Phone {
public:
void show() {
std::cout << "NokiaPhone created" << std::endl;
}
};
class PhoneFactory {
public:
virtual ~PhoneFactory() {}
virtual Phone* createPhone() = 0;
};
class AppleFactory : public PhoneFactory{
public:
Phone* createPhone() {
return new ApplePhone();
}
};
class SamsungFactory : public PhoneFactory {
public:
Phone* createPhone() {
return new SamsungPhone();
}
};
class NokiaFactory : public PhoneFactory {
public:
Phone* createPhone() {
return new NokiaPhone();
}
};
int main()
{
PhoneFactory* pPhoneFactory = new AppleFactory();
Phone* pApplePhone = pPhoneFactory->createPhone();
pApplePhone->show();
delete pApplePhone;
delete pPhoneFactory;
return 0;
}
抽象工厂模式(Abstract Factory Pattern)
单例模式(Singleton Pattern)
TODO