Modo de combinación-modo de combinación transparente, modo de combinación seguro

Modo de combinación

Visión general

Los nodos hoja realizan operaciones relacionadas.

Este árbol puede entenderse como un contenedor grande, que contiene muchos objetos miembros , que pueden ser objetos contenedor u objetos hoja.

Sin embargo, debido a la diferencia de función entre los objetos de contenedor y los objetos de hoja , debemos distinguir entre los objetos de contenedor y los objetos de hoja durante el uso , pero esto traerá problemas innecesarios a los clientes.

Como cliente, siempre quiere poder tratar los objetos contenedores y los objetos hoja de forma coherente .

definición:

También conocido como modo de conjunto parcial, se utiliza para tratar un grupo de objetos similares como un solo objeto.

El modo de combinación combina objetos de acuerdo con una estructura de árbol, que se utiliza para representar los niveles total y parcial.

Este tipo de patrón de diseño es un patrón estructural, que crea una estructura de árbol de grupos de objetos.

 

5.6.2 Estructura

El modo de combinación incluye principalmente tres roles:

  • Nodo raíz abstracto (componente): define los métodos y atributos comunes de los objetos en todos los niveles del sistema y puede predefinir algunos comportamientos y atributos predeterminados.
  • Nodo de rama (compuesto): defina el comportamiento de los nodos de rama, almacene nodos secundarios, combine nodos de rama y nodos de hoja para formar una estructura de árbol.
  • Nodo de hoja (Hoja): Objeto de nodo de hoja, no hay rama debajo de él, es la unidad más pequeña de recorrido a nivel del sistema.

 

5.6.3 Realización de casos

[Ejemplo] Menú de software

Como se muestra en la figura siguiente, cuando visitamos otros sistemas de gestión, a menudo podemos ver menús similares.

Un menú puede contener elementos de menú (un elemento de menú se refiere a un elemento de menú que ya no contiene otro contenido) o puede contener un menú con otros elementos de menú.

Por lo tanto, es apropiado utilizar el modo combinado para describir el menú Nuestro requisito es imprimir los nombres de todos los menús y elementos de menú contenidos en un menú.

Para implementar este caso, primero dibujamos un diagrama de clases:

Código:

Independientemente de si se trata de un menú o de un elemento de menú, debe heredarse de una interfaz unificada . Aquí, vamos a llamar a esta interfaz unificada un componente de menú.



MenuComponent.java

package com.itheima.pattern.combination;

/**
 * @version v1.0
 * @ClassName: MenuComponent
 * @Description: 菜单组件 : 属于抽象根节点
 * @Author: dym
 */
public abstract class MenuComponent {
    //菜单组件的名称
    protected String name;
    //菜单组件的层级
    protected int level;

    //添加子菜单
    public void add(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }

    //移除子菜单
    public void remove(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }

    //获取指定的子菜单
    public MenuComponent getChild(int index) {
        throw new UnsupportedOperationException();
    }

    //获取菜单或者菜单项的名称
    public String getName() {
        return name;
    }

    //打印菜单名称的方法(包含子菜单和字菜单项)
    public abstract void print();
}

MenuItem.java

package com.itheima.pattern.combination;

import com.itheima.principles.demo1.SougouInput;

/**
 * @version v1.0
 * @ClassName: MenuItem
 * @Description: 菜单项类 : 属于叶子节点
 * @Author: dym
 */
public class MenuItem extends MenuComponent {

    public MenuItem(String name,int level) {
        this.name = name;
        this.level = level;
    }

    public void print() {
        //打印菜单项的名称
        for(int i = 0; i < level; i++) {
            System.out.print("--");
        }
        System.out.println(name);
    }
}

Menu.java

package com.itheima.pattern.combination;

import java.util.ArrayList;
import java.util.List;

/**
 * @version v1.0
 * @ClassName: Menu
 * @Description: 菜单类  : 属于树枝节点
 * @Author: dym
 */
public class Menu extends MenuComponent {

    //菜单可以有多个子菜单或者子菜单项
    private List<MenuComponent> menuComponentList = new ArrayList<MenuComponent>();

    //构造方法
    public Menu(String name,int level) {
        this.name = name;
        this.level = level;
    }

    @Override
    public void add(MenuComponent menuComponent) {
        menuComponentList.add(menuComponent);
    }

    @Override
    public void remove(MenuComponent menuComponent) {
        menuComponentList.remove(menuComponent);
    }

    @Override
    public MenuComponent getChild(int index) {
        return menuComponentList.get(index);
    }

    @Override
    public void print() {
        //打印菜单名称
        for(int i = 0; i < level; i++) {
            System.out.print("--");
        }
        System.out.println(name);

        //打印子菜单或者子菜单项名称
        for (MenuComponent component : menuComponentList) {
            component.print();
        }
    }
}

Client.java

package com.itheima.pattern.combination;

/**
 * @version v1.0
 * @ClassName: Client
 * @Description: TODO(一句话描述该类的功能)
 * @Author: dym
 */
public class Client {
    public static void main(String[] args) {
        //创建菜单树
        MenuComponent menu1 = new Menu("菜单管理",2);
        menu1.add(new MenuItem("页面访问",3));
        menu1.add(new MenuItem("展开菜单",3));
        menu1.add(new MenuItem("编辑菜单",3));
        menu1.add(new MenuItem("删除菜单",3));
        menu1.add(new MenuItem("新增菜单",3));

        MenuComponent menu2 = new Menu("权限管理",2);
        menu2.add(new MenuItem("页面访问",3));
        menu2.add(new MenuItem("提交保存",3));

        MenuComponent menu3 = new Menu("角色管理",2);
        menu3.add(new MenuItem("页面访问",3));
        menu3.add(new MenuItem("新增角色",3));
        menu3.add(new MenuItem("修改角色",3));

        //创建一级菜单
        MenuComponent component = new Menu("系统管理",1);
        //将二级菜单添加到一级菜单中
        component.add(menu1);
        component.add(menu2);
        component.add(menu3);


        //打印菜单名称(如果有子菜单一块打印)
        component.print();
    }
}



El MenuComponent aquí se define como una clase abstracta,

Debido a que hay algunas propiedades y comportamientos comunes que se deben implementar en esta clase, las clases Menu y MenuItem solo pueden cubrir los métodos que les interesan.

En lugar de tratar con métodos que no necesita o que no le interesan,

por ejemplo,

La clase Menú puede contener submenús, por lo que debe anular los métodos add (), remove (), getChild (),

Pero MenuItem no debería tener estos métodos.

La implementación predeterminada que se proporciona aquí es para lanzar una excepción, también puede reescribir la implementación predeterminada de acuerdo con sus necesidades



La clase Menu ha implementado todos los demás métodos excepto el método getName, porque la clase Menu tiene las funciones de agregar menús, eliminar menús y obtener submenús.

MenuItem es un elemento de menú y ya no puede tener submenús, por lo que las funciones de agregar menús, eliminar menús y obtener submenús no se pueden realizar.



Clasificación de modos de combinación

Al usar el modo de combinación, de acuerdo con la forma de definición de la clase de componente abstracto, podemos dividir el modo de combinación en dos formas: el modo de combinación transparente y el modo de combinación seguro .

  • Modo de combinación transparente

    Modo de combinación transparente, papel raíz abstracta declara todos los métodos para la gestión de los miembros del objeto , como en el ejemplo  MenuComponent declara  add, remove , getChild métodos, beneficios de hacerlo es asegurarse de que todos los miembros tienen el mismo tipo de interfaz. El modo de combinación transparente también es la forma estándar del modo de combinación.

    La desventaja del modo de combinación transparente es que no es lo suficientemente seguro , porque los objetos hoja y los objetos contenedor son esencialmente diferentes . Los objetos hoja no pueden tener el siguiente nivel de objetos, es decir, no pueden contener objetos miembros, así que agregue () y elimine () y otros métodos no tienen sentido, esto no generará un error durante la fase de compilación, pero si llama a estos métodos durante la fase de tiempo de ejecución, pueden ocurrir errores (si no se proporciona el código de manejo de errores correspondiente)

  • Modo de combinación segura

    En el modo de combinación de seguridad, no se declaran métodos para administrar objetos miembro en el rol de componente abstracto, pero Menu estos métodos se declaran e implementan en la clase de nodo de rama  . El modo combinado de desventajas de seguridad no es transparente porque el miembro y el miembro contenedor se van con métodos diferentes, y el miembro contenedor para administrar esos miembros del objeto no está definido en el miembro de la clase abstracta, por lo que el cliente no puede abstraer completamente para la programación, debe Trate los componentes de las hojas y los componentes del contenedor de manera diferente .



ventaja

  • El modo de combinación puede definir claramente objetos complejos jerárquicos , que representan la totalidad o parte de la jerarquía del objeto, permite al cliente ignorar las diferencias de niveles y facilitar el control de toda la jerarquía.
  • El cliente puede usar una estructura compuesta o un solo objeto en ella de manera consistente, y no necesita preocuparse por si está procesando un solo objeto o toda la estructura compuesta, lo que simplifica el código del cliente.
  • Es muy conveniente agregar nuevos nodos de rama y nodos de hoja en el modo combinado, sin ninguna modificación a la biblioteca de clases existente, que se ajusta al "principio de apertura y cierre".
  • El modo de combinación proporciona una solución flexible para la realización orientada a objetos de la estructura de árbol.A través de la combinación recursiva de nodos de hoja y nodos de rama, se puede formar una estructura de árbol compleja , pero el control de la estructura de árbol es muy simple.

 

escenas que se utilizarán

El modo de combinación nace en respuesta a la estructura del árbol, por lo que la escena de uso del modo de combinación es donde aparece la estructura del árbol.

Por ejemplo: visualización de directorio de archivos, visualización de directorio de varios niveles y otras operaciones de datos de estructura de árbol

 

Supongo que te gusta

Origin blog.csdn.net/qq_39368007/article/details/114012739
Recomendado
Clasificación