Today we will take a look at another abstract factory pattern that is used very frequently. After reading the principles, we will give the implementation source codes of .NET and JAVA.
definition:
Abstract Factory Pattern: Provides an interface for creating a series of related or interdependent objects without specifying their specific classes.
Abstract Factory Pattern: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
Also known as Tool (Kit) mode
The concrete factory in the abstract factory pattern does not just create a product, it is responsible for creating a family of products
When a factory hierarchy can create all objects in a product family belonging to different product hierarchies , the abstract factory pattern is simpler and more efficient than the factory method pattern
analyze:
Each specific factory has only one or a set of overloaded factory methods , and can only produce one product , which may lead to a large number of factory classes in the system, which will inevitably increase the overhead of the system
A factory can produce a series of products (a family of products) , greatly reducing the number of factory classes
Product hierarchy structure: The product hierarchy structure is the inheritance structure of the product
Product family: A product family refers to a group of products produced by the same factory and located in different product hierarchy structures
Class Diagram:
The abstract factory pattern contains the following 4 roles:
AbstractFactory (abstract factory)
ConcreteFactory (concrete factory)
AbstractProduct (abstract product)
ConcreteProduct (specific product)
applicability:
A system should not depend on the details of how product class instances are created, composed and represented
There is more than one product family in the system, but only one of them is used at a time
Products belonging to the same product family will be used together , this constraint must be reflected in the design of the system
The product level structure is stable . After the design is completed, no new product level structure will be added to the system or the existing product level structure will not be deleted.
advantage:
Isolates the generation of concrete classes so that clients don't need to know what is being created
When multiple objects in a product family are designed to work together, it ensures that clients always use only objects from the same product family
It is very convenient to add a new product family without modifying the existing system, which conforms to the principle of opening and closing
shortcoming:
It is troublesome to add a new product level structure , and requires major modifications to the original system, and even the code of the abstraction layer, which will obviously bring great inconvenience and violate the principle of opening and closing
@Add product family
For adding a new product family , the abstract factory pattern supports the principle of opening and closing very well . It only needs to add a specific product and a new specific factory correspondingly, without any modification to the existing code
@Add new product level structure
For adding a new product hierarchy structure , all factory roles need to be modified, including abstract factory classes. In all factory classes, methods for producing new products need to be added, which violates the principle of opening and closing
Case 1: (.NET code)
The code listing includes:
Program.cs
using System;
using System.Configuration;
using System.Reflection;
namespace AbstractFactorySample
{
class Program
{
static void Main(string[] args)
{
//使用抽象层定义
SkinFactory factory;
Button bt;
TextField tf;
ComboBox cb;
//读取配置文件
string factoryType = ConfigurationManager.AppSettings["factory"];
//反射生成对象
factory = (SkinFactory)Assembly.Load("AbstractFactorySample").CreateInstance(factoryType);
bt = factory.CreateButton();
tf = factory.CreateTextField();
cb = factory.CreateComboBox();
bt.Display();
tf.Display();
cb.Display();
Console.Read();
}
}
}
Button.cs
namespace AbstractFactorySample
{
interface Button
{
void Display();
}
}
SpringButton.cs
using System;
namespace AbstractFactorySample
{
class SpringButton : Button
{
public void Display()
{
Console.WriteLine("显示浅绿色按钮。");
}
}
}
SummerButton.cs
using System;
namespace AbstractFactorySample
{
class SummerButton : Button
{
public void Display()
{
Console.WriteLine("显示浅蓝色按钮。");
}
}
}
TextField.cs
namespace AbstractFactorySample
{
interface TextField
{
void Display();
}
}
SpringTextField.cs
using System;
namespace AbstractFactorySample
{
class SpringTextField : TextField
{
public void Display()
{
Console.WriteLine("显示绿色边框文本框。");
}
}
}
SummerTextField.cs
using System;
namespace AbstractFactorySample
{
class SummerTextField : TextField
{
public void Display()
{
Console.WriteLine("显示蓝色边框文本框。");
}
}
}
ComboBox.cs
namespace AbstractFactorySample
{
interface ComboBox
{
void Display();
}
}
SpringComboBox.cs
using System;
namespace AbstractFactorySample
{
class SpringComboBox : ComboBox
{
public void Display()
{
Console.WriteLine("显示绿色边框组合框。");
}
}
}
SummerComboBox.cs
using System;
namespace AbstractFactorySample
{
class SummerComboBox : ComboBox
{
public void Display()
{
Console.WriteLine("显示蓝色边框组合框。");
}
}
}
SkinFactory.cs
namespace AbstractFactorySample
{
interface SkinFactory
{
Button CreateButton();
TextField CreateTextField();
ComboBox CreateComboBox();
}
}
SpringSkinFactory.cs
namespace AbstractFactorySample
{
class SpringSkinFactory : SkinFactory
{
public Button CreateButton()
{
return new SpringButton();
}
public TextField CreateTextField()
{
return new SpringTextField();
}
public ComboBox CreateComboBox()
{
return new SpringComboBox();
}
}
}
SummerSkinFactory.cs
namespace AbstractFactorySample
{
class SummerSkinFactory : SkinFactory
{
public Button CreateButton()
{
return new SummerButton();
}
public TextField CreateTextField()
{
return new SummerTextField();
}
public ComboBox CreateComboBox()
{
return new SummerComboBox();
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="factory" value="AbstractFactorySample.SpringSkinFactory"/>
</appSettings>
</configuration>
Case 2: (JAVA code)
AbstractFactory
public interface IAnimalFactory {
ICat createCat();
IDog createDog();
}
ConcreteFactory
public class BlackAnimalFactory implements IAnimalFactory {
public ICat createCat() {
return new BlackCat();
}
public IDog createDog() {
return new BlackDog();
}
}
public class WhiteAnimalFactory implements IAnimalFactory {
public ICat createCat() {
return new WhiteCat();
}
public IDog createDog() {
return new WhiteDog();
}
}
AbstractProduct
public interface ICat {
void eat();
}
public interface IDog {
void eat();
}
ConcreteProduct
public class BlackCat implements ICat {
public void eat() {
System.out.println("The black cat is eating!");
}
}
public class WhiteCat implements ICat {
public void eat() {
System.out.println("The white cat is eating!");
}
}
public class BlackDog implements IDog {
public void eat() {
System.out.println("The black dog is eating");
}
}
public class WhiteDog implements IDog {
public void eat() {
System.out.println("The white dog is eating!");
}
}
Test
public static void main(String[] args) {
IAnimalFactory blackAnimalFactory = new BlackAnimalFactory();
ICat blackCat = blackAnimalFactory.createCat();
blackCat.eat();
IDog blackDog = blackAnimalFactory.createDog();
blackDog.eat();
IAnimalFactory whiteAnimalF*ctory = new WhiteAnimalFactory();
ICat whiteCat = whiteAnimalFactory.createCat();
whiteCat.eat();
IDog whiteDog = whiteAnimalFactory.createDog();
whiteDog.eat();
}
The program runs and returns the result:
The black cat is eating! The black dog is eating! The white cat is eating! The white dog is eating!