Java設計模式-單例模式、觀察者模式、工廠模式
單例設計模式
概念:
全域性只有一個例項,自行例項化物件,自行向整個系統提供這個例項。
應用場景:
- 需要全域性只有一個例項的時候,如儲存使用者資訊。
- 只有一個訪問途徑
優點:
- 全域性只有一個例項,避免了頻繁的建立例項,耗費的資源。
- 提供了對唯一例項的受控訪問。
- 允許改變數目的例項。
缺點:
餓漢式
類載入的時候就開始載入,使用的是靜態變數,由JVM的classloader機制避免了執行緒安全問題,保證執行緒安全。
缺點:一開始便載入佔用記憶體,沒有達到懶載入效果,如果例項化是耗費資源的,則懶載入可以節省載入時耗費的資源。另外如果例項一直沒有使用會佔用記憶體。
public class SingleTon{ private static SingleTon single = new SingleTon(); private SingleTon(){} public static SingleTon getInstanceO(){ retrun single; } }
餓漢式的另外方式
與正常的餓漢式並沒有太大的區別。
public class SingleTon{
private SingleTon instance = null;
static{
instance = new SingleTon();
}
private SingleTon(){}
public static SingleTon getInstance(){
return this.instance;
}
}
懶漢式
延遲載入,在呼叫getInstance的時候才開始載入,無須一直佔用系統資源。從資源利用率的角度來講優於餓漢式。
缺點:執行緒不安全,當執行緒A判斷了是空的時候進行建立物件,在建立物件前執行緒B進來判斷到是空,也建立了物件,因此執行緒A和執行緒B的物件不一致。
public class SingleTon {
private static SingleTon single;
private SingleTon(){}
public static SingleTon getInstance(){
if(single == null){
single = new SingleTon();
}
return single;
}
}
//優化---增加鎖機制 1 ,在方法上加
public synchronize SingleTon getInstance(){
if(single == null){
single = new SingleTon();
}
}
//缺點:鎖住了整個類,這個類中的其他成員變數也需要等待釋放鎖後被其他執行緒使用,效率低下。
//優化,雙重鎖校驗,缺點:可能會出現等待時間,降低系統性能。
public static SingleTon getInstance(){
if(single == null){
synchronize(SingleTon.class){
if(single == null){
single = new SingleTon();
}
}
}
return single;
}
靜態內部類
靜態內部類不是在一開始啟動的時候載入,而是第一次呼叫的使用載入,實現了懶載入,並且由JVM的classloader機制實現執行緒同步,保證執行緒安全。
虛擬機器會保證一個類的構造器()方法在多執行緒環境中被正確地載入,同步,如果多個執行緒同時去初始化一個類,那麼只有一個執行緒去執行這個類的.
public class SingleTon{
private SingleTon();
private static class SingleTonHelper{
private static final SingleTon single = new SingleTon();
}
public static SingleTon getInstance(){
retrun SingleTonHelper.single;
}
}
觀察者模式
概念:
實現一對多的依賴關係,當一方改變時,存在依賴關係的多方可以做出更改。
即釋出訂閱關係,釋出者釋出訊息,存在訂閱關係的訂閱者可以接收訊息。
包含的類
- 抽象被觀察者介面:定義被觀察者需要實現的介面,如註冊觀察者建立關係;移除觀察者,通知所有觀察變化。
- 抽象觀察者介面:定義接收到訊息後的更新方法。
- 具體被觀察者:抽象被觀察者實現者,與觀察者建立關係,並通知觀察者的實現方法。
- 具體觀察者:被通知物件,具體實現收到通知後做出更新。
定義被觀察者介面
public Interface IObservable{
void registObserver(IObserver o);
void removeObserver(IObserver o);
void notifyObserver();
}
定義觀察者介面
public Interface IObserver{
void update(Strign message); //傳入的引數時任意想接收的訊息
}
具體被觀察者實現
public class MyObservable impelement IObservable{
private String message ;//需要傳遞的訊息
private List<IObserver> observers ;
public MyObservable(){
observers = new ArrayList<>();
}
@override
public void registObserver(IObserver o){
if(observers!=null){
observers.add(o);
}
}
@override
public void removeObserver(IObserver o){
if(observers!=null && observers.size()>0){
observers.remove(o);
}
}
@override
public void notifyObserver(){
for(int i=0 ;i<observers.size();i++){
observers.get(i).update(message);
}
}
//需要更新的訊息
public void sendMsg(String msg){
this.message = msg;
//通知觀察者
notifyObserver();
}
}
具體觀察者
public class MyObserver impelement IObserver{
@override
public void update(String message){
System.out.println("接收到訊息,開始處理");
}
}
工廠模式
概念:
集中建立產品的類,是呼叫者和具體建立例項類分離開來,實現解偶。
簡單工廠模式
概念與步驟
又叫靜態工廠模式,通過工廠類根據型別建立不同的例項類。
優點:結構簡單,便於理解。客戶不用關心具體的類的建立過程。
缺點:程式碼邏輯較其他工廠模式複雜,新增產品時必須修改工廠類。當需要建立的類比較多時,工廠類會變的較為臃腫。
//需建立的例項類的共同點
public interface Car{
void go();
}
//具體例項
public class Audi{
@override
public void go(){
System.out.println("奧迪在跑");
}
}
public class Baoma{
@override
public void go(){
System.out.println("奧迪在跑");
}
}
//工廠類
public class CarFactory{
public static final int AUDI_TYPR = 1;
public static final int BMW_TYPR = 2;
public static Car createCar(int type){
Car car = null;
switch(type){
case AUDI_TYPR:
car = new Audi();
case BMW_TYPR:
car = new Baoma();
}
return car;
}
}
工廠方法模式
概念與步驟
把工廠類抽象出去,建立例項由具體的工廠類實現,針對每一個產品都由自己的具體工廠類實現。
優點:
呼叫者無需關心產品的實現,只需要關心產品的介面。增加新的產品時,只要介面不變,不需要修改工廠類的邏輯,實現解偶。
缺點:
類比較多,如果需要建立多個產品的時候專案結構會比較大。
//抽象工廠介面
public interface IFactory{
Car createCar();
}
//具體工廠類
public class AudiFactory impelement IFactory{
@Override
public Car createCar(){
return new Audi();
}
}
//抽象產品
public interface Car{
void getName();
}
//具體的產品
public class Audi impelement Car{
@Override
public void getName(){
System.out.println("get an audi");
}
}
//新增產品時新增產品類及產品工廠類
抽象工廠模式
概念與步驟
具有關聯功能的產品作為一個產品族。 步驟:抽象工廠類,定於具體工廠類必須要實現的方法。
具體工廠類,建立一族產品;抽象產品類:定義產品的共性。具體產品類:建立具體的產品。
優點:具有工廠方法模式的優點外,另外可以在類內對產品族進行約束。
缺點:擴充套件比較麻煩。
試用場景:當建立的物件是一系列相互關聯或相互依賴的產品族時適用。
//抽象工廠類
public interface AbstractFactory {
AbstractCar createCar();
AbstractPlane createPlane();
}
//抽象產品類
public abstract class AbstractCar {
public abstract void getName();
}
public abstract class AbstractPlane {
public abstract void getName();
}
//具體工廠類
public class BigFactory implements AbstractFactory{
@Override
public AbstractCar createCar() {
return new BigCar();
}
@Override
public AbstractPlane createPlane() {
return new BigPlane();
}
}
//具體產品類
public class BigCar extends AbstractCar {
@Override
public void getName() {
System.out.print("抽象工廠-大車");
}
}
class BigPlane extends AbstractPlane {
@Override
public void getName() {
System.out.print("抽象工廠-大飛機");
}
}