一、簡單工廠模式
簡單工廠模式又叫靜態工廠方法模式,他定義一個具體的工廠類負責創建一些類的實例。
優點:客戶端不需要在負責對象的創建,從而明確了各個類的職責。
缺點:這個具體的工廠類要負責所有類的對象的創建,如果有新的對象增加或者某些類的創建方式不同,就需要不斷的修改這個工廠類,不利於後期的維護和擴展。
下面我們通過代碼通俗易懂的瞭解一下:
//抽象動物類
public abstract class Animal {
public abstract void eat();
}
//狗類
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
//貓類
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("貓吃魚");
}
}
以上內容和簡單工廠方法本身沒有太大的關聯,重點在下一個動物工廠類
//動物工廠類
public class AnimalFactory {
//構造方法私有就只能通過靜態方法創建對象了
private AnimalFactory(){}
public static Animal createAnimal(String type){
if("dog".equals(type)){
return new Dog();
}else if("cat".equals(type)){
return new Cat();
}else{
return null;
}
}
}
//測試類
public class Test {
public static void main(String[] args) {
Animal a=AnimalFactory.createAnimal("cat");
a.eat();//貓吃魚
a=AnimalFactory.createAnimal("dog");
a.eat();//狗吃肉
}
}
那麼可以看到,我們要創建狗或貓的對象,不用去找狗或者貓,找動物工廠就可以幫我們造出相應的對象,那如果我還想要獅子、老虎、鱷魚、斑馬這些動物,就要不停的改寫動物工廠類裏面createAnimal()這個方法,很顯然,這樣做非常不利於維護和擴展,不符合面向對象設計原則裏面的開閉原則。
二、工廠方法模式
工廠方法模式就是爲了彌補簡單工廠模式的不足而設計的。工廠方法模式中抽象工廠類或者工廠接口負責定義創建對象的接口,具體對象的創建工作由抽象工廠類和工廠接口的具體實現類來完成。工廠方法模式和簡單工廠模式的區別顯而易見:工廠方法模式工廠類或接口並不負責創建對象,他是一個抽象的,具體的創建工作有抽象工廠的實現類來負責,而簡單工廠模式工廠類是具體的,他要實實在在的的負責創建對象,那肯定很辛苦了,前者抽象工廠是老大,創建對象的事情小弟去做就行了。
//抽象動物類
public abstract class Animal {
public abstract void eat();
}
//狗類
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
//貓類
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("貓吃魚");
}
}
以上內容和工廠方法模式本身沒有太大的關聯,重點在下一個抽象工廠接口
//抽象工廠
public interface Factory {
public abstract Animal createAnimal();
}
//狗工廠
public class DogFactory implements Factory {
@Override
public Animal createAnimal() {
return new Dog();
}
}
//貓工廠
public class CatFactory implements Factory {
@Override
public Animal createAnimal() {
return new Cat();
}
}
//測試類
public class Test {
public static void main(String[] args) {
Factory f=new DogFactory();
Animal a=f.createAnimal();
a.eat();//狗吃肉
f=new CatFactory();
a=f.createAnimal();
a.eat();//貓吃魚
}
}
如果這個時候我們還想要老虎獅子等更多的動物,那就只需要增加相關的老虎工廠、獅子工廠就可以了,而不需要在改動抽象工廠。
三、單例模式
單例模式:保證類在內存中只有一個對象
如何保證類在內存中只有一個該類的對象:
(1)把構造方法私有,這樣外界就不能通過構造方法創建對象
(2)在成員位置創建一個自己的對象(私有)
(3)通過公共方法提供訪問
單例模式分爲餓漢式和懶漢式,所謂餓漢式就是指類一加載就創建對象,懶漢式是指用的時候再創建對象。
1、餓漢式單例
public class Student {
private Student(){}//構造私有
private static Student s=new Student();//成員位置的私有對象
public static Student getStudent(){//對外提供公共的訪問方法
return s;
}
}
餓漢式單例的對象在類一加載就會創建,不存在線程安全問題,可以保證在內存中只存在一個實例。
2、懶漢式單例
public class Teacher {
private Teacher(){}//構造私有
private static Teacher t=null;//成員位置的對象
public static synchronized Teacher getTeacher(){//對外提供公共訪問方法
if(t==null){
t=new Teacher();
}
return t;
}
}
這是懶漢式單例,由於懶漢式單例在多線程環境下可能存在同步問題,所以加上synchronized關鍵字可以保證線程安全,但是如果這樣的話,每個線程需要獲取對象的時候都要獲取鎖,如果獲取不到就要阻塞,無形之間降低了併發的效率,所以我們可以嘗試降低鎖的粒度,如下:
public class Teacher {
private Teacher(){}//構造私有
private static Teacher t=null;//成員位置的對象
public static Teacher getTeacher(){//對外提供公共訪問方法
if(t==null){
synchronized(Teacher.class){
t=new Teacher();
}
}
return t;
}
}
這樣如果對象已經存在的話,就不需要再進入臨界區了。