Factory mode of design mode

Posted by iBuddy Media on Wed, 22 Dec 2021 12:41:37 +0100

Factory mode

First, let's look at the traditional design pattern

Now there is a demand: the production of Xiaomi mobile phones

Mobile interface

//Mobile interface
public interface Phone {
    void make();
}

Xiaomi mobile phone

//Xiaomi mobile phone
public class MiPhone implements Phone {
    public MiPhone() {
        this.make();
    }
    @Override
    public void make() {
        // TODO Auto-generated method stub
        System.out.println("make xiaomi phone!");
    }
}

test

public class Demo {
    public static void main(String[] arg) {
        String phoneType = "MiPhone";
        Phone miPhone = null;
        if(phoneType.equalsIgnoreCase("MiPhone")){
            Phone miPhone = new MiPhone();
        }
    }
}

Above, we can easily realize the requirements through the traditional methods, but now the requirements need to be expanded. For example, we need to add and produce IPhone mobile phones. If the above methods are adopted, the IPhone class must be essential, but the following line of code needs to be added when using.

else if(phoneType.equalsIgnoreCase("iPhone")) {
    return new IPhone();
}

Then we can complete the new requirements. However, if the ordered mobile phone is not only used here, we need to modify the corresponding code in another place where it is used, so it is not easy to expand. Therefore, we think of a way to put the methods of new mobile phone in one class, that is, Factory. Start the following simple Factory mode

1, Simple factory mode

We still use the above requirements to write code

First, we add an IPhone class

IPhone class

//IPhone class
public class IPhone implements Phone {
    public IPhone() {
        this.make();
    }
    @Override
    public void make() {
        // TODO Auto-generated method stub
        System.out.println("make iphone!");
    }
}

Secondly, we unify the operations of the above new mobile phone into one class (Factory)

PhoneFactory class

//PhoneFactory class
public class PhoneFactory {
    public Phone makePhone(String phoneType) {
        if(phoneType.equalsIgnoreCase("MiPhone")){
            return new MiPhone();
        }
        else if(phoneType.equalsIgnoreCase("iPhone")) {
            return new IPhone();
        }
        return null;
    }
}

Finally, in the test class, the new Factory() instance, and then call the method of the production mobile phone of the factory to get the corresponding mobile phone

Test class

public class Demo {
    public static void main(String[] arg) {
        PhoneFactory factory = new PhoneFactory();
        MiPhone miPhone = (MiPhone)factory.makePhone("MiPhone");	// make xiaomi phone!
        IPhone iPhone = (IPhone)factory.makePhone("iPhone");    	// make iphone!
    }
}

In this way, when we need to extend a new mobile phone type in the future, we only need to add a new mobile phone class and modify the Factory class to facilitate expansion.

2, Factory method model

Compared with the simple factory mode in which the factory is responsible for producing all products, the factory method mode distributes the task of generating specific products to specific product factories. That is, an abstract factory is defined, which defines the production interface of products, but is not responsible for specific products. The production tasks are handed over to different derived factories. This eliminates the need to create objects by specifying types.

Next, continue to use the example of producing mobile phones to explain this mode.

The definitions of Phone class, MiPhone class and IPhone class related to the product remain unchanged.

First, we create the abstract factory AbstractFactory interface, which is not specific

AbstractFactory

public interface AbstractFactory {
    Phone makePhone();
}

Then, create the corresponding mobile phone factory implementation interface

XiaoMiFactory

public class XiaoMiFactory implements AbstractFactory{
    @Override
    public Phone makePhone() {
        return new MiPhone();
    }
}

AppleFactory

public class AppleFactory implements AbstractFactory {
    @Override
    public Phone makePhone() {
        return new IPhone();
    }
}

test

public class Demo {
    public static void main(String[] arg) {
        AbstractFactory miFactory = new XiaoMiFactory();
        AbstractFactory appleFactory = new AppleFactory();
        miFactory.makePhone();            // make xiaomi phone!
        appleFactory.makePhone();        // make iphone!
    }
}

In the above, we don't need to specify a specific type in the factory class. We just need to inherit the super factory and create the corresponding mobile phone from the specified subclass.

3, Abstract factory pattern

The above methods can well solve our current needs, but there are still deeper needs. What if we want to produce not only mobile phones, but also computers and so on; In fact, it can also be implemented in the above way, but you need to add another super factory and add the corresponding implementation class, which is obviously not easy to expand. Therefore, we thought of another way. Through a super factory, we can declare a variety of production methods, not only mobile phones but also computers. After specifying the implementation class of the brand factory, we can realize this demand by realizing the corresponding production methods of mobile phones and computers.

First, PC related

public interface PC {
    void make();
}
public class MiPC implements PC {
    public MiPC() {
        this.make();
    }
    @Override
    public void make() {
        // TODO Auto-generated method stub
        System.out.println("make xiaomi PC!");
    }
}
public class MAC implements PC {
    public MAC() {
        this.make();
    }
    @Override
    public void make() {
        // TODO Auto-generated method stub
        System.out.println("make MAC!");
    }
}

Then, modify the super factory

public interface AbstractFactory {
    Phone makePhone();//Production of mobile phones
    PC makePC();//Production PC
}

Secondly, the brand class implements the corresponding interface

public class XiaoMiFactory implements AbstractFactory{
    @Override
    public Phone makePhone() {
        return new MiPhone();
    }
    @Override
    public PC makePC() {
        return new MiPC();
    }
}
public class AppleFactory implements AbstractFactory {
    @Override
    public Phone makePhone() {
        return new IPhone();
    }
    @Override
    public PC makePC() {
        return new MAC();
    }
}

test

public class Demo {
    public static void main(String[] arg) {
        AbstractFactory miFactory = new XiaoMiFactory();
        AbstractFactory appleFactory = new AppleFactory();
        miFactory.makePhone();            // make xiaomi phone!
        miFactory.makePC();                // make xiaomi PC!
        appleFactory.makePhone();        // make iphone!
        appleFactory.makePC();            // make MAC!
    }
}

Topics: Java Scala Eclipse