设计模式-工厂模式
工厂模式属于创建模式
工厂模式可分为3种模式:
1:简单工厂模式
2:工厂方法模式
3:抽象工厂模式
一:简单工厂模式
简单工厂模式又称为静态工厂方法,它属于创建模式。在简单工厂中,可以根据不同的参数返回不同的类实例。简单工厂专门定义了一个负责创建其他类的实例,被创建的实例通常都具有共同的父类。
模式结构角色:
factory: 工厂角色,工厂角色复制创造所有实例的内部逻辑
product:抽象产品角色,抽象产品角色是所有创建的所有对象的父类,负责描叙所有实例所共有的公共接口
ConcreteProduct:具体产品角色,具体产品角色是创建目标,所有创建的对象都充当这个个角色的某个具体类的实例。
例子:
1. 比如说一些数据库的链接,MySQL, Oracle,SqlServer 连接方式 connectMode和查询方式queryMode等可以使用工厂模式进行封装
<?php //抽象产品角色 interface Connection { public function connection($dsn); } class MySQLConnection implements Connection { public function connection($dsn) { echo "I am MySQLConnection: " . $dsn; } } //具体产品角色 class OracleConnection implements Connection { public function connection($dsn) { echo "I am OracleConnection: " . $dsn; } } //具体产品角色 class SQLServerConnection implements Connection { public function connection($dsn) { echo "I am SQLServerConnection: " . $dsn; } } //工厂角色 class SimpleFactory { //========简单工厂的静态方法 1 ======== static function createMySQLConn() { return new MySQLConnection(); } static function createOracleConn() { return new OracleConnection(); } static function createSQLServerConn() { return new SQLServerConnection(); } //========简单工厂的静态方法 2 ======== public static function createConnection($connType, $dsn) { switch ($connType) { case 'mysql': $conn = new MySQLConnection($dsn); break; case 'oracle': $conn = new OracleConnection($dsn); break; default: echo "param error"; break; } } } //简单工厂 1 $MySQLConn = SimpleFactory::createMySQLConn(); $dsn = "mysql conn"; $MySQLConn->Connection($dsn); echo "\r\n"; $SQLServerConn = SimpleFactory::createSQLServerConn(); $dsn = "sqlserver conn"; $SQLServerConn->Connection($dsn);
优点:
工厂可以决定在什么时候创建哪一种产品,客户端可以避免直接创建产品对象的责任,而仅仅是消费产品,简单工厂模式通过这种方法实现了对责任的分割
客户端无需知道具体的产品类的名称,只需要记住产品类对应的参数
缺点:
工厂类集中了所有产品创建的逻辑,一旦不能正常工作,则会影响整个系统。
简单工厂增加了类的个数,一定程度增加了程序复杂性。
系统扩展困难,一旦增加了新的产品,还要去修改工厂类,在产品类多的时候,可能造成工厂逻辑复杂
所以使用这种模式要根据具体的情况而定
二:工厂方法模式
在工厂方法模式中,工厂父类负责和定义创建产品对象的工作接口,二工厂子类则负责生成具体的产品对象,
这样做是为了将产品类的实例化操作延迟到了工厂子类中完成,及是通过子类来实例化一个具体产品类
工厂方法模式包含如下角色:
Product:抽象产品
ConcreteProduct:具体产品
Factory:抽象工厂
ConcreteFactory:具体工厂
代码示例:
有一只猫,不管是黑猫还是白猫,他们的名字也叫黑猫和白猫
<?php //抽象产品 interface Cat { public function getName(); } //具体产品 class BlackCat implements Cat { function getName() { return "This is an black cat"; } } class WhiteCat implements Cat { function getName() { return "this is a white cat"; } } //抽象工厂方法 interface CommonFactory { public function getCat(); } //具体工厂实现 class BlackCatFactory implements CommonFactory { function getCat() { return new BlackCat(); } } class WhiteCatFactory implements CommonFactory { function getCat() { return new WhiteCat(); } } //调用 $factory = new BlackCatFactory(); echo $factory->getCat()->getName(); echo "\r\n"; $factory = new WhiteCatFactory(); echo $factory->getCat()->getName();
优点:
在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户还隐藏了产品类被实例化这一细节,用户无需关心产品类的类名
基于工厂角色和产品角色的多态设计是工厂方法的关键。它能够使工厂可以自主确定创建何种产品对象。工厂方法又被称为多态工厂模式,是因为所有的具体工厂类都有统一抽象的父类。
使用工厂方法另外一个优点是加入新产品时,无需修改抽象产品和抽象工厂提供的接口,无需修改客户端,也无需修改具体的产品和具体工厂,而只需添加一个具体的工厂和一个具体的产品。这样就符合”开闭原则“了
缺点:
在添加新产品时候,需要编写新产品类,还要提供与之对应的具体工厂类,类增加了 。
考虑到系统可扩展性,引入了抽象层,增加了系统的抽象性和难度。
三:抽象工厂模式
提供一个创建一组列相关或者相互依赖对象的接口,而无需指定他们具体的类
系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式
<?php //抽象产品 interface AnimalInterface { public function color(); } //具体产品 class BlackCat implements AnimalInterface { public function color() { echo "I am black cat"; } } class WhiteCat implements AnimalInterface { public function color() { echo "I am white cat"; } } class BlackDog implements AnimalInterface { public function color() { echo "I am black dog"; } } class WhiteDog implements AnimalInterface { public function color() { echo "I am white dog"; } } //抽象工厂 interface createAnimalInterface { public function createWhiteAnimal(); public function createBlackAnimal(); } //具体工厂 class FactoryCat implements createAnimalInterface { public function createWhiteAnimal() { return new WhiteCat(); } public function createBlackAnimal() { return new BlackCat(); } } class FactoryDod implements createAnimalInterface { public function createWhiteAnimal() { return new WhiteDog(); } public function createBlackAnimal() { return new BlackDog(); } } $catFactory = new FactoryCat(); $catFactory->createWhiteAnimal()->color(); echo "\r\n"; $catFactory->createBlackAnimal()->color();
优点:
当一个产品中,有多个对象在一起工作时,它能保证客户端只使用同一组产品中的对象。
增加新的工厂很方便,无需修改已有系统
缺点:
比较难以扩展抽象工厂来生成新的产品,因为抽象工厂规定了可能被创建的产品集合,要支持新种类产品就
意味着对该接口扩展,这会涉及到抽象工厂子类的修改,如果子类比较多,那么修改也多