設計模式4--工廠模式 (Executors 執行緒池用到)
工廠模式
主要是為建立物件提供過渡介面,以便將建立物件的具體過程遮蔽隔離起來,達到提高靈活性的目的。
工廠方法模式:
一個抽象產品類,可以派生出多個具體產品類。
一個抽象工廠類,可以派生出多個具體工廠類。
每個具體工廠類只能建立一個具體產品類的例項。
抽象工廠模式:
多個抽象產品類,每個抽象產品類可以派生出多個具體產品類。
一個抽象工廠類,可以派生出多個具體工廠類。
每個具體工廠類可以建立多個具體產品類的例項。
區別:
工廠方法模式只有一個抽象產品類,而抽象工廠模式有多個。
工廠方法模式的具體工廠類只能建立一個具體產品類的例項,而抽象工廠模式可以建立多個。
1 普通建立物件:
public class BMW320 { public BMW320(){ System.out.println("製造-->BMW320"); } } public class BMW523 { public BMW523(){ System.out.println("製造-->BMW523"); } } public class Customer { public static void main(String[] args) { BMW320 bmw320 = new BMW320(); BMW523 bmw523 = new BMW523(); } }
2 簡單工廠模式:
產品類:
產品抽象類和具體子類
抽象產品角色:它一般是具體產品繼承的父類或者實現的介面。
具體產品角色:工廠類所建立的物件就是此角色的例項。
package com.duoduo.Factory;
public class BWV {
public BWV() {
}
}
public class BWV888 extends BWV{
public BWV888() {
System.out.println("This is a BWV888 car ~");
}
}
public class BWV520 extends BWV{ public BWV520() { System.out.println("This is a BWV520 car~"); } }
工廠類:
本模式的核心,含有一定的商業邏輯和判斷邏輯,用來建立產品
public class Factory {
public static BWV createCar(int type) {
switch(type) {
case 520:
return new BWV520();
case 888:
return new BWV888();
default:
break;
}
return null;
}
}
客戶類:
public class Customer {
public static void main(String [] args) {
Factory ft=new Factory();
BWV bwv520=ft.createCar(520);
BWV bwv888=ft.createCar(888);
}
}
開閉原則(對擴充套件開放;對修改封閉)
分析簡單工廠模式:
產品部分:符合開閉原則
工廠部分:因為每增加一種新型車,都要在工廠類中增加相應的建立業務邏輯(createBMW(int type)方法需要新增case),這顯然是違背開閉原則的。
可想而知對於新產品的加入,工廠類是很被動的。對於這樣的工廠類,我們稱它為全能類或者上帝類。
3 工廠方法模式:
工廠方法模式
去掉了簡單工廠模式中工廠方法的靜態屬性,使得它可以被子類繼承。
這樣在簡單工廠模式裡集中在工廠方法上的壓力可以由工廠方法模式裡不同的工廠子類來分擔。
工廠方法模式組成:
1)抽象工廠角色: 工廠方法模式核心,與應用程式無關。是具體工廠角色必須實現的介面/繼承的父類。在java中它由抽象類或者介面來實現。
2)具體工廠角色:它含有和具體業務邏輯有關的程式碼。由應用程式呼叫以建立對應的具體產品的物件。
3)抽象產品角色:它是具體產品繼承的父類或者是實現的介面。在java中一般有抽象類或者介面來實現。
4)具體產品角色:具體工廠角色所建立的物件就是此角色的例項。在java中由具體的類來實現。
工廠方法模式使用繼承自抽象工廠角色的多個子類來代替簡單工廠模式中的“上帝類”。
優點: 分擔了物件承受的壓力,使得結構變得靈活 起來
eg. 當有新的產品產生時,只要按照抽象產品角色、抽象工廠角色提供的合同來生成,那麼就可以被客戶使用,而不必去修改任何已有 的程式碼.
抽象工廠:
package com.duoduo.Factory;
public interface FactoryBWV {
BWV createBWV();
}
具體工廠類:
public class FactoryBWV520 implements FactoryBWV{
@Override
public BWV520 createBWV() {
return new BWV520();
// TODO Auto-generated method stub
}
}
public class FactoryBWV888 implements FactoryBWV {
@Override
public BWV888 createBWV() {
return new BWV888();
}
}
產品類(抽象/具體):
public class BWV {
public BWV() {
}
}
public class BWV888 extends BWV{
public BWV888() {
System.out.println("This is a BWV888 car ~");
}
}
public class BWV520 extends BWV{
public BWV520() {
System.out.println("This is a BWV520 car~");
}
}
客戶類:
public class Customer {
public static void main(String [] args) {
FactoryBWV520 f1=new FactoryBWV520();
BWV520 b1=f1.createBWV();
FactoryBWV888 f2=new FactoryBWV888();
BWV888 b2=f2.createBWV();
// Factory ft=new Factory();
// BWV bwv520=ft.createCar(520);
// BWV bwv888=ft.createCar(888);
}
}
分析:
當產品種類非常多時,會出現大量的與之對應的工廠物件,這不是我們所希望的。
4 抽象工廠模式:
需求改變:
隨著客戶的要求越來越高,寶馬車需要不同配置的空調和發動機等配件。於是這個工廠開始生產空調和發動機,用來組裝汽車。這時候工廠有兩個系列的產品:空調和發動機。寶馬320系列配置A型號空調和A型號發動機,寶馬230系列配置B型號空調和B型號發動機。
解決方法:
抽象工廠模式是工廠方法模式的升級版本,他用來建立一組相關或者相互依賴的物件。比如寶馬320系列使用空調型號A和發動機型號A,而寶馬230系列使用空調型號B和發動機型號B,那麼使用抽象工廠模式,在為320系列生產相關配件時,就無需制定配件的型號,它會自動根據車型生產對應的配件型號A。
注意:
每一個具體工廠角色只負責某一個產品角色的例項化。每一個具體工廠類只負責建立抽象產品的某一個具體子類的例項。
產品類:(抽象/具體子類):
//發動機以及型號
public interface Engine {
}
public class EngineA implements Engine{
public EngineA(){
System.out.println("製造-->EngineA");
}
}
public class EngineB implements Engine{
public EngineB(){
System.out.println("製造-->EngineB");
}
}
//空調以及型號
public interface Aircondition {
}
public class AirconditionA implements Aircondition{
public AirconditionA(){
System.out.println("製造-->AirconditionA");
}
}
public class AirconditionB implements Aircondition{
public AirconditionB(){
System.out.println("製造-->AirconditionB");
}
}
工廠類:
//建立工廠的介面
public interface AbstractFactory {
//製造發動機
public Engine createEngine();
//製造空調
public Aircondition createAircondition();
}
//為寶馬320系列生產配件
public class FactoryBMW320 implements AbstractFactory{
@Override
public Engine createEngine() {
return new EngineA();
}
@Override
public Aircondition createAircondition() {
return new AirconditionA();
}
}
//寶馬523系列
public class FactoryBMW523 implements AbstractFactory {
@Override
public Engine createEngine() {
return new EngineB();
}
@Override
public Aircondition createAircondition() {
return new AirconditionB();
}
}
客戶類:
public class Customer {
public static void main(String[] args){
//生產寶馬320系列配件
FactoryBMW320 factoryBMW320 = new FactoryBMW320();
factoryBMW320.createEngine();
factoryBMW320.createAircondition();
//生產寶馬523系列配件
FactoryBMW523 factoryBMW523 = new FactoryBMW523();
factoryBMW320.createEngine();
factoryBMW320.createAircondition();
}
}
總結:
無論是簡單工廠模式,工廠方法模式,還是抽象工廠模式,他們都屬於工廠模式,在形式和特點上也是極為相似的,他們的最終目的都是為了解耦。在使用時,我們不必去在意這個模式到底工廠方法模式還是抽象工廠模式,因為他們之間的演變常常是令人琢磨不透的。經常你會發現,明明使用的工廠方法模式,當新需求來臨,稍加修改,加入了一個新方法後,由於類中的產品構成了不同等級結構中的產品族,它就變成抽象工廠模式了;而對於抽象工廠模式,當減少一個方法使的提供的產品不再構成產品族之後,它就演變成了工廠方法模式。