编程知识 cdmana.com

3. Factory pattern of Java design pattern

Basic needs :

  • A pizza shop needs to order different kinds of pizzas

The traditional way :

  • Realize the idea

    • In the ordering class, different pizza entity classes are directly created according to different input of users
  • UML Class diagram

  • Code implementation

    • Pizza

      • //  Abstract parent class 
        public abstract class Pizza {
        
           String name;
        
           public abstract void prepare();
        
           public void bake() {
               System.out.println(this.name + " Pizza baking ");
           }
        
           public void cut() {
               System.out.println(this.name + " Pizza cutting ");
           }
        
           public void box() {
               System.out.println(this.name + " The pizza is packed ");
           }
        
        }
        
        //  Cheese pizza   Subclass 1
        public class CheesePizza extends Pizza {
        
           public CheesePizza(String name) {
               this.name = name;
           }
        
           @Override
           public void prepare() {
               System.out.println(this.name + " The pizza is prepared from raw materials ");
           }
        
        }
        //  Greek pizza   Subclass 2
        public class GreekPizza extends Pizza{
        
           public GreekPizza(String name) {
               this.name = name;
           }
        
           @Override
           public void prepare() {
               System.out.println(this.name + " The pizza is prepared from raw materials ");
           }
        
        }
        
    • Ordering

      • public class PizzaStore {
        
           public static void main(String[] args) {
               new PizzaStore().OrderPizza();
           }
        
           //  How to order pizza   The traditional way is to use new The method of subclass is used to return the corresponding pizza 
           public void OrderPizza() {
               Pizza pizza;
               Scanner scanner = new Scanner(System.in);
               String orderType;
               while (true) {
                   System.out.println(" Enter the type of pizza :");
                   orderType = scanner.nextLine();
                   if (StringUtils.equals("cheese", orderType)) {
                       pizza = new CheesePizza("cheese");
                   } else if (StringUtils.equals("greek", orderType)) {
                       pizza = new GreekPizza("greek");
                   } else {
                       System.out.println(" There's no pizza of this type ");
                       break;
                   }
                   pizza.prepare();
                   pizza.bake();
                   pizza.cut();
                   pizza.box();
               }
           }
        
        }
        

Defects and improvements :

  • In the ordering method , Direct adoption new The method of subclass is used to return the corresponding pizza , In violation of the design pattern ocp principle , Open to expansion , Turn off for changes . That is, when we add new functions to the class , Try not to change the code , Or change the code as little as possible
  • If you add a new type of pizza , It needs to be modified OrderPizza Method implementation of , If you have more than one creation Pizza All methods need to be modified
  • Create Pizza Objects are encapsulated in a class , So we have new Pizza When kind , Just modify the class , Others have created Pizza Object code does not need to be modified ——> Simple factory model

Simple factory model :

  • The simple factory pattern is a creation pattern , It's a kind of factory model . The simple factory pattern is an instance of which product class is created by a factory object . The simple factory pattern is the simplest and most practical pattern in the family of factory patterns

  • Simple factory model : Defines a class for creating objects , This class encapsulates the behavior of the instantiated object ( Code )

  • When we're going to use a lot to create a certain 、 When a class or a batch of objects , It will use the factory mode

  • Realize the idea

    • Create a simple factory class SimpleFactory, Provide a create Pizza Methods ,PizzaStore to want to Pizza when , It can be obtained directly from the factory
  • UML Class diagram

  • Code implementation

    • //  Simple factory class  Pizza Class and implementation class are the same as 
      public class SimpleFactory {
      
         //  establish Pizza Methods   It can be called in multiple places , If you need to add other kinds of Pizza You only need to modify the internal implementation of this method , No callers are required 
         public Pizza createPizza(String orderType) {
             Pizza pizza = null;
             if (StringUtils.equals("cheese", orderType)) {
                 pizza = new CheesePizza("cheese");
             } else if (StringUtils.equals("greek", orderType)) {
                 pizza = new GreekPizza("greek");
             } else {
                 System.out.println(" There's no pizza of this type ");
             }
             return pizza;
         }
      
         //  Simple factory is also called static factory   It can directly provide static methods to obtain objects 
         public static Pizza createPizza1(String orderType) {
             Pizza pizza = null;
             if (StringUtils.equals("cheese", orderType)) {
                 pizza = new CheesePizza("cheese");
             } else if (StringUtils.equals("greek", orderType)) {
                 pizza = new GreekPizza("greek");
             } else {
                 System.out.println(" There's no pizza of this type ");
             }
             return pizza;
         }
         
      }
      
    • public class PizzaStore {
      
         public static void main(String[] args) {
             // new PizzaStore().OrderPizza();
             new PizzaStore(new SimpleFactory());
         }
      
         private SimpleFactory simpleFactory;
      
         public PizzaStore(SimpleFactory simpleFactory) {
             this.simpleFactory = simpleFactory;
             OrderPizza();
         }
      
         private void OrderPizza() {
             Pizza pizza;
             Scanner scanner = new Scanner(System.in);
             String orderType;
             while (true) {
                 System.out.println(" Enter the type of pizza :");
                 orderType = scanner.nextLine();
                 //  adopt Pizza The factory gets Pizza object 
                 pizza = simpleFactory.createPizza(orderType);
                 if (null == pizza) {
                     break;
                 }
                 pizza.prepare();
                 pizza.bake();
                 pizza.cut();
                 pizza.box();
             }
         }
      
      }
      

Factory method model :

  • On the basis of the above, new requirements have been added , Need to be in every kind of pizza Plus the place of origin , for example Cheese in Beijing pizza、 Pepper in Beijing pizza Or London cheese pizza、 Pepper in London pizza

  • Ideas 1: You can use the simple factory model , Two new simple factories ,BJPizzaSimpleFactory and LDPizzaSimpleFactory But considering the scale of the project , And software maintainability 、 Scalability is not particularly good

  • Ideas 2: Adopt the factory approach model

    • Abstract the instantiation function of pizza project into abstract method , In the different taste ordering subclass, the specific implementation of
    • Factory method model : Defines an abstract method for creating objects , It's up to the subclass to decide which class to instantiate . The factory method pattern defers the instantiation of objects to subclasses .
  • Realize the idea

    • stay PizzaStore Add a create Pizza Abstract method , from BJPizzaStore and LDPizzaStore To achieve , So far, the two subclasses create Pizza They're all from their own regions
  • UML Class diagram

  • Code implementation

    • //  Abstract classes with abstract methods 
      public abstract class PizzaStore {
      
         public static void main(String[] args) {
             //  Select the factory according to the region ?  What's the benefit of not having a product and creating multiple simple factories 
             String area = "BJ";
             if (area.equals("BJ")) {
                 new BJPizzaStore();
             } else {
                 new LDPizzaStore();
             }
         }
      
         public PizzaStore() {
             OrderPizza();
         }
      
         private void OrderPizza() {
             Pizza pizza;
             Scanner scanner = new Scanner(System.in);
             String orderType;
             while (true) {
                 System.out.println(" Enter the type of pizza :");
                 orderType = scanner.nextLine();
                 //  Use abstract methods to create Pizza, Using different implementation classes will result in different pizzas 
                 pizza = createPizza(orderType);
                 if (null == pizza) {
                     break;
                 }
                 pizza.prepare();
                 pizza.bake();
                 pizza.cut();
                 pizza.box();
             }
         }
      
         //  establish Pizza Abstract method of   Implemented by subclasses 
         public abstract Pizza createPizza(String orderType);
      
      }
      
    • //  Subclass 1
      public class BJPizzaStore extends PizzaStore {
      
         @Override
         public Pizza createPizza(String orderType) {
             Pizza pizza = null;
             if (StringUtils.equals("cheese", orderType)) {
                 pizza = new BJCheesePizza("BJCheese");
             } else if (StringUtils.equals("pepper", orderType)) {
                 pizza = new BJPepperPizza("BJPepper");
             } else {
                 System.out.println(" There's no pizza of this type ");
             }
             return pizza;
         }
      }
      
      //  Subclass 2
      public class LDPizzaStore extends PizzaStore {
      
         @Override
         public Pizza createPizza(String orderType) {
             Pizza pizza = null;
             if (StringUtils.equals("cheese", orderType)) {
                 pizza = new BJCheesePizza("LDCheese");
             } else if (StringUtils.equals("pepper", orderType)) {
                 pizza = new BJPepperPizza("LDPepper");
             } else {
                 System.out.println(" There's no pizza of this type ");
             }
             return pizza;
         }
      }
      

Abstract factory pattern :

  • The abstract factory pattern defines a interface Used to create related or dependent object clusters , Without specifying a specific class , You can integrate the simple factory model with the factory approach pattern

  • From the perspective of design , Abstract factory pattern is the improvement of simple factory pattern ( Or further abstraction ), Abstract the factory into two layers ,

  • Realize the idea

    • establish AbsFactory( Abstract factory ) And the specific implementation of the factory subclass , Create a factory subclass when using
  • UML Class diagram

  • Code implementation

    • //  Abstract factory class 
      public interface AbsFactory {
      
         Pizza createPizza(String orderType);
      
      }
      
      //  Subclass 1
      public class BJFactory implements AbsFactory {
      
         @Override
         public Pizza createPizza(String orderType) {
             Pizza pizza = null;
             if (StringUtils.equals("cheese", orderType)) {
                 pizza = new BJCheesePizza("BJCheese");
             } else if (StringUtils.equals("pepper", orderType)) {
                 pizza = new BJPepperPizza("BJPepper");
             } else {
                 System.out.println(" There's no pizza of this type ");
             }
             return pizza;
         }
      
      }
      
      //  Subclass 2
      public class LDFactory implements AbsFactory {
      
         @Override
         public Pizza createPizza(String orderType) {
             Pizza pizza = null;
             if (StringUtils.equals("cheese", orderType)) {
                 pizza = new BJCheesePizza("LDCheese");
             } else if (StringUtils.equals("pepper", orderType)) {
                 pizza = new BJPepperPizza("LDPepper");
             } else {
                 System.out.println(" There's no pizza of this type ");
             }
             return pizza;
         }
      
      }
      
    • public class PizzaStore {
      
         public static void main(String[] args) {
             new PizzaStore(new BJFactory());
         }
      
         private AbsFactory factory;
      
         public PizzaStore(AbsFactory factory) {
             //  Declare the need for factory class objects here  ,  When you use it, you can directly create the subclass object of the abstract factory 
             this.factory = factory;
             OrderPizza();
         }
      
         private void OrderPizza() {
             Pizza pizza;
             Scanner scanner = new Scanner(System.in);
             String orderType;
             while (true) {
                 System.out.println(" Enter the type of pizza :");
                 orderType = scanner.nextLine();
                 //  Use abstract methods to create Pizza, Using different implementation classes will result in different pizzas 
                 pizza = factory.createPizza(orderType);
                 if (null == pizza) {
                     break;
                 }
                 pizza.prepare();
                 pizza.bake();
                 pizza.cut();
                 pizza.box();
             }
         }
      
      }
      

jdk Source code :

  • stay Calendar Class getInstance() The simple factory pattern is useful in the method

  • public static Calendar getInstance()
       {
       	//  Get the default zone and aLocale
           return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
       }
    
    public static Calendar getInstance(TimeZone zone,
                                          Locale aLocale)
       {
           return createCalendar(zone, aLocale);
       }
    
    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;
       	//  The simple factory pattern is used here to create Calender object   adopt aLocale Different suffixes 
           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;
                   }
               }
           }
       
           ......
               
           return cal;
       }
    

matters needing attention :

  • significance : Extract the code of the instantiated object , Put the same management and maintenance in a class , Achieve the goal of dependency decoupling in the project , Improve the expansibility and maintainability of the project
  • Rely on the abstract principle ( Try to rely on abstract things )
    • When you create an object , Do not use new, It's going to be new Put things in a factory and return to
    • Don't let a class inherit a concrete class , Instead, it inherits abstract classes or implements interfaces , Don't override the base class to summarize the implemented methods

版权声明
本文为[xiaocantian]所创,转载请带上原文链接,感谢

Scroll to Top