设计模式是一些编程方式,用来解决某一类特殊问题的一种最佳实践,在面向对象编程中有着举足轻重的地位。
但是,以上的方法只适用于单线程环境,在多线程环境下就会出现问题:如果两个线程同时运行到判断instance是否为null的语句时,若此时instance还没有创建,则此时两个线程都会各自创建一个实例,这样就破坏了单例模式的要求(只能创建某一特定类类型的一个单一的实例)。多线程的问题可以通过加同步锁来解决。
单例模式模式适用于需要而且只能有一个对象的场景下。如一个web站点需要一个数据库连接对象,并将所有数据库连接都放在这个对象上;或者需要创建一个全局对象的场景下,如一个web应用程序需要使用同一个配置对象,这时候可以用单例模式实现一个config类。
工厂模式的实现是把工厂类抽象出一个接口,该接口有一个创建抽象产品的工厂方法。让客户来决定实例化哪一类的工厂。
组合模式的使用环境:当需求中是体现部分和整体层次的结构时,希望可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时。
代理模式的使用环境:
设计模式可以分成3个大类:
- 创建型模式
- 结构型模式
- 行为型模式
其中,
- 创建型模式用以创建对象。包含了创建者模式、工厂模式、原型模式和单例模式
- 结构型模式帮助我们创造和使用复杂的结构。包含了适配器模式、桥接模式、组合模式、装饰模式、外观模式和代理模式
- 行为型模式描述了对象在系统中的通信方式和程序的逻辑控制流。包含了命令模式、迭代器模式、观察者模式、状态模式、策略模式和模板方法模式
单例模式
单例模式限制应用程序,使其只能创建某一特定类类型的一个单一的实例。由于要求只能生成一个实例,所以可以把构造函数设置为私有函数,从而禁止他人创建实例。
class Singleton{
static private $instance = NULL;
private function __construct(){};
private function __clone(){};
static function getInstance(){
if(self::$instance == NULL){
self::$instance = new Singleton();
}
return self::$instance;
}
... ...
}
但是,以上的方法只适用于单线程环境,在多线程环境下就会出现问题:如果两个线程同时运行到判断instance是否为null的语句时,若此时instance还没有创建,则此时两个线程都会各自创建一个实例,这样就破坏了单例模式的要求(只能创建某一特定类类型的一个单一的实例)。多线程的问题可以通过加同步锁来解决。
单例模式模式适用于需要而且只能有一个对象的场景下。如一个web站点需要一个数据库连接对象,并将所有数据库连接都放在这个对象上;或者需要创建一个全局对象的场景下,如一个web应用程序需要使用同一个配置对象,这时候可以用单例模式实现一个config类。
工厂模式
工厂模式和单例模式都是创建型模式,不同的是:单例模式创建和管理一个单独的类型的单一对象,而工厂模式则被用于创建多个不同类型的类的多个对象。
简单工厂模式
简单工厂模式:客户端传一个条件进工厂类,工厂类根据条件创建相应的产品类对象,并将产品类对象 return 给客户端使用。
简单工厂模式的实现一般通过一个静态方法,如factory(),这个方法至少要接收一个参数,用于标识将要创建的对象的类型,并会返回一个该类型的对象。
static function factory($type){
//validate $type
return new SomeClassType();
}
简单工厂模式的使用环境:当编写程序的时候并不能完全确定需要生成的对象的确切类型,只有在程序运行时才能确定的情况下;或者有一个抽象的基类,它的几个不同的派生子类需要立即被创建。这些情况下,将对象的创建工作交给类自己去完成。
工厂模式
工厂模式的实现是把工厂类抽象出一个接口,该接口有一个创建抽象产品的工厂方法。让客户来决定实例化哪一类的工厂。
抽象工厂模式
抽象工厂模式是工厂模式的变种,其提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
工厂模式与抽象工厂模式的区别
- 工厂方法模式中,每个抽象产品派生多个具体产品类,每个抽象工厂类派生多个具体工厂类,每个具体工厂类负责一个具体产品的实例创建;
- 而抽象工厂模式中,每个抽象产品派生多个具体产品类,每个抽象工厂派生多个具体工厂类,每个具体工厂负责多个(一系列)具体产品的实例创建。
组合模式
组合模式的使用环境:当需求中是体现部分和整体层次的结构时,希望可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时。
代理模式
代理模式的使用环境:
- 远程代理:为一个对象在不同的地址空间提供局部代表,可以隐藏一个对象存在于不同地址空间的事实。
- 虚拟代理:对一个开销很大的对象,应该根据需要来创建。通过虚拟代理来存放实例化需要很长时间的真实对象。
- 安全代理:控制真实对象访问时的权限。
- 智能代理:当调用真实的对象的时候,代理处理另外的事情。如计算真实对象的引用次数。
适配器模式
应用场景:
- 使用一个存在的类,而它的接口不符合自己的需求;
- 想要创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作。
适配器模式与代理模式的区别:
- 适配器模式是因为新旧接口不一致导致出现了客户端无法得到满足的问题,但是,由于旧的接口是不能被完全重构掉的,因为我们还想使用实现了这个接口的一些服务。那么为了使用以前实现旧接口的服务,我们就应该把新的接口转换成旧接口;实现这个转换的类就是抽象意义的转换器;
- 虽然代理也同样是增加了一层,但是,代理提供的接口和原本的接口是一样的,代理模式的作用是不把实现直接暴露给client,而是通过代理这个层,代理能够做一些处理。
策略模式
策略模式的实现是把算法类抽象出一个接口,该接口有一个创建算法的策略方法。让客户来决定调用哪一类的策略算法。
策略模式与工厂模式的区别:
- 目的不同:工厂模式是创建型模式,用以创建对象;而策略模式是行为型模式,用以选择不同的算法
- 作用不同:工厂模式是接受类型参数并创建出符合要求的实例,主要解决的是资源的统一分发,将对象的创建完全独立出来,主要应用在多数据库选择,类库文件加载等;策略模式是为了解决的是策略的切换与扩展,定义策略族并分别封装起来,让它们之间可以相互替换。