Design pattern-factory pattern (simple factory, factory method, abstract factory)

table of Contents

1. Simple factory model

1.1 Use the traditional way to complete

1.2 Advantages and disadvantages of traditional methods

2. Simple factory

2.1 Basic introduction of simple factory

2.2 Use the simple factory pattern

Three, the factory method model

3.1 Introduction to Factory Method Pattern

3.2 Application case of factory method pattern

Fourth, the abstract factory model

4.1 Basic introduction to abstract factory

4.2 Application examples of abstract factory pattern

V. Source code analysis of factory mode in JDK-Calendar application

6. Summary of factory model


1. Simple factory model

Look at a pizza project: to facilitate the expansion of pizza types, and to facilitate maintenance

  1. There are many types of pizza (such as GreekPizz, CheesePizz, etc.)
  2. There are prepare, bake, cut, box for making pizza
  3. Complete the pizzeria ordering function.

1.1 Use the traditional way to complete

Idea analysis (class diagram)

Write OrderPizza.java to order all kinds of Pizzas, the traditional way code is as follows:

public class OrderPizza {
    // 构造器
	public OrderPizza() {
	    Pizza pizza = null;
	    String orderType; //  订购披萨的类型
	    do {
	        orderType = getType();
	        
	        if (orderType.equals("greek")) {
                pizza = new GreekPizza();
                pizza.setName(" 希腊披萨 ");
            } else if (orderType.equals("cheese")) {
                pizza = new CheesePizza();
                pizza.setName(" 奶酪披萨 ");
            } else if (orderType.equals("pepper")) {
                pizza = new PepperPizza();
                pizza.setName("胡椒披萨");
            } else {
                break;
            }
            //输出 pizza 制作过程
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
	    } while (true);
	}

	public String getType() {
	    return "";
    }
}

abstract class Pizza{
    public void setName(String name){}
    public void prepare(){}
    public void bake() {}
    public void cut() {}
    public void box() {}
}

class GreekPizza extends Pizza{

}

class CheesePizza extends Pizza {

}

class PepperPizza extends Pizza {

}

1.2 Advantages and disadvantages of traditional methods

  1. The advantage is that it is easier to understand and easy to operate.
  2. The disadvantage is that it violates the ocp  principle of the design pattern  , that is, it is open to extension and closed to modification. That is, when we add new functions to the class, try not to modify the code, or modify the code as little as possible.
  3. For example, if we want to add a new  type of Pizza (Pepper  Pizza ) at this time , we need to make the following modifications. If we add a Pizza class, as long as the code for ordering Pizza needs to be modified. 

Improved thinking analysis

  • Analysis : Modification of the code is acceptable, but if we also have the code for creating Pizza in other places, it means that we also need to modify, and  there are often multiple codes for creating Pizza .
  • Idea : Encapsulate the created  Pizza  object into a class, so that when we have a new type of  Pizza  , we only need to modify the class, and other  codes created to the Pizza object do not need to be modified -> Simple Factory Mode

2. Simple factory

2.1 Basic introduction of simple factory

  1. The simple factory model belongs to the creation model and is a kind of factory model. The simple factory pattern is that a factory object determines which instance of a product class is created. Simple factory mode is the simplest and most practical mode in the factory mode family
  2. Simple factory pattern: defines a class for creating objects, and this class encapsulates the behavior of instantiated objects (code)
  3. In software development, when we will use a large number of objects to create a certain type, a certain type or a certain batch of objects, the factory pattern will be used

2.2 Use the simple factory pattern

The design scheme of the simple factory pattern: Define a class that can instantiate the Pizaa object and encapsulate the code for creating the object.

Sample code:

// 简单工厂类
public class SimpleFactory {
    // 简单工厂模式 也叫 静态工厂模式
    public static Pizza createPizza(String orderType) {
        Pizza pizza = null;

        System.out.println("使用简单工厂模式");
        if (orderType.equals("greek")) {
            pizza = new GreekPizza();
            pizza.setName(" 希腊披萨 ");
        } else if (orderType.equals("cheese")) {
            pizza = new CheesePizza();
            pizza.setName(" 奶酪披萨 ");
        } else if (orderType.equals("pepper")) {
            pizza = new PepperPizza();
            pizza.setName("胡椒披萨");
        }

        return pizza;
    }
}
public class OrderPizza {
    //定义一个简单工厂对象
    SimpleFactory simpleFactory;
	Pizza pizza = null;

    //构造器
    public OrderPizza(SimpleFactory simpleFactory) {
	    setFactory(simpleFactory);
    }

    public void setFactory(SimpleFactory simpleFactory) {
        String orderType = ""; //用户输入的
        this.simpleFactory = simpleFactory; //设置简单工厂对象
        do {
            orderType = getType();
            pizza = this.simpleFactory.createPizza(orderType);

            //输出 pizza
            if (pizza != null) { //订购成功
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                System.out.println(" 订购披萨失败 ");
                break;
            }
        } while (true);
    }

    // 写一个方法,可以获取客户希望订购的披萨种类
    private String getType() {
        try {
            BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String str = strIn.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace(); return "";
        }
    }
}

Three, the factory method model

  • See a new demand

New demand for the pizza project: when customers order pizza, they can order different flavors of pizza, such as cheese pizza in Beijing, pepper pizza in Beijing, or cheese pizza in London or pepper pizza in London.

 

  • Idea 1

Use the simple factory pattern to create different simple factory classes, such as BJPizzaSimpleFactory, LDPizzaSimpleFactory, etc. From the current case, it is also possible, but considering the scale of the project, and the maintainability and scalability of the software, it is not special it is good

 

  • Idea 2

Use factory method pattern


3.1 Introduction to Factory Method Pattern

  1. Factory method pattern design scheme : Abstract the instantiation function of the pizza project into an abstract method, and implement it in different taste ordering subclasses.
  2. Factory method pattern : defines an abstract method to create an object, and the subclass determines the class to be instantiated. The factory method pattern defers the instantiation of objects to subclasses.

3.2 Application case of factory method pattern

The new demand for the pizza project: when customers order pizza, they can order different flavors of pizza, such as cheese pizza in Beijing, pepper pizza in Beijing, or cheese pizza in London, pepper pizza in London

Idea analysis diagram

Code

public class BJCheesePizza extends Pizza {
    
}
public class BJPepperPizza extends Pizza {

}
public class LDCheesePizza extends Pizza {

}
public class LDPepperPizza extends Pizza {
    
}
public abstract class AbstractOrderPizza {
    //定义一个抽象方法,createPizza ,  让各个工厂子类自己实现
    abstract Pizza createPizza(String orderType);

    // 构造器
    public AbstractOrderPizza() { Pizza pizza = null;
        String orderType; //  订购披萨的类型
        do {
            orderType = getType();
            pizza = createPizza(orderType); //抽象方法,由工厂子类完成
            //输出 pizza 制作过程
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();

        } while (true);
    }


    // 写一个方法,可以获取客户希望订购的披萨种类
    private String getType() {
        try {
            BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String str = strIn.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace(); return "";
        }
    }
}
public class BJOrderPizza extends AbstractOrderPizza {
    @Override
    Pizza createPizza(String orderType) {

        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            pizza = new BJCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new BJPepperPizza();
        }
        return pizza;
    }
}
public class LDOrderPizza extends AbstractOrderPizza {
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null; if(orderType.equals("cheese")) {
            pizza = new LDCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
}

Fourth, the abstract factory model

4.1 Basic introduction to abstract factory

  1. Abstract factory pattern: defines an  interface  to create a cluster of related or dependent objects without specifying the specific class
  2. The abstract factory pattern can integrate the simple factory pattern and the factory method pattern.
  3. From a design perspective, the abstract factory pattern is an improvement (or called further abstraction) of the simple factory pattern.
  4. The factory is abstracted into two layers, AbsFactory ( abstract factory and concrete factory subclasses. The programmer can use the corresponding factory subclass according to the type of object created. This turns a single simple factory class into a factory cluster, which is more conducive to code maintenance and expansion.

Class Diagram

4.2 Application examples of abstract factory pattern

Use the abstract factory pattern to complete the pizza project.

//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
    //让下面的工厂子类来 具体实现
    public Pizza createPizza(String orderType);
}
//这是工厂子类
public class BJFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        System.out.println("~使用的是抽象工厂模式~");
        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            pizza = new BJCheesePizza();
        } else if (orderType.equals("pepper")){
            pizza = new BJPepperPizza();
        }
        return pizza;
    }
}
public class LDFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        System.out.println("~使用的是抽象工厂模式~");
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new LDCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
}
public class OrderPizza {
    AbsFactory factory;

    // 构造器
    public OrderPizza(AbsFactory factory) {
        setFactory(factory);
    }

    private void setFactory(AbsFactory factory) {
        Pizza pizza = null;
        String orderType = ""; //  用户输入
        this.factory = factory; do {
            orderType = getType();
            // factory  可能是北京的工厂子类,也可能是伦敦的工厂子类
            pizza = factory.createPizza(orderType);
            if (pizza != null) { // 订 购 ok
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                System.out.println("订购失败");
                break;
            }
        } while (true);
    }

    // 写一个方法,可以获取客户希望订购的披萨种类
    private String getType() {
        try {
            BufferedReader strIn = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String str = strIn.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace(); return "";
        }
    }
}

V. Source code analysis of factory mode in JDK-Calendar application

  • In the Calendar class in the JDK, a simple factory pattern is used
  • Source code analysis + Debug source code + description
import java.util.Calendar;

public class Factory {
    public static void main(String[] args) {
        // getInstance 是 Calendar 静态方法
        Calendar cal = Calendar.getInstance();
        // 注意月份下标从 0 开始,所以取月份要+1
        System.out.println("年:" + cal.get(Calendar.YEAR));
        System.out.println(" 月 :" + (cal.get(Calendar.MONTH) + 1)); 
        System.out.println("日:" + cal.get(Calendar.DAY_OF_MONTH));
        System.out.println("时:" + cal.get(Calendar.HOUR_OF_DAY));
        System.out.println("分:" + cal.get(Calendar.MINUTE));
        System.out.println("秒:" + cal.get(Calendar.SECOND));
    }
}

In Calendar.java:

    public static Calendar getInstance()
    {
        return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
    }
    private static Calendar createCalendar(TimeZone zone,
                                           Locale aLocale)
    {
        CalendarProvider provider =
            LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                 .getCalendarProvider();
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
            }
        }

        Calendar cal = null;

        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                switch (caltype) {
                case "buddhist":
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case "japanese":
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case "gregory":
                    cal = new GregorianCalendar(zone, aLocale);
                    break;
                }
            }
        }
        if (cal == null) {
            // If no known calendar type is explicitly specified,
            // perform the traditional way to create a Calendar:
            // create a BuddhistCalendar for th_TH locale,
            // a JapaneseImperialCalendar for ja_JP_JP locale, or
            // a GregorianCalendar for any other locales.
            // NOTE: The language, country and variant strings are interned.
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }

6. Summary of factory model

  1. The meaning of the factory pattern:  extract the code of the instantiated object, put it into a class for unified management and maintenance, and achieve the decoupling of the dependency relationship with the main project. Thereby improving the expansion and maintenance of the project.
  2. Three factory patterns (simple factory pattern, factory method pattern, abstract factory pattern)
  3. Dependence on abstract principles of design patterns

Recommendations:

  • When creating an object instance, don't directly new class, but put the action of this new class in a factory method and return. Some books say that variables should not directly hold references to specific classes.
  • Don't let the class inherit the concrete class, but inherit the abstract class or implement interface (interface)
  • Don't overwrite methods already implemented in the base class.

 


At the end of the article, I recommend some popular technical blog links :

  1. JAVA related deep technical blog link
  2. Flink related technical blog links
  3. Spark core technology link
  4. Design Pattern-Deepin Technology Blog Link
  5. Machine learning-deep technology blog link
  6. Hadoop related technical blog links
  7. Super dry goods-Flink mind map, it took about 3 weeks to compile and proofread
  8. Deepen the core principles of JAVA JVM to solve various online faults [with case]
  9. Please talk about your understanding of volatile? --A recent "hardcore contest" between Xiao Lizi and the interviewer
  10. Talk about RPC communication, an interview question that is often asked. Source code + notes, package understanding
  11. In-depth talk about Java garbage collection mechanism [with schematic diagram and tuning method]

Welcome to scan the QR code below or search the public account "Big Data Senior Architect", we will push more and timely information to you, welcome to communicate!

                                           

       

 

Guess you like

Origin blog.csdn.net/weixin_32265569/article/details/108314331