我是设计模式的新手,我不能真正看到这两种模式之间的区别,两者都是创作模式不是吗?每种模式的目的是什么?感谢。
答案 0 :(得分:62)
单例模式可确保您始终返回您正在检索的任何类型的实例,而工厂模式通常会为您提供每种类型的不同的实例。
单身人士的目的是让所有呼叫都通过同一个实例。这方面的一个例子可能是管理磁盘缓存或从静态字典中获取数据的类;只要重要的是,只有一个已知实例与资源交互。这确实降低了它的可扩展性。
工厂的目的是创建并返回新实例。通常,这些实际上根本不是同一类型,但它们将是相同基类的实现。但是,每种类型可能有许多实例
答案 1 :(得分:20)
当只需要单个资源实例时,单个模式是许多应用程序中经常使用的模式。 PHP网页最明显的资源类型是数据库连接,但可以使用其他资源类型。在获取动态创建网页时,可能需要进行多次数据库调用。如果可以使用单个资源实例,而不是创建多个连接,则会减少开销。在这种情况下,单个实例由单例模式创建。
<?php
class db {
/*** Declare instance ***/
private static $instance = NULL;
/**
* the constructor is set to private so
* so nobody can create a new instance using new
*/
private function __construct() {
/*** maybe set the db name here later ***/
}
/**
* Return DB instance or create intitial connection
* @return object (PDO)
* @access public
*/
public static function getInstance() {
if (!self::$instance) {
self::$instance = new PDO("mysql:host='localhost';dbname='animals'", 'username', 'password');
self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
return self::$instance;
}
/**
* Like the constructor, we make __clone private
* so nobody can clone the instance
*/
private function __clone() {
}
} /*** end of class ***/
?>
让我们看看上面的单身人士课程中发生了什么。变量名$instance
已创建并生成private
,这可确保无人并尝试直接访问它。类似地,构造函数和__clone方法已被设置为私有,以防止克隆类,或者某人试图实例化它的实例。该类有一种提供资源的方法,即getInstance()
方法。
getInstance()
方法检查实例是否尚不存在。如果不存在实例,则会创建PDO类的新实例并将其分配给$instance
变量。如果现有实例可用,getInstance()
方法将返回此实例。结果是返回的值始终是相同的实例,并且不需要新的资源或开销。
这是一个关于如何在应用程序中使用它的小型演示。
<?php
try {
/*** query the database ***/
$result = DB::getInstance()->query("SELECT animal_type, animal_name FROM animals");
/*** loop over the results ***/
foreach ($result as $row) {
print $row['animal_type'] .' - '. $row['animal_name'] . '<br />';
}
} catch (PDOException $e) {
echo $e->getMessage();
}
?>
工厂模式是一个为您创建对象的类,而不是您需要使用new关键字来自己创建对象。顾名思义,工厂是一个用于创建物体的工厂。我们为什么需要这个?让我们考虑使用ini
文件进行配置选项的应用程序。然后更改应用程序以从数据库获取配置选项。除了基座之外,应用程序的其余部分就像纸牌屋一样崩溃。
对象的“紧耦合”,其中每个对象严重依赖于另一个对象,在较大的应用程序中产生问题。需要一个系统,其中对象可以相互引用,但不是相互依赖的
在我们的配置文件成为数据库的示例中,如果其他类依赖于从ini
文件读取的类,并且突然对数据库类负责,则会出现问题。
通过使用工厂设计模式,如果将对象类型从ini
reader类更改为数据库类,则只需更改工厂。使用工厂的任何其他代码都将自动更新。
<?php
/**
* @config interface
*/
interface Config {
function getName();
}
/**
* @config class
*/
class userConfig implements Config {
/*
* @username
*/
public $user_id;
/*** contructor is empty ***/
public function __construct($id) {
$this->user_id = $id;
}
public static function Load($id) {
return new userConfig($id);
}
public function getName() {
try {
/*** query the database ***/
$sql = "SELECT username FROM user_table WHERE user_id=:user_id";
$db = db::getInstance();
$stmt = $db->prepare($sql)
$stmt->bindParam(':user_id', $this->user_id, PDO::PARAM_INT);
return $stmt->fetch(PDO::FETCH_COLUMN);
} catch (PDOException $e) {
/*** handle exception here ***/
return false;
}
}
} /*** end of class ***/
/*** returns instance of config ***/
$conf = userConfig::Load( 1 );
echo $conf->getName();
?>
这对于简单地检索用户名而言似乎有点过多的代码。但是,在从基于文件到数据库检索的更改的大规模应用程序中,结果可能是灾难性的。这里只需要更改getName()
方法检索名称,返回的对象是相同的,从而允许应用程序的其他需要用户名的部分,例如:登录购物车,继续就像他们以前一样。
答案 2 :(得分:6)
+---------------------------+-------------------------------+
| Singleton | Factory |
+---------------------------+-------------------------------+
| Returns Same instance | Returns various new instances |
| Single Constructor hiding | Multiple Constructors expose |
| No interface | Interface driven |
| No Subclasses | Subclasses |
+---------------------------+-------------------------------+
答案 3 :(得分:5)
Singleton模式确保只存在该类的一个实例,并且通常提供一个众所周知的,即访问它的全局点。
Factory模式定义了一个用于创建对象的接口(不限制数量),并且通常抽象控制要实例化的类。
答案 4 :(得分:3)
单例模式是一种模式,其目的是确保无论客户端(或多个客户端)要求为其创建(实例化)此特定类型的实例多少次,它们总是会得到完全相同的一个且只有一个类型的实例。它保证只能实例化该类型的一个实例(例如,如果Type正在管理某个数据结构的内存缓存副本中的200 MByte - 您只需要存在一个副本)Singleton Type通常会有一个工厂其中的方法是向请求客户端传递一个且只有一个实例。
Factory方法是一种封装类型的创建或实例化的方法,以便类型本身可以控制实例化的方式。
答案 5 :(得分:0)
Singleton始终返回同一个类实例,工厂可以通过实例化各种类创建对象,或者使用其他 分配方案 (如对象池)。所以单例可以在工厂模式中使用