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