# 1、設計模式
### 1.1 單例模式
* ##### **餓漢式【可用】**
~~~
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
// 構造方法私有化
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
~~~
優點:簡單、線程安全
缺點:非懶加載模式,在類加載時進行初始化,如果自始至終都沒有使用過該對象,那么就造成了內存的浪費
* ##### **懶漢式【不推薦使用】**
~~~
public class Singleton {
private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if (instance == null){
instance = new Singleton();
}
return instance;
}
}
~~~
優點:使用了懶加載的模式,在第一次使用該對象時實例化該對象
缺點:線程不安全,在單線程中可使用,多線程中無效
* ##### 懶漢改進式【不推薦使用】
* ~~~
public class Singleton {
private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
synchronized (Singleton.class){
if (instance == null){
instance = new Singleton();
}
return instance;
}
}
}
~~~
優點:在使用懶加載的基礎上實現了線程安全
缺點:每次獲取對象時多需要進行加鎖,效率比較低。
* ##### 雙重校驗鎖【推薦使用】
* ~~~
public class Singleton {
private static Singleton INSTANCE = null;
private Singleton(){}
public static Singleton getInstance(){
if (INSTANCE == null){
synchronized (Singleton.class){
if (INSTANCE == null){
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
~~~
優點:只在第一次調用時加鎖,之后直接返回對象實例。**延遲加載、線程安全、效率較高**
* **靜態內部類【推薦使用】**
~~~
public class Singleton{
private Singleton(){}
private static class SingleObject{
private static Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingleObject.INSTANCE;
}
}
~~~
優點:線程安全、延遲加載、效率較高。
(靜態內部類在第一次調用時進行加載,實現了延時加載;INSTANCE是一個靜態變量,JVM在實例化時保證了變量的唯一和線程安全)
* ##### 枚舉【推薦使用】
~~~
public enum Singleton{
INSTANCE;
Singleton(){}
}
~~~
優點:系統內存中只存在一個實例對象,節省了系統資源
缺點:當想要實例化一個對象時,需要記住相應的方法,而不是new XXX(),會給其他開發者造成困擾,特別是在看不到源碼的情況下。
### 1.2 工廠模式
~~~
public abstract class Sender{
abstract void send();
}
public class SMSSender extends Sender{
@Override
public void send() {
System.out.println("This is SMS Sender");
}
}
public class MailSender extends Sender{
@Override
void send() {
System.out.println("This is Email Sender");
}
}
~~~
* ##### 簡單工廠模式
~~~
public class SimpleFactory {
public Sender getSender(String senderType){
switch (senderType){
case "sms":
return new SMSSender();
case "mail":
return new MailSender();
default:
return null;
}
}
public static void main(String[] args) {
Sender sender = new SimpleFactory().getSender("sms");
sender.send();
}
}
~~~
缺點:如果傳遞的字符串錯誤,則不能正確的創建對象
* 靜態工廠方法模式
~~~
public class StaticMethodFactory {
public static Sender getSMSSender(){
return new SMSSender();
}
public static Sender getMailSender(){
return new MailSender();
}
public static void main(String[] args) {
Sender sender = StaticMethodFactory.getMailSender();
sender.send();
}
}
~~~
缺點:如果需要新增一個WXSender,則需要重新對Factory進行增添和補充,違反了閉包原則
* 抽象工廠模式
?在簡單工廠模式和工廠方法模式中,工廠的功能比較單一(只能生產Sender),而在抽象工廠方法中,工廠中可以有多個方法(生產Sender、Provider等)。如
~~~
public interface Provider {
Sender produce();
}
public class MailSenderProvider implements Provider {
@Override
public Sender produce() {
return new MailSender();
}
}
public class SMSSenderProvider implements Provider {
@Override
public Sender produce() {
return new SMSSender();
}
}
public class AbstractFactory {
public static void main(String[] args) {
Provider provider = new SMSSenderProvider();
Sender sender = provider.produce();
sender.send();
}
}
~~~
> 設計模式代碼產出:[http://git.sankuai.com/users/duoshilin/repos/android-practices/browse/java\_design\_patter](http://git.sankuai.com/users/duoshilin/repos/android-practices/browse/java_design_patter "http://git.sankuai.com/users/duoshilin/repos/android-practices/browse/java_design_patter")
>
> 設計模式參考文章:[http://www.runoob.com/design-pattern/abstract-factory-pattern.html](http://www.runoob.com/design-pattern/abstract-factory-pattern.html "http://www.runoob.com/design-pattern/abstract-factory-pattern.html")