简述
工厂模式分三种类型。
1. 简单工厂模式。
2. 工厂方法模式。
3. 抽象工厂模式。
设计的原则和思想
把对象的创建封装在工厂类中,解耦对象的创建和使用。
产品等级结构和产品族
产品等级结构 :
继承结构,就是同类。例如,华为手机,小米手机,魅族手机,这些都是具体实现类,抽象类是手机。
产品族 :
是同一个牌子的产品,都是由同一个工厂生产的。例如,华为手机,华为平板,华为电脑,这些构成了一个华为的产品族。
简单工厂模式 - Simple Factory Pattern
定义
1. 一个工厂类,根据参数的不同返回不同类的实例。
2. 简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式。
一句话概括设计模式
一个静态方法返回产品对象。
结构中包含的角色
1. Factory(工厂角色)
2. Product(抽象产品角色)
3. ConcreteProduct(具体产品角色)
最小可表达代码
// 产品
abstract class Product {}
class ConcreteProductA extends Product {}
class ConcreteProductOther extends Product {}
// 简单工厂
class SimpleFactory {
public static getProduct($param) : Product
{
if ("A" == $param) {
return new ConcreteProductA();
}
return new ConcreteProductOther();
}
}
优点
- 根据参数就可以创建产品,不需要知道产品的具体实现。
- 实现对象的创建和使用分离。
缺点
- 随着时间的推移,产品的具体类逐渐增多,工厂的逻辑会逐渐复杂,不利于系统的扩展和维护。
- 增加产品等级结构,需要增加对应的工厂类,增加产品族也必须修改工厂类。
何时使用
- 根据不同的条件生成不同的对象,并且创建的对象比较少,例如框架中配置的驱动。
- 一个对象的创建比较复杂。
实际应用场景
- PDO中的数据库驱动。Mysql,DB2,还是Oracle。
工厂方法模式 - Factory Method Pattern
定义
- 一个用于创建对象的接口,让子类决定将哪一个类实例化(一个工厂实例化一个产品类)。
- 工厂方法模式又简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。
一句话概括设计模式
不同的工厂返回不同的产品对象。
结构中包含的角色
- Product(抽象产品)
- ConcreteProduct(具体产品)
- Factory(抽象工厂)
- ConcreteFactory(具体工厂)
最小可表达代码
// 产品
interface Product {}
class ConcreteProductA implements Product {}
class ConcreteProductOther implements Product {}
// 工厂
interface Factory {
public function createProduct() : Product;
}
class ConcreteFactoryA implements Factory {
public public createProduct() : Product
{
return new ConcreteProductA();
}
}
class ConcreteFactoryOther implements Factory {
public public createProduct() : Product
{
return new ConcreteProductOther();
}
}
优点
- 客户端只要知道产品对应的工厂即可,不需要知道具体产品的类名。
- 新增产品只需要添加一个具体工厂和具体产品就可以了,可扩展性非常好。
缺点
- 新增产品会导致系统中存在大量的工厂类。
- 使用了抽象,并且实现时可能还会用到反射或者IOC,增加了系统的复杂度。
何时使用
- 工厂方法模式实际上是多个简单工厂模式的集合。所以,当简单工厂里面的产品过多时,可以使用工厂方法模式解耦。
- 运行时动态决定所需的类。可将具体工厂类的类名存储在配置文件,运行时通过反射实例化。虽然简单工厂也可以做到,但是违反了开闭原则。
实际应用场景
- 商城的商品有精选商品,收藏的商品,销售最高的商品,每类商品都有所差异,可以使用工厂方法模式设计。
- 框架中,通过配置实例化类。例如laravl中,通过config/cache配置选择缓存(redis 或 memcached)驱动。
抽象工厂模式-Abstract Factory Pattern
定义
提供一个创建一系列相关或相互依赖对象的接口(每个工厂负责创建整个产品族),而无须指定它们具体的类。
一句话概括设计模式
一个工厂有不同的方法,不同的方法返回不同的产品对象。简单就是一个工厂返回一系列产品。
结构中包含的角色
- AbstractFactory(抽象工厂)
- ConcreteFactory(具体工厂)
- AbstractProduct(抽象产品)
- ConcreteProduct(具体产品)
最小可表达代码
// 手机产品
interface Phone {}
class HuaWeiPhone implements Phone {}
class XiaoMiPhone implements Phone {}
// 笔记本产品
interface NoteBook {}
class HuaWeiNoteBook implements NoteBook {}
class XiaoMiNoteBook implements NoteBook {}
// 工厂
interface Factory {
public function createPhone() : Phone;
public function createNoteBook() : NoteBook;
}
// 华为工厂
class HuaWeiFactory implements Factory {
public function createPhone() {
return new HuaWeiPhone();
}
public function createNoteBook() {
return new HuaWeiNoteBook();
}
}
// 小米工厂
class XiaoMiFactory implements Factory {
public function createPhone()
{
return new XiaoMiPhone();
}
public function createNoteBook() {
return new XiaoMiNoteBook();
}
}
优点
- 增加新的产品族(新增具体工厂和具体产品)无须修改已有系统,符合开闭原则。
缺点
- 增加新的产品等级结构(所有具体工厂都要修改,新增抽象产品和具体产品),需要对原有系统进行较大的修改。
何时使用
- 抽象工厂模式实际上是多个工厂方法模式的集合。所以,当工厂方法模式里面存在多个产品等级结构时,可以使用抽象工厂模式。
- 同一个产品族的产品,它们之间打包在一起使用。
实际应用场景
- 同一个产品族的产品。qq皮肤,窗口和菜单都属于同一个主题。
- 不同操作系统的程序。按钮与文本框都是属于某一操作系统。