注:文章主要参考head first 设计模式,四人帮设计模式以及网上查到的资料,页码主要针对head first设计模式
一.抽象工厂(AbstractFactory)(黑狗黑猫,白狗白猫案例,一个抽象工厂能产生猫和狗及更多的对象):client只用抽象工厂和抽象产品来进行一系列操作。即用接口来作为引用(工厂方法也是)。(披萨制作案例)
二.工厂方法(FactoryMethod)(披萨店及其原料工厂案例)(设计原则:6.要依赖抽象,不要依赖具体类):定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。
PS:利用静态方法定义一个简单的工厂,这是很常见的技巧,常被称为静态工厂,他不需要使用创建对象的方法来实例化对象,缺点是不能通过继承来改变创建方法行为(静态方法可以被子类重写,但不具备多态)。P135
两者区别:
1. 首先它俩解决问题的出发点不同
抽象工厂模式是为了解决”一系列相互依赖的对象”的创建工作;同时由于需求的变化,往往存在着更多系列对象的创建工作”
工厂方法模式是为了解决“某个对象的创建工作,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口。" 换句话说,抽象工厂的产品可能有很多,而且在一个逻辑中存在依赖关系,共同完成一个任务,但是工厂方法只创建一类产品(我遇到的是这种情况),这类产品又有统一的接口。
2. 产品产出的地方不同
抽象工厂模式中由抽象工厂直接创造产品。
工厂方法把产品的生产延迟到子类中
三.单态模型(singleton)(巧克力工厂案例):保证一个类仅有一个实例,并提供一个访问它的全局访问点。
Java实现单件模式需要私有构造器,一个静态方法和一个静态变量。
改善多线程造成的singletonbug:(p181)
1.通过增加synchronized关键字到setInstance()方法中,我们迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法。
2.迫切创建实例:直接:
Public class Singleton{
private static Singleton uniqueInstance=new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return uniqueInstance;}}
3.用双重检查加锁(不适用java1.4及更早版本),如果尚未创建,才进行同步:
public classSingleton{
private volatile staticSingletonuniqueInstance;
/*Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
*/
private Singleton(){}
public static Singleton getInstance(){
if(uniqueInstance==null){//注意只有在第一次才彻底执行这里的代码
synchronized(Singleton.class){
if(uniqueInstance==null){uniqueInstance=new Singleton();}
}
}
}
}
小心如果你使用多个类加载器,可能导致单件失效而产生多个实例(解决方法:自行指定类加载器并指定同一个类加载器)
除非有绝对的必要使用类的单件,否则还是建议使用对象的单件比较保险。
四.建造者模型(Builder)(P615):(4步走,第一步.创建接口;第二步.实现接口;第三步构造一个使用builder接口的对象)将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式的实质是解耦组装过程和创建具体部件,使得我们不用去关心每个部件是如何组装的。就好像我们去KFC,我们买的套餐中的组成元素是先前就有的,但是怎么组合是随机的
这样,通过传入不同的PersonBuilder参数,就可构建出不同的Person。
客户创建Derector对象,并用它所想要的Builder对象进行配置。顾客进入KFC店要买套餐,先找到一个收银员,相当于创建了一个指导者对象。这位收银员给出两种套餐供顾客选择:1普通套餐,2黄金套餐。完成的工作如时序图中红色部分所示。
五.原型模式(prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象