Java設計模式之工廠模式的兩種實現方式


工廠模式(Factory Pattern)是 Java 中最常用的設計模式之一。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。

1. 為什么要有工廠模式?

"Talk is cheap,show me the code". 想要找到這個問題的答案,我們先來看看下面這個項目。

1.1  一個實體類

public class User{
    
    public String username;
    public String password;
}

為了更方便講述,我盡量讓代碼精簡,方便我們深入了解想關注的點。

實體類很簡單,User對象,兩個成員變量,username 用戶名稱,password 用戶密碼

1.2 定義了一個IUser接口

也很簡單,只有一個insert方法

import com.xingyun.model.User;

public interface IUser {
    void insert(User user);
}

 1.3 一個實現類IUserMySQLImpl.java

import com.xingyun.model.User;
import com.xingyun.myinterface.IUser; public class IUserMySQLImpl implements IUser{ @Override public void insert(User user) { // TODO Auto-generated method stub System.out.println("insert to MySQL"+user.toString()); } }

這個實現類實現了IUser接口,所以需要實現IUser接口定義的insert(User user)方法.

1.4 最后我們可能需要再多個地方調用

Test1.java

import com.xingyun.model.User;
import com.xingyun.myinterface.IUser;
import com.xingyun.myinterface.impl.IUserMySQLImpl;

public class Test1 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        User user=new User();
        user.username="admin";
        user.password="root";
        
        IUser test=new IUserMySQLImpl();
        test.insert(user);
    }
}

Test2.java

import com.xingyun.model.User;
import com.xingyun.myinterface.IUser;
import com.xingyun.myinterface.impl.IUserMySQLImpl;

public class Test2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        User user=new User();
        user.username="admin";
        user.password="root";
        
        IUser test=new IUserMySQLImpl();
        test.insert(user);
    }

}

我們可以發現Test1.java 和Test2.java 中調用方式都是這樣:

IUser test=new IUserMySQLImpl();

test.insert(user);

 但是假設后來項目中MySQL不想用了,想換Oracle 數據庫了怎么辦?

1.6 我們需要新寫一個實現類 IUserOracleImpl.java

import com.xingyun.model.User;
import com.xingyun.myinterface.IUser;

public class IUserOracleImpl implements IUser{

    @Override
    public void insert(User user) {
        // TODO Auto-generated method stub
        System.out.println("insert to Oracle"+user.toString());
    }

}

1.7 這很正常,但是我們之前有多處調用,所以我們將不得不修改Test1.java 和Test2.java,

Test1.java

import com.xingyun.model.User;
import com.xingyun.myinterface.IUser;
import com.xingyun.myinterface.impl.IUserOracleImpl;

public class Test1 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        User user=new User();
        user.username="admin";
        user.password="root";
        
        IUser test=new IUserOracleImpl();
        test.insert(user);
    }
}

Test2.java

import com.xingyun.model.User;
import com.xingyun.myinterface.IUser;
import com.xingyun.myinterface.impl.IUserOracleImpl;

public class Test2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        User user=new User();
        user.username="admin";
        user.password="root";
        
        IUser test=new IUserOracleImpl();
        test.insert(user);
    }

}

試想下,假如Test1 ,Test 這類的調用方式有十幾處的話,那么這么多地方都要改,我們是不是要累死?

那么如何優化呢?

2. 工廠模式手動實現方式

聰明的大牛做了這樣的優化

2.1 實體類不變

public class User{
    
    public String username;
    public String password;
}

2.2 消息接口不變

import com.xingyun.model.User;

public interface IUser {
    void insert(User user);
}

2.3 一個實現類IUserMySQLImpl.java

import com.xingyun.model.User;
import com.xingyun.myinterface.IUser; public class IUserMySQLImpl implements IUser{ @Override public void insert(User user) { // TODO Auto-generated method stub System.out.println("insert to MySQL"+user.toString()); } }

2.4 實現類 IUserOracleImpl.java 不變

import com.xingyun.model.User;
import com.xingyun.myinterface.IUser;

public class IUserOracleImpl implements IUser{

    @Override
    public void insert(User user) {
        // TODO Auto-generated method stub
        System.out.println("insert to Oracle"+user.toString());
    }

}

2.5 新建了一個這樣的類 IUserFactory.java

import com.xingyun.myinterface.IUser;
import com.xingyun.myinterface.impl.IUserMySQLImpl; public class IUserFactory { public static IUser getIUserImpl() { return new IUserMySQLImpl(); } }

2.6 最開始調用方式改變下

Test1.java

import com.xingyun.factory.IUserFactory;
import com.xingyun.model.User;
import com.xingyun.myinterface.IUser;

public class Test1 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        User user=new User();
        user.username="admin";
        user.password="root";
        
        IUser test=IUserFactory.getIUserImpl(); test.insert(user);
    }
}

Test2.java

import com.xingyun.factory.IUserFactory;
import com.xingyun.model.User;
import com.xingyun.myinterface.IUser;

public class Test2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        User user=new User();
        user.username="admin";
        user.password="root";
        
        IUser test=IUserFactory.getIUserImpl(); test.insert(user);
    }

}

然后將Test1.java和Test2.java 中原來的調用方式

IUser test=new IUserMySQLImpl();
test.insert(user);

改成了這樣:

IUser test=IUserFactory.getIUserImpl();
test.insert(user);

於是乎,我當需要將IUserMySQLImpl更換為IUserOracleImpl 的時候,我們只需要修改這個IUserFactory即可,Test1.java和Test2.java 任何調用的地方都不再需要改變。

import com.xingyun.myinterface.IUser;
import com.xingyun.myinterface.impl.IUserOracleImpl;

public class IUserFactory {

    public static IUser getIUserImpl() {
        return new IUserOracleImpl();
    }
}

你猜的沒錯,這就是Java 設計模式中著名的工廠模式,通過抽象出一個工廠,來屏蔽調用選擇哪一種實現類的,這個問題丟給工廠類來處理切換哪一個實現類。

2. 工廠模式Spring IOC實現方式

Mark:https://www.cnblogs.com/cowboys/p/6638484.html 

待續。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM