1. 程式人生 > 遊戲攻略 >《艾爾登法環》老龍位置與擊殺獎勵介紹 老龍在哪

《艾爾登法環》老龍位置與擊殺獎勵介紹 老龍在哪

設計模式——工廠模式

工廠模式在Java中使用非常廣泛,其主要是為了解決介面選擇的問題,顧名思義,工廠就是生產產品的。使用者只需要告訴工廠我需要什麼產品,工廠就給你什麼產品,使用者不需要關注產品是怎麼生產出來的。以手機這個產品舉例,先看程式碼

簡單工廠模式

//工廠要生產手機,先定義一個介面
public interface Phone {
    //生產手機的方法。
    void make();
}
//如果我們要生產小米手機,建立一個小米手機類
public class MiPhone implements Phone {
    public MiPhone() {
        this.make();
    }
    //實現小米手機的生產方法。
    @Override
    public void make() {
        System.out.println("make xiaomi phone!");
    }
}
//我們還要生產蘋果手機
public class IPhone implements Phone {
    public IPhone() {
        this.make();
    }
    //實現蘋果手機的生產方法。
    @Override
    public void make() {
        System.out.println("make xiaomi phone!");
    }
}
//現在建立一個工廠類,用來生產小米手機和蘋果手機。
public class PhoneFactory {
    public Phone makePhone(String phoneType) {
        //如果使用者要小米手機,就例項化MiPhone
        if(phoneType.equalsIgnoreCas("MiPhone"){
            return new MiPhone();
        }
        //如果用要要蘋果手機就例項化iPhone
         if(phoneType.equalsIgnoreCa("iPhone") {
            return new IPhone();
        }
        return null;
    }
}
//呼叫示例
public class Demo{
    public static void main(){
        //例項化工廠
        PhoneFacory facory=new PhoneFacory();
        //生產小米手機
        phone miphone = facory.makePhone("MiPhone");
        //生產蘋果手機
        phone iphone = facory.makePhone("iPhone");
    } 
}

在C++中,可以使用抽象基類來實現介面

//定義一個抽象基類
class phone {
public:
   virtual void make() = 0;
};
//實現生產小米手機
class MiPhone :public phone {
public:
    MiPhone() {
        make();
    }
    void make() override {
        std::cout << "我是小米手機" << std::endl;
    }
};
//實現生產蘋果手機
class IPhone :public phone {
public:
    IPhone() {
        make();
    }
    void make() override{
        std::cout << "我是蘋果手機" << std::endl;
    }
};
//定義手機工廠類
class PhoneFacory {
public:
    phone * MakePhone(std::string phoneType) {
        if (phoneType._Equal("MiPhone"))
            return new MiPhone();
        if (phoneType._Equal("IPhone"))
            return new IPhone();
        return nullptr;
    }
};
//呼叫示例
int main()
{
    PhoneFacory facory;
    phone* miphone = facory.MakePhone("MiPhone");
    phone* iphone = facory.MakePhone("IPhone");
    //使用智慧指標
    std::shared_ptr<phone> miphone2(facory.MakePhone("MiPhone"))
}

抽象工廠模式

所謂的抽象工廠模式,可以將工廠理解為一個超級工廠,圍繞這個工廠建立其它工廠。前面實現的工廠模式,只能生成手機這一個品類的商品,當我們還想要電腦產品,比如小米筆記本和蘋果筆記本,就可以使用抽象工廠模式,看程式碼。

//因為我們想要生產膝上型電腦。所以按照手機的方法定義一個電腦的產品介面。
public interface Laptop {
    //生產膝上型電腦的方法。
    public void make();
}
//小米膝上型電腦的生產
public class MiLaptop implements Laptop{
    public void make() override {
        std::cout << "我是小米膝上型電腦" << std::endl;
    }
}
//蘋果膝上型電腦
public class MacLaptop implements Laptop{
    public void make() override{
        std::cout << "我是蘋果膝上型電腦" << std::endl;
    }
}
//定義一個抽像工廠來生成手機和電腦兩個品類的商品
public abstract class AbstractFactory{
    //這個工廠生產手機的方法
    public abstract phone makePhone(string phoneType);
    //生產膝上型電腦的方法
    public abstract Laptop makeLaptop(string laptopType);
}
//擴充套件一下之前的手機工廠
public class PhoneFactory extends AbstractFactory {
    @Override
    public Phone makePhone(String phoneType) {
        //如果使用者要小米手機,就例項化MiPhone
        if(phoneType.equalsIgnoreCas("MiPhone"){
            return new MiPhone();
        }
        //如果用要要蘋果手機就例項化iPhone
         if(phoneType.equalsIgnoreCa("iPhone") {
            return new IPhone();
        }
        return null;
    }
    @Override
    public Laptop makeLaptop(string laptopType){
        return null;
    }
}
//實現一個筆記本的工廠
public class LaptopFactory extends AbstractFactory {
    @Override
    public Phone makePhone(String phoneType) {
        
        return null;
    }
    @Override
    public Laptop makeLaptop(string laptopType){
        //如果使用者要小米筆記本,就例項化MiLaptop
        if(phoneType.equalsIgnoreCase("MiLaptop"){
            return new MiLaptop();
        }
        //如果用要要蘋果筆記本就例項化MacLaptop
         if(phoneType.equalsIgnoreCase("MacLaptop") {
            return new MacLaptop();
        }
        return null;
    }
}
//建立一個工廠生成器,來選擇工廠
public class FactoryProducer{
    public static AbstractFactory getFactory(string factoryType){
        if (factoryType.equalsIgnoreCase("phone"))
             return new PhoneFactory();
        if (factoryType.equalsIgnoreCase("laptop"))
            return new LaptopFactory();
        return null;
    }
}

//使用示例
public class Demo{
    public static void main(string[] args){
        //獲取手機工廠
        AbstractFactory phoneFactory = FactoryProducer.getFactory("phone");
        //生產小米手機
        phone miphone = phoneFactory.makePhone("MiPhone");
        //生產蘋果手機
        phone iphone = phonefactory.makePhone("iphone");
        //獲取筆記本工廠
        AbstractFactory laptopFactory = FactoryProducer.getFactory("laptop");
        //獲取小米筆記本
        Laptop miLaptop = laptopFactory.makeLaptop("MiLaptop");
        //獲取蘋果筆記本
        Laptop macLaptop = laptopFactory.makeLaptop("MacLaptop");
    }
}

c++中的實現類似

//定義一個筆記本介面
class Laptop{
public:
    virtual void make() = 0;
}
//定義小米筆記本的實現
class MiLaptop :public Laptop
{
public:
    MiLaptop(){
        make();
    }
    void make() override {
        std::cout << "我是小米筆記本" << std::endl;
    }
}
//蘋果筆記本的實現
class MacLaptop :public Laptop
{
public:
    MacLaptop(){
        make();
    }
    void make() override {
        std::cout << "我是蘋果筆記本" << std::endl;
    }
}
//定義抽象工廠
class AbstractFactory
{
public:
   virtual phone * makePhone(std::string phoneType) =0;
   virtualLaptop * makeLaptop(std::string laptopType)=0;
}
//擴充套件前面的手機工廠
class phoneFactory:public AbstractFactory
{
public:
    phone * makePhone(std::strig phoneType) override{
        if (phoneType._Equal("MiPhone"))
            return new MiPhone();
        if (phoneType._Equal("IPhone"))
            return new IPhone();
        return nullptr;
    }
private:
    Laptop * makeLaptop(std::string laptopType){
        return nullptr;
    }
}
//實現膝上型電腦工廠
class LaptorFactory:public AbstractFactory
{
private:
    phone * makePhone(std::strig phoneType) override{
        
        return nullptr;
    }
public:
    Laptop * makeLaptop(std::string laptopType){
        if (phoneType._Equal("MiLaptop"))
            return new MiLaptop();
        if (phoneType._Equal("MacLaptop"))
            return new MacLaptop();
        return nullptr;
    }  
}
//建立一個工廠生成器,來選擇工廠
class FactoryProducer{
public: 
static AbstractFactory* getFactory(string factoryType){
        if (factoryType._Equal("phone"))
             return new PhoneFactory();
        if (factoryType._Equal("laptop"))
            return new LaptopFactory();
        return null;
    }
}
//呼叫示例
int main(){
    //獲取手機工廠
    AbstractFactory * phoneFactory = FactoryProducer::getFactory("phone");
    //獲取小米手機
    phone * miphone = phoneFactory->makePhone("MiPhone");
    phone * iphone = phoneFactory->makePhone("IPhone");
    //獲取筆記本工廠
    AbstractFactory * laptopFactory = FactoryProducer::getFactory("Laptop");
    //獲取小米筆記本
    Laptop * miLaptop = laptopFactory->makeLaptop("MiLaptop");
    //獲取蘋果筆記本
    Laptop * MacLaptop = laptopFactory->makeLaptop("MacLaptop");
}

例子很簡單,只實現了一個介面,展示了工廠模式的實現和原理,可能體現不出工廠模式的作用,工廠模式究竟有什麼用,在什麼情況下用,這裡的一篇博文我覺得寫的非常好。https://www.cnblogs.com/wangenxian/p/10787785.html
以下為這篇部落格的全文。
工廠模式的實現方式和原理都不難理解和掌握。但是,在學習完之後,發現網上給的例子,根本體現不了工廠模式的作用。先不說存在有的例子本身就是錯誤的,主要是例子中的程式碼太簡單,可以說沒必要用工廠模式,只不過是為了說明實現方式和原理。所以,會產生一種錯覺:還不如直接new 一個物件來的方便,有效。

的確,設計模式本身就有其適用的場景,並不是濫用的,否則還不如不用。

現在,我記錄一下在翻閱一些資料後,自己的理解。

首先,工廠模式是為了解耦:把物件的建立和使用的過程分開。就是Class A 想呼叫 Class B ,那麼A只是呼叫B的方法,而至於B的例項化,就交給工廠類。

其次,工廠模式可以降低程式碼重複。如果建立物件B的過程都很複雜,需要一定的程式碼量,而且很多地方都要用到,那麼就會有很多的重複程式碼。我們可以這些建立物件B的程式碼放到工廠裡統一管理。既減少了重複程式碼,也方便以後對B的建立過程的修改維護。(當然,我個人覺得也可以把這些建立過程的程式碼放到類的建構函式裡,同樣可以降低重複率,而且建構函式本身的作用也是初始化物件。不過,這樣也會導致建構函式過於複雜,做的事太多,不符合java 的設計原則。)

由於建立過程都由工廠統一管理,所以發生業務邏輯變化,不需要找到所有需要建立B的地方去逐個修正,只需要在工廠裡修改即可,降低維護成本。同理,想把所有呼叫B的地方改成B的子類B1,只需要在對應生產B的工廠中或者工廠的方法中修改其生產的物件為B1即可,而不需要找到所有的new B()改為new B1()。

另外,因為工廠管理了物件的建立邏輯,使用者並不需要知道具體的建立過程,只管使用即可,減少了使用者因為建立邏輯導致的錯誤。

舉個例子:

一個數據庫工廠:可以返回一個數據庫例項,可以是mysql,oracle等。

這個工廠就可以把資料庫連線需要的使用者名稱,地址,密碼等封裝好,直接返回對應的資料庫物件就好。不需要呼叫者自己初始化,減少了寫錯密碼等等這些錯誤。呼叫者只負責使用,不需要管怎麼去建立、初始化物件。

還有,如果一個類有多個構造方法(構造的重寫),我們也可以將它抽出來,放到工廠中,一個構造方法對應一個工廠方法並命名一個友好的名字,這樣我們就不再只是根據引數的不同來判斷,而是可以根據工廠的方法名來直觀判斷將要建立的物件的特點。這對於使用者來說,體驗比較好。

工廠模式適用的一些場景(不僅限於以下場景):

  1. 物件的建立過程/例項化準備工作很複雜,需要初始化很多引數、查詢資料庫等。

2.類本身有好多子類,這些類的建立過程在業務中容易發生改變,或者對類的呼叫容易發生改變。