设计模式——创建型模式

抽象工厂模式、建造者模式、工厂方法模式、原型模式、单例模式都属于创建型模式,即与对象的创建有关的模式,但是功能越接近越难以区分,他们在创建对象的过程中各自有承担着什么杨的责任,他们该在什么地方使用呢?这使我们分类后不得不接近的问题。

抽象工厂模式:

抽象工厂模式的使用情况

1.系统不依赖于产品类实例如何被创建,组合和表达的细节。

2.系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。

3.同属于同一个产品是在一起使用的。这一约束必须在系统的设计中体现出来。

4.系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

优缺点:

优点:

隔离了具体类的生成,使得客户不需要知道什么被创建

当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。

缺点:

添加新的产品对象时,难以扩展抽象工厂以便产生新种类的产品。

抽象模式最大的好处是易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。

设计模式——创建型模式

建造者模式

建造者模式的使用情况:

以下情况应当使用建造者模式:

1、需要生成的产品对象有复杂的内部结构。

2、需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。

3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。

优缺点:

优点:1、建造者模式的使用使得产品内部表象可以独立的变化,使客户端不必知道产品内部组成细节。

2、每一个Builder都相对独立,而与其它的Builder无关。

3、可以使对构造过程更加精细控制,以降低控制细节的风险。

4、将构建代码和表示代码分开。

缺点:1、由于其的变化点在于对象创建的细节,故其也难于分步骤构建的算法需求的变动,因为其关注的是对象创建顺序。

建造者模式一般适用于稳定的系统,比如说同样是对人的描述,如果描述的是正常人,就可用,但是对于残疾人,因为系统不再稳定,再使用的话就无法满足“开闭原则”了。

设计模式——创建型模式

工厂方法模式:

工厂方法模式的使用情况:

第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。Java Collection中的iterator() 方法即属于这种情况。

第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。

工厂方法模式的优缺点

1、可以在不知具体实现的情况下编程
工厂方法模式可以让你在实现功能的时候,如果需要某个产品对象,只需要使用产品的接口即可,而无需关心具体的实现。选择具体实现的任务延迟到子类去完成。

2、更容易扩展对象的新版本
工厂方法给子类提供了一个挂钩,使得扩展新的对象版本变得非常容易。比如上面示例的参数化工厂方法实现中,扩展一个新的导出Xml文件格式的实现,已有的代码都不会改变,只要新加入一个子类来提供新的工厂方法实现,然后在客户端使用这个新的子类即可。
另外这里提到的挂钩,就是我们经常说的钩子方法(hook),这个会在后面讲模板方法模式的时候详细点说明。

3、连接平行的类层次
工厂方法除了创造产品对象外,在连接平行的类层次上也大显身手。这个在前面已经详细讲述了。

4、具体产品对象和工厂方法的耦合性
在工厂方法模式里面,工厂方法是需要创建产品对象的,也就是需要选择具体的产品对象,并创建它们的实例,因此具体产品对象和工厂方法是耦合的。

设计模式——创建型模式

原型模式:

其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的。

有的时候,我们需要一个实例时,并且,当创建一个实例的过程比较复杂或者说是昂贵时,

比如,创建实例的构造函数非常的复杂,在执行这个构造函数时会消耗较长的时间,同时呢,这个构造函数中的一些信息又没有什么变化(也就是说创建第一个实例时初始化信息是这样的,创建第二个实例时初始化信息还是还是这样的),那么直接使用 new 来创建这样一个实例就显得太昂贵了,最好的解决方法,并不是使用 new 来实例化一个对象,而是使用克隆,也就是复制,克隆呢,就是通过复制现在已经有了的实例来创建新的实例

浅复制和深复制

浅复制又称为浅拷贝,深复制又称为深拷贝。浅复制的话,就是通过一个原型实例(这里暂称为老对象)克隆所得到的对象(这里暂时称为新对象),而这个新对象中所有的值类型变量都含有与老对象相同的值,但是,新对象所有的对其他对象的引用却是和老对象指向同一个地方,即对引用类型来说,老对象和新对象指向同一个引用对象。深复制呢,和浅复制就一点不同,那就是,新对象所有的对其他对象的引用都是指向了复制过的对象,而不再是和老对象指向同一个对象。

设计模式——创建型模式

单例模式:

实现单例模式的思路是:

一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。

单例模式在多线程的应用场合下必须小心使用。如果当唯一实例尚未创建时,有两个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自创建了一个实例,这样就有两个实例被构造出来,从而违反了单例模式中实例唯一的原则。解决这个问题的办法是为指示类是否已经实例化的变量提供一个互斥锁(虽然这样会降低效率)。

优点

实例控制:Singleton 会阻止其他对象实例化其自己的Singleton 对象的副本,从而确保所有对象都访问唯一实例

灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程

缺点

开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题,上面的五种实现方式中已经说过了。

可能的开发混淆:使用 singleton 对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用 new 关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。

设计模式——创建型模式

从开始写这篇博客到现在,已经有几天了,一方面这几天专业课比较多,而考试在即,不得不听,另一方面其实自己对设计模式的理解还是模糊的很,刚刚学完的时候感觉还不错,基本上每个模式都能理解,而且自己能想出一个不错的用法,但是真正要把它写成博客,写出自己的东西,发现是难之又难,这几天oneNote的笔记猛增,就是因为一直在上网查,可以说网上的资源太多了,当了解的越多反而越糊涂,有时候甚至本来感觉自己是明白的查完之后完全就糊涂了,最后七拼八凑的写了这么一篇,当然,我的任务不是创新,而是整理,虽然整理的也是差强人意,有时候都开始佩服那些写出这样文章的人了,不过,又想起那句提高班一次次被提起的话“前途是光明的,道路是曲折的,忍着吧!!!”。

忍着吧,接受现在的困扰,努力去做到“柳暗花明又一村”!