设计模式可分为三大类:
模式描述 | 包括 |
---|---|
创建型模式 | 工厂模式(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) |
我们将详细阐述一下三大类其中比较常用的设计模式,并简要分析一下利弊。
什么是工厂模式呢?首先我们来看一下工厂模式的定义:
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
该模式的动机在于:
定义一个创建对象的接口,通过不同的参数传递,让其子类决定具体创建哪一类型的实例,工厂模式让对象的创建过程延迟到了子类过程创建。对用户来讲,不用关心对象是怎么创建的,只需要知道不同的参数条件便可触发创建不同的实例即可。
应用场景:
1.日志记录器:对于用户来讲,日志可以保存到本地硬盘、系统事件、远程服务器,而为了将日志记录器和系统的其他功能解耦合,故可用日志记录器,只暴露一个接口传递参数,让工厂类创建实例即可。
2.数据库访问:对于用户来讲,用户可能不知道系统最终会选择什么数据库,以及数据库可能产生变化时,故可使用工厂模式,隐藏数据库创建过程,暴漏接口供系统调用。
3.设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。
可以拿富士康工厂来举例。
工厂说明
在富士康中会生产很多类型的手机,比如苹果、三星、诺基亚等等牌子的手机,工厂可随意指定生产线生产某一个品牌的手机。
UML图
结构组成
模式结构包括如下:
简单工厂的缺点
扩展性非常差,当需要添加新的产品时,需要更改工厂类,违背了开放-封闭原则(软件实体(类、模块、函数等等)应该可以扩展,但是不可以修改。)
简单工厂代码
Phone()为抽象类,用于子类的共同函数,开放接口为show(),用于显示品牌信息。
ApplePhone()、SamsungPhone()、NokiaPhone()为子类,具体类实现过程在此类中实现。
#include
#include
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)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
XML结构图
模式结构:
优点:
缺点:
工厂方法模式代码
#include
#include
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;
}
TODO
上一篇:HashSet原理