和單例模式相似,工廠模式同樣聚焦於在考慮整個軟體構建的情況下合理創建對象,從而保證軟體的擴展性和穩定性。 簡單工廠模式:適用客戶端無需擴展的應用場景 //工廠方法模式:適合客戶端創建單個產品的應用場景 //抽象工廠模式:適合創建多個產品(產品固定)的應用場景 ...
什麼是工廠模式?
工廠模式是創建型模式的一種,工廠是用來生產的,而在Java里,是用來生產對象實例的。
和單例模式相似,工廠模式同樣聚焦於在考慮整個軟體構建的情況下合理創建對象,從而保證軟體的擴展性和穩定性。
工廠模式分為三種:
- 簡單工廠模式
- 工廠方法模式
- 抽象工廠模式
簡單工廠模式(實現服務端自擴展)
服務端:提供代碼的人(作者)
客戶端:使用代碼的人(用戶)
【對於程式員來說,自己是作者,用戶是普通人;那麼對於發明語言,框架的人來說,創建者是作者,而普通程式員是用戶】
假設沒有使用簡單工廠模式:
定義一個Coder介面,然後定義JavaCoder和PythonCoder實現Coder介面。客戶端通過new來創建對象。(耦合)
//服務端
interface Coder {
void express();
}
class JavaCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Java Coder");
}
}
class PythonCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Python Coder");
}
}
//===============================================================================
public class ProductManager //客戶端
{
public static void main(String[] args) {
Coder javaCoder = new JavaCoder();
javaCoder.express();
}
}
當服務端需要擴展一個類時:需要進行1,2兩步
//服務端
interface Coder {
void express();
}
class JavaCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Java Coder");
}
}
class PythonCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Python Coder");
}
}
class GoCoder implements Coder //1.服務端擴展
{
@Override
public void express()
{
System.out.println("I am a Go Coder");
}
}
//===============================================================================
public class ProductManager //客戶端
{
public static void main(String[] args) {
Coder javaCoder = new JavaCoder();
javaCoder.express();
Coder goCoder = new GoCoder(); //2.客戶端跟著修改
goCoder.express();
}
}
服務端和客戶端處於高度耦合狀態。(服務端的變化會引起客戶端的變化)
使用簡單工廠模式:(如果服務端要擴展一個GoCoder,客戶端無需做修改)
//服務端
interface Coder {
void express();
}
class JavaCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Java Coder");
}
}
class PythonCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Python Coder");
}
}
class GoCoder implements Coder //1.服務端擴展
{
@Override
public void express()
{
System.out.println("I am a Go Coder");
}
}
class SimpleFactory
{
//使用靜態內部類實現單例模式
private static class StaticClassInnerInstance {
private static final SimpleFactory INSTANCE = new SimpleFactory();
}
public static SimpleFactory getInstance() {
return StaticClassInnerInstance.INSTANCE;
}
public Coder createCoder(String language)
{
Coder coder = null;
if(language.equals("Java"))
{
coder= new JavaCoder();
}
else if(language.equals("Python"))
{
coder= new PythonCoder();
}
else if(language.equals("Go")) //2.擴展條件
{
coder= new GoCoder();
}
return coder;
}
}
//===============================================================================
public class ProductManager //客戶端
{
public static void main(String[] args) {
SimpleFactory factory = SimpleFactory.getInstance();
Coder javaCoder = factory.createCoder("Java");
javaCoder.express();
}
}
簡單工廠UML類圖:
簡單工廠的優缺點:
優點:
解決了服務端與客戶端的耦合問題,實現了服務端的自擴展。
缺點:
當客戶端需要進行功能擴展時,無法在SimpleFactory中添加對應修改代碼。
簡單工廠可以完成服務端的自擴展,但客戶端只能調用,無法擴展。
工廠方法模式(實現客戶端自擴展)
//服務端
interface Coder {
void express();
}
class JavaCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Java Coder");
}
}
class PythonCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Python Coder");
}
}
class GoCoder implements Coder //1.服務端擴展
{
@Override
public void express()
{
System.out.println("I am a Go Coder");
}
}
interface CoderFactory //抽象出CoderFactory
{
public Coder createCoder(String language);
}
class ServerFactory implements CoderFactory
{
private static class StaticClassInnerInstance {
private static final ServerFactory INSTANCE = new ServerFactory();
}
public static ServerFactory getInstance() {
return StaticClassInnerInstance.INSTANCE;
}
@Override
public Coder createCoder(String language)
{
Coder coder = null;
if(language.equals("Java"))
{
coder= new JavaCoder();
}
else if(language.equals("Python"))
{
coder= new PythonCoder();
}
else if(language.equals("Go")) //2.擴展條件
{
coder= new GoCoder();
}
return coder;
}
}
//===============================================================================
class RustCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Rust Coder");
}
}
class ClientFactory implements CoderFactory
{
private static class StaticClassInnerInstance1 {
private static final ClientFactory INSTANCE = new ClientFactory();
}
public static ClientFactory getInstance() {
return ClientFactory.StaticClassInnerInstance1.INSTANCE;
}
@Override
public Coder createCoder(String language)
{
return new RustCoder();
}
}
public class ProductManager //客戶端
{
public static void main(String[] args) {
ClientFactory clientFactory = ClientFactory.getInstance();
Coder coder = clientFactory.createCoder("Rust");
coder.express();
}
}
工廠方法UML類圖:
工廠方法模式的優缺點:
優點:實現了客戶端的自擴展。
缺點:無法擴展多個產品。
抽象工廠模式(實現產品簇)
適應多個產品,加入設計師。
抽象工廠中可以生產多個產品,產品之間存在內在聯繫。比如說JavaCoder對應JavaDesigner。
而實例化的工廠就是根據這種內在聯繫來劃分的。
同一個工廠的產品屬於一個產品簇,不同產品簇之間是不能互相組合的。比如說GoDesigner和PythonCoder是不能組合到一個工廠里的。
//服務端
interface Coder {
void express();
}
interface Designer {
void express();
}
class JavaCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Java Coder");
}
}
class PythonCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Python Coder");
}
}
class GoCoder implements Coder
{
@Override
public void express()
{
System.out.println("I am a Go Coder");
}
}
class JavaDesigner implements Designer
{
@Override
public void express()
{
System.out.println("I am a Java Designer!");
}
}
class PythonDesigner implements Designer
{
@Override
public void express()
{
System.out.println("I am a Python Designer!");
}
}
class GoDesigner implements Designer
{
@Override
public void express()
{
System.out.println("I am a Go Designer!");
}
}
interface ProductFactory
{
public Coder createCoder();
public Designer createDesigner();
}
class GoFactory implements ProductFactory
{
private static class StaticClassInnerInstance {
private static final GoFactory INSTANCE = new GoFactory();
}
public static GoFactory getInstance() {
return StaticClassInnerInstance.INSTANCE;
}
@Override
public Coder createCoder()
{
Coder coder= new GoCoder();
return coder;
}
@Override
public Designer createDesigner()
{
Designer designer= new GoDesigner();
return designer;
}
}
class JavaFactory implements ProductFactory
{
private static class StaticClassInnerInstance {
private static final JavaFactory INSTANCE = new JavaFactory();
}
public static JavaFactory getInstance() {
return StaticClassInnerInstance.INSTANCE;
}
@Override
public Coder createCoder()
{
Coder coder= new JavaCoder();
return coder;
}
@Override
public Designer createDesigner()
{
Designer designer= new JavaDesigner();
return designer;
}
}
//===============================================================================
public class ProductManager //客戶端
{
public static void main(String[] args) {
JavaFactory javaFactory = JavaFactory.getInstance();
Coder coder =javaFactory.createCoder();
Designer designer = javaFactory.createDesigner();
coder.express();
designer.express();
}
}
抽象工廠UML類圖:
工廠模式總結
簡單工廠模式:適用客戶端無需擴展的應用場景
工廠方法模式:適合客戶端創建單個產品的應用場景
抽象工廠模式:適合創建多個產品的應用場景(但產品類別需要固定)
-------------------------------------------------------------------------------------------------------------2019.8.11