Design Patterns (15) - Abstract Factory (Abstract Factory)

Scene problems

  For life in common example - computer assembly, we assembled computers, you usually need to select a range of accessories, such as CPU, hard drives, memory, motherboard, power supply, chassis and so on. To discuss the use of a simple point, only consider the choice of CPU and motherboard.

  In fact, the choice of CPU time, face a series of problems, such as make, model, pin number, frequency and other issues, these issues are only finalized in order to determine the specific CPU.

  Similarly, in selecting a motherboard, there are a range of issues, such as brand, chipset, integrated chip, bus frequency and other issues, and only these are identified in order to determine the specific motherboard.

  Choose a different CPU and motherboard, the assembly is required for each client in the computer, the installed capacity of the proposed company, that is, each of us own installation plan drawn up.

  Prior to finalizing this program installed, we also need to consider the overall compatibility between the various parts. For example: CPU and motherboard, if you use Intel CPU and AMD motherboard is impossible to assemble. Because the CPU pin count is not compatible with the Intel CPU socket AMD motherboard provides, that if you use an Intel CPU simply could not AMD's motherboard, so the installed program is holistic, between the various parts inside there is a choice Associated.

  For the installed capacity of engineer, he knew assemble a computer, you need the appropriate accessories, but specifically what kind of accessories used by the customer will have the final say. That engineer is only responsible for assembly installed, and the customer is responsible for selecting the specific accessories required for assembly. Therefore, when the installed capacity of engineers for different customers assemble computers, just according to customer's installed programs, to obtain the corresponding parts, and then assembled to.

Using a simple factory pattern solution

  Consider customer, you need to select their own needs CPU and motherboard, and then tell engineers installed their own choice, then just wait installed engineers assembled computer.

  For engineers installed, just know that the CPU and motherboard interface, without knowing the specific implementation, it is clear that can be used for simple factory pattern or factory method pattern. For simplicity, here we use a simple plant. Customers tell engineers installed their own choice, and then installed engineers to obtain the appropriate instance of an object through the corresponding factory.

  

Source

CPU interface and concrete implementation

public interface Cpu {
    public void calculate();
}
public class IntelCpu implements Cpu {
    /**
     * CPU的针脚数
     */
    private int pins = 0;
    public  IntelCpu(int pins){
        this.pins = pins;
    }
    @Override
    public void calculate() {
        // TODO Auto-generated method stub
        System.out.println("Intel CPU的针脚数:" + pins);
    }

}
public class AmdCpu implements Cpu {
    /**
     * CPU的针脚数
     */
    private int pins = 0;
    public  AmdCpu(int pins){
        this.pins = pins;
    }
    @Override
    public void calculate() {
        // TODO Auto-generated method stub
        System.out.println("AMD CPU的针脚数:" + pins);
    }
}

Motherboard interface embodied

public interface Mainboard {
    public void installCPU();
}
public class IntelMainboard implements Mainboard {
    /**
     * CPU插槽的孔数
     */
    private int cpuHoles = 0;
    /**
     * 构造方法,传入CPU插槽的孔数
     * @param cpuHoles
     */
    public IntelMainboard(int cpuHoles){
        this.cpuHoles = cpuHoles;
    }
    @Override
    public void installCPU() {
        // TODO Auto-generated method stub
        System.out.println("Intel主板的CPU插槽孔数是:" + cpuHoles);
    }

}
public class AmdMainboard implements Mainboard {
    /**
     * CPU插槽的孔数
     */
    private int cpuHoles = 0;
    /**
     * 构造方法,传入CPU插槽的孔数
     * @param cpuHoles
     */
    public AmdMainboard(int cpuHoles){
        this.cpuHoles = cpuHoles;
    }
    @Override
    public void installCPU() {
        // TODO Auto-generated method stub
        System.out.println("AMD主板的CPU插槽孔数是:" + cpuHoles);
    }
}

CPU motherboard factory classes

public class CpuFactory {
    public static Cpu createCpu(int type){
        Cpu cpu = null;
        if(type == 1){
            cpu = new IntelCpu(755);
        }else if(type == 2){
            cpu = new AmdCpu(938);
        }
        return cpu;
    }
}
public class MainboardFactory {
    public static Mainboard createMainboard(int type){
        Mainboard mainboard = null;
        if(type == 1){
            mainboard = new IntelMainboard(755);
        }else if(type == 2){
            mainboard = new AmdMainboard(938);
        }
        return mainboard;
    }
}

Engineers installed and operating results class customer categories as follows:

public class ComputerEngineer {
    /**
     * 定义组装机需要的CPU
     */
    private Cpu cpu = null;
    /**
     * 定义组装机需要的主板
     */
    private Mainboard mainboard = null;
    public void makeComputer(int cpuType , int mainboard){
        /**
         * 组装机器的基本步骤
         */
        //1:首先准备好装机所需要的配件
        prepareHardwares(cpuType, mainboard);
        //2:组装机器
        //3:测试机器
        //4:交付客户
    }
    private void prepareHardwares(int cpuType , int mainboard){
        //这里要去准备CPU和主板的具体实现,为了示例简单,这里只准备这两个
        //可是,装机工程师并不知道如何去创建,怎么办呢?
        
        //直接找相应的工厂获取
        this.cpu = CpuFactory.createCpu(cpuType);
        this.mainboard = MainboardFactory.createMainboard(mainboard);
        
        //测试配件是否好用
        this.cpu.calculate();
        this.mainboard.installCPU();
    }
}

 

public class Client {
    public static void main(String[]args){
        ComputerEngineer cf = new ComputerEngineer();
        cf.makeComputer(1,1);
    }
}

Results are as follows:


  The above realization, although solved by a simple factory method: the installed capacity for engineers only know the CPU and motherboard interface, without knowing the specific implementation problems. But there is a problem is not resolved, that these objects CPU and motherboard objects actually are related, need to match each other. The above implementation, did not maintain this relationship, CPU and motherboard are arbitrarily selected by the customer, which is problematic. Such as when the client calls makeComputer, its argument is (1,2), results are as follows:

observation result will be seen that the above problems. Customers who are on Intel CPU pin count is 755, and the choice of motherboard is AMD, CPU socket on the motherboard is 938, can not assemble, this is no cause to maintain the relationship between the parts. How to solve this problem?  

The introduction of the abstract factory pattern

  Each pattern is a solution for certain problems. Abstract factory pattern and factory method mode the biggest difference is that, for the factory method pattern is a product of the hierarchical structure; and abstract factory pattern you need to face multiple product hierarchy.

  In the abstract factory before studying specific examples, you should understand two important concepts: product family and product level.

  The so-called product family, refer to the product family is in a different hierarchical structure, functions associated with products composed. For example AMD motherboard chipset, a family consisting of the CPU, Intel motherboard chipset, a family consisting of the CPU. The two families are from three product levels: motherboard, chipset, CPU. A hierarchical structure is the same structure as the product composition diagram is as follows:

  Obviously, the number of products contained in each product family, product grade and structure number are equal. Product hierarchical structure and the products in accordance with the product family is divided in different directions, forming a two-dimensional coordinate system. The horizontal axis represents the hierarchical structure of the product, and the vertical axis represents the product family, product family figure there are two, three different products distributed in the hierarchy. As long as a product specify which product family as well as hierarchical structure to which it belongs, we can only determine this product.

  Three different levels given above structure having parallel structures. Therefore, if the factory method pattern, it is bound to use three separate factories hierarchical structure to deal with these three product hierarchy. Due to the similarity of these three products hierarchical structure, it will lead three parallel plant hierarchy. The number of factory hierarchical structure as the number increases, the factory method pattern hierarchical structure of the product given will increase. As shown below:

    So, whether you can use the same factory hierarchical structure to deal with these identical or very similar product grade structure? Of course you can, but that's the beauty of the abstract factory pattern. The same plant hierarchy responsible for creating the product of three different objects in the product hierarchy.

  As can be seen, a plant hierarchy can create all of the objects belonging to a product family of different products in the hierarchy. Apparently, this time the abstract factory pattern than a simple factory pattern, factory method is more efficient. Corresponding to each of a family of products has a concrete factory. And each is responsible for creating a concrete factory belong to the same product family, but belong to different levels of the product structure.

Abstract factory pattern structure

  Abstract factory pattern is to create an object model, which is to further promote the factory method pattern.

  Suppose that a subsystem needs some product objects, and these products in turn belong to more than one product hierarchy. So in order to create the consumption of these products liability and responsibility for these products objects objects separated, can introduce abstract factory pattern. In this case, a party directly involved in consumer products do not need to create work products, and only need to plant a product common interface requests need.

  By using abstract factory model can be processed with the same (or similar) to create an object of the products in question hierarchy in a plurality of product family. As shown below:

  

  Since the same hierarchical structure of these two product family, the use of the same plant family can deal with these two issues to create product family, which is the abstract factory pattern.

  A structural view of the role of the product, it is not difficult given the structure of the plant design role.

  As can be seen, each character has two factories factory methods were responsible for creating product objects belong to different product grade structure.

  

Source

  Preceding example implementation of CPU and CPU interface to achieve the object, the object interface board and motherboard implementation, need not change.

  Create the preceding example CPU simply create plants and motherboard simple plant, it is no longer required.

  New entrants abstract factory class and implementation class:

public interface AbstractFactory {
    /**
     * 创建CPU对象
     * @return CPU对象
     */
    public Cpu createCpu();
    /**
     * 创建主板对象
     * @return 主板对象
     */
    public Mainboard createMainboard();
}
public class IntelFactory implements AbstractFactory {

    @Override
    public Cpu createCpu() {
        // TODO Auto-generated method stub
        return new IntelCpu(755);
    }

    @Override
    public Mainboard createMainboard() {
        // TODO Auto-generated method stub
        return new IntelMainboard(755);
    }

}
public class AmdFactory implements AbstractFactory {

    @Override
    public Cpu createCpu() {
        // TODO Auto-generated method stub
        return new IntelCpu(938);
    }

    @Override
    public Mainboard createMainboard() {
        // TODO Auto-generated method stub
        return new IntelMainboard(938);
    }

}

  Engineers installed in front of the class, compared with the realization, the main changes are: CPU and motherboard incoming selecting parameters from the client is no longer, but directly into the client has chosen a good product object. This prevents the individual to choose the CPU and motherboard compatibility issues arising from the customer to choose is set, is a series.

public class ComputerEngineer {
    /**
     * 定义组装机需要的CPU
     */
    private Cpu cpu = null;
    /**
     * 定义组装机需要的主板
     */
    private Mainboard mainboard = null;
    public void makeComputer(AbstractFactory af){
        /**
         * 组装机器的基本步骤
         */
        //1:首先准备好装机所需要的配件
        prepareHardwares(af);
        //2:组装机器
        //3:测试机器
        //4:交付客户
    }
    private void prepareHardwares(AbstractFactory af){
        //这里要去准备CPU和主板的具体实现,为了示例简单,这里只准备这两个
        //可是,装机工程师并不知道如何去创建,怎么办呢?
        
        //直接找相应的工厂获取
        this.cpu = af.createCpu();
        this.mainboard = af.createMainboard();
        
        //测试配件是否好用
        this.cpu.calculate();
        this.mainboard.installCPU();
    }
}

Client code:

public class Client {
    public static void main(String[]args){
        //创建装机工程师对象
        ComputerEngineer cf = new ComputerEngineer();
        //客户选择并创建需要使用的产品对象
        AbstractFactory af = new IntelFactory();
        //告诉装机工程师自己选择的产品,让装机工程师组装电脑
        cf.makeComputer(af);
    }
}

  Abstract factory function is to create an interface as a series of related objects or interdependent objects. Must be noted that the method in this interface is not any stuffing, but a series of related or interdependent methods. For example in the example above the motherboard and CPU, it is to assemble a computer related objects. Different programs installed capacity, represents a specific PC series.

  

  
  Due to a series of objects defined in the abstract factory is usually related or dependent, these products constitute a target product family, which is the abstract factory defines a product family.

  This brings great flexibility to switch product family, as long as providing different abstract factory to achieve it, that now is a product family as a whole is switched.


Under what circumstances should use the abstract factory pattern

  1. A system should not depend on how the product class instance is created, a combination of details and expression, which are important for all forms of the factory pattern.

  2. The product of this system has more than one product family, and the only system in which a family of consumer products.

  3. belong to the same product family of products are used together, the constraints must be reflected in the design of the system. (Example: Intel motherboard must use Intel CPU, Intel chipset)

  4. The system provides a product class library, all of the products appear in the same interface, so that the client does not depend on the implementation.

The origin of the abstract factory pattern

  Or the origin of the earliest applications of the abstract factory pattern is used to create Windows operating system belong to different building. For example: Command button (Button) and text box (Text) windows are constructed in the UNIX operating system, Windows environment and Windows operating systems Windows environment, both built with different local implementation, their details are different .

  In each operating system, there is a window. Construction of family composition. Here is the composition of Button and Text product family. And each window member constitutes their hierarchical structure is given by an abstract description of the abstract character function, given by the concrete subclasses embodied in different operating systems.

  


  The above products can be found in the class diagram, the hierarchical structure of the two products, respectively, Text and Button hierarchical structure hierarchy. At the same time there are two product family, which is the UNIX and Windows product family product family. UNIX product family consists of UNIX Button and UNIX Text products; and Windows product family consists of Windows Button and Windows Text products.

    The system creates demand for the product target by a hierarchical structure of the project are met, including the role of two specific projects, namely UnixFactory and WindowsFactory. UnixFactory object is responsible for creating the Unix product family of products, and WindowsFactory object is responsible for creating a Windows product family of products. This is the application, the abstract factory pattern abstract factory pattern solutions in the following figure:

  

  Clearly, a system can only run one operating system at the Windows environment, but can not run on different operating systems. Therefore, the system actually consume only belong to the same product family of products.

  In modern applications, the use of the abstract factory pattern has been greatly expanded, and the system no longer requires only a consumer of a product family. Therefore, we can not ignore the original intent previously mentioned.

Abstract factory pattern advantage

  • Separation of interface and implementation

  The client uses the abstract factory to create the required objects, and clients who do not know the specific implementation, the client only oriented programming interface products only. In other words, the client decoupled from specific product implementations.

  • The switching product family easily become

  Because a specific factory implementation represents a family of products, such as the example above, only need to look at the concrete factory switched from Intel to AMD series series.

Shortcoming abstract factory pattern

  • Not easy to expand new products

  If you need to add a new product to the entire product family, then you need to modify the abstract factory, which would lead to a revision of all the factory implementation class.

Published 295 original articles · won praise 37 · views 30000 +

Guess you like

Origin blog.csdn.net/tianshan2010/article/details/104722394