php教程 PHP开发 반복자 패턴을 사용하여 객체를 문자열로 변환

반복자 패턴을 사용하여 객체를 문자열로 변환

Dec 13, 2016 pm 05:46 PM
iterator

JSOM, XML, Java Bean 및 기타 객체를 조작할 때 먼저 방문자 패턴을 생각할 수 있습니다. 그러나 방문자 패턴을 사용하면 호출 코드에서 콜백을 제어하기가 어렵습니다. 예를 들어 모든 콜백 하위 분기 및 리프 노드에서 분기를 조건부로 건너뛸 수 없습니다. 이 문제를 해결하려면 반복자 패턴을 사용하여 전체 개체를 탐색하고 개발자가 쉽게 읽고 디버그할 수 있는 문자열을 생성할 수 있습니다. 이 반복자는 매우 다재다능하며 XPath를 사용하여 Java 개체를 찾고 StackHunter에서 예외를 기록하는 것과 같은 도구에서 사용했습니다.

API

이 글에서는 주로 StringGenerator와 ObjectIterator라는 두 가지 클래스를 소개합니다.

문자열 생성기

StringGenerator 도구 클래스는 객체를 더 읽기 쉽게 만들기 위해 객체를 문자열로 변환합니다. 이를 사용하여 클래스의 toString 메소드를 구현하거나 객체의 문자열 표현식을 로그 디버깅 코드로 사용할 수 있습니다.

package com.stackhunter.util.tostring.example;
 
import com.stackhunter.example.employee.Department;
import com.stackhunter.example.employee.Employee;
import com.stackhunter.example.employee.Manager;
import com.stackhunter.example.people.Person;
 
import com.stackhunter.util.tostring.StringGenerator;
 
public class StringGeneratorExample {
 
    public static void main(String[] args) {
        Department department = new Department(5775, "Sales")
        .setEmployees(
                new Employee(111, "Bill", "Gates"), 
                new Employee(222, "Howard", "Schultz"), 
                new Manager(333, "Jeff", "Bezos", 75000));
 
        System.out.println(StringGenerator.generate(department));
        System.out.println(StringGenerator.generate(new int[] { 111, 222, 333 }));
        System.out.println(StringGenerator.generate(true));
    }
 
}
로그인 후 복사

StringGenerator.generate()는 출력을 위해 부서, 배열 및 부울 값의 형식을 지정합니다. .

com.stackhunter.example.employee.Department@129719f4
  deptId = 5775
  employeeList = java.util.ArrayList@7037717a
    employeeList[0] = com.stackhunter.example.employee.Employee@17a323c0
      firstName = Bill
      id = 111
      lastName = Gates
    employeeList[1] = com.stackhunter.example.employee.Employee@57801e5f
      firstName = Howard
      id = 222
      lastName = Schultz
    employeeList[2] = com.stackhunter.example.employee.Manager@1c4a1bda
      budget = 75000.0
      firstName = Jeff
      id = 333
      lastName = Bezos
  name = Sales
[I@39df3255
  object[0] = 111
  object[1] = 222
  object[2] = 333
true
로그인 후 복사

객체 반복자

ObjectIterator는 반복자 패턴을 사용하여 객체의 속성을 순회하고 키-값 쌍 형식으로 저장합니다. 객체의 Java Bean, 컬렉션, 배열 및 맵을 반복해야 합니다. ObjectIterator는 또한 객체 간의 순환 참조 처리를 고려합니다.

package com.stackhunter.util.tostring.example;
 
import com.stackhunter.example.employee.Department;
import com.stackhunter.example.employee.Employee;
import com.stackhunter.example.employee.Manager;
import com.stackhunter.util.objectiterator.ObjectIterator;
 
public class ObjectIteratorExample {
 
    public static void main(String[] args) {
        Department department = new Department(5775, "Sales")
        .setEmployees(
                new Employee(111, "Bill", "Gates"), 
                new Employee(222, "Howard", "Schultz"), 
                new Manager(333, "Jeff", "Bezos", 75000));
 
        ObjectIterator iterator = new ObjectIterator("some department", department);
         
        while (iterator.next()) {
            System.out.println(iterator.getName() + "=" + iterator.getValueAsString());
        }
    }
 
}
로그인 후 복사

전체 객체를 순회하여 키-값 쌍 컬렉션을 생성합니다. toString() 대신 getValueAsString() 메서드를 사용하여 출력 형식을 지정합니다. 기본 유형, 래핑된 유형, 문자열, 날짜 및 열거형에는 원래 toString() 구현을 사용하십시오. 다른 유형의 경우 클래스 이름과 해시 값이 출력됩니다.

ObjectIterator.getDepth()는 들여쓰기를 늘리고 출력을 더 읽기 쉽게 만듭니다. 현재 분기를 단축하고 다음 속성으로 이동하려면 next()를 호출하기 전에 nextParent()를 사용하십시오.

some department=com.stackhunter.example.employee.Department@780324ff
deptId=5775
employeeList=java.util.ArrayList@6bd15108
employeeList[0]=com.stackhunter.example.employee.Employee@22a79c31
firstName=Bill
...
로그인 후 복사

Java 객체 반복자의 구체적인 구현

반복자 패턴을 구현하는 첫 번째 단계는 일반 반복자 인터페이스인 IObjectIterator를 만드는 것입니다. 이 인터페이스는 탐색된 객체가 Java Bean, 배열 또는 맵인지 여부에 관계없이 사용할 수 있습니다.

public interface IObjectIterator {
    boolean next();
    String getName();
    Object getValue();
}
로그인 후 복사

이 인터페이스를 사용하면 현재 속성의 이름과 값을 단일 순서로 얻을 수 있습니다.

IObjectIterator를 구현하는 클래스는 특정 유형의 개체를 처리하는 데 사용됩니다. 대부분의 클래스는 getName()을 호출하여 이름 접두사를 반환합니다. ArrayIterator는 요소의 인덱스를 사용합니다: 반환 이름 + "[" + nextIndex + "]";.

반복자 패턴을 사용하여 객체를 문자열로 변환

Property Iterator

PropertyIterator는 아마도 가장 중요한 반복 클래스일 것입니다. 이는 Java Bean 내부 검사를 사용하여 객체 속성을 읽고 이를 일련의 키-값 쌍으로 변환합니다.

public class PropertyIterator implements IObjectIterator {
 
    private final Object object;
    private final PropertyDescriptor[] properties;
    private int nextIndex = -1;
    private PropertyDescriptor currentProperty;
 
    public PropertyIterator(Object object) {
        this.object = object;
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
            properties = beanInfo.getPropertyDescriptors();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
 
    @Override
    public boolean next() {
        if (nextIndex + 1 >= properties.length) {
            return false;
        }
 
        nextIndex++;
        currentProperty = properties[nextIndex];
        if (currentProperty.getReadMethod() == null || "class".equals(currentProperty.getName())) {
            return next();
        }
        return true;
    }
 
    @Override
    public String getName() {
        if (currentProperty == null) {
            return null;
        }
        return currentProperty.getName();
    }
 
    @Override
    public Object getValue() {
        try {
            if (currentProperty == null) {
                return null;
            }
            return currentProperty.getReadMethod().invoke(object);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
 
}
로그인 후 복사

Array Iterator

ArrayIterator는 리플렉션을 통해 배열의 길이를 가져온 다음 각 데이터 요소를 검색합니다. ArrayIterator는 getValue() 메서드에서 반환된 값의 특정 세부 정보에 관심이 없습니다. 일반적으로 PropertyIterator에 전달됩니다.

public class ArrayIterator implements IObjectIterator {
 
    private final String name;
    private final Object array;
    private final int length;
    private int nextIndex = -1;
    private Object currentElement;
 
    public ArrayIterator(String name, Object array) {
        this.name = name;
        this.array = array;
        this.length = Array.getLength(array);
    }
 
    @Override
    public boolean next() {
        if (nextIndex + 1 >= length) {
            return false;
        }
 
        nextIndex++;
        currentElement = Array.get(array, nextIndex);
        return true;
    }
 
    @Override
    public String getName() {
        return name + "[" + nextIndex + "]";
    }
 
    @Override
    public Object getValue() {
        return currentElement;
    }
 
}
로그인 후 복사

集合迭代器

CollectionIterator与ArrayIterator非常相似。使用java.lang.Iterable调用它的Iterable.iterator()方法初始化内部迭代器。

Map迭代器

MapIterator遍历java.util.Map的entry。它并不深入到每个entry的键值对,这个工作由MapEntryIterator类完成。

public class MapIterator implements IObjectIterator {
 
    private final String name;
    private Iterator<?> entryIterator;
    private Map.Entry<?, ?> currentEntry;
    private int nextIndex = -1;
 
    public MapIterator(String name, Map<?, ?> map) {
        this.name = name;
        this.entryIterator = map.entrySet().iterator();
    }
 
    @Override
    public boolean next() {
        if (entryIterator.hasNext()) {
            nextIndex++;
            currentEntry = (Entry<?, ?>) entryIterator.next();
            return true;
        }
        return false;
    }
 
    ...
 
}
로그인 후 복사

Map Entry迭代器

MapEntryIterator处理java.util.Map的单个entry。它只返回两个值:entry的键和值。与ArrayIterator及其他的类似,如果是复杂类型的话,它的结果可能最终传递给PropertyIterator,作为Java bean处理。

根迭代器

RootIterator返回单个元素——初始节点。可以把它想成XML文件的根节点。目的是发起整个遍历过程。

整合

ObjectIterator类作为门面角色(Facade),包装了所有的遍历逻辑。它根据最后一次getValue()的返回值类型决定哪个IObjectIterator的子类需要实例化。当子迭代器在内部创建时它在栈中保存当前迭代器的状态。它也暴露了getChild()和getDepth()方法为调用者展示当前进度。

private IObjectIterator iteratorFor(Object object) {
    try {
        if (object == null) {
            return null;
        }
 
        if (object.getClass().isArray()) {
            return new ArrayIterator(name, object);
        }
 
        if (object instanceof Iterable) {
            return new CollectionIterator(name, (Iterable<?>) object);
        }
 
        if (object instanceof Map) {
            return new MapIterator(name, (Map<?, ?>) object);
        }
 
        if (object instanceof Map.Entry) {
            return new MapEntryIterator(name, (Map.Entry<?, ?>) object);
        }
 
        if (isSingleValued(object)) {
            return null;
        }
 
        return new PropertyIterator(object);
    } catch (RuntimeException e) {
        throw e;
    } catch (Exception e) {
        throw new RuntimeException(e.getMessage(), e);
    }
 
}
로그인 후 복사

字符串生成器的实现

已经看到如何遍历对象中的所有属性。最后的工作就是让输出更加美观,以及增加一些限制条件(比如不能创建一个GB级大小的字符串)。

public static String generate(Object object) {
    String s = "";
 
    ObjectIterator iterator = new ObjectIterator("object", object);
 
    ...
 
    while (iterator.next()) {
        if (s.length() >= MAX_STRING_LENGTH) {
            return s;
        }
 
        if (iterator.getChild() >= MAX_CHILDREN) {
            iterator.nextParent();
            continue;
        }
 
        String valueAsString = iterator.getValueAsString();
 
        s += System.lineSeparator();
        s += indent(iterator.getDepth()) + truncateString(iterator.getName());
        if (valueAsString == null) {
            s += " = null";
        } else {
            s += " = " + truncateString(valueAsString);
        }
    }
 
    return s;
}
로그인 후 복사

代码第21行完成了格式化,增加了缩进和层次结构使显示更美观。

同时增加了一些限制条件:

第9行——限制字符串长度在16k内。

第13行——限制任何父节点下子节点数量小于64.

第21&25行——限制键和值长度在64个字符。

总结

本文介绍了如何使用迭代器模式遍历包含各种复杂属性的对象。关键是将每种类型的迭代委派给各自的类实现。可以在你自己的软件中使用这两个工具。


본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

<gum> : Bubble Gum Simulator Infinity- 로얄 키를 얻고 사용하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
Nordhold : Fusion System, 설명
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora : 마녀 트리의 속삭임 - Grappling Hook 잠금 해제 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Java Iterator와 Iterable: 반복자와 반복 가능한 객체의 세계 알아보기 Java Iterator와 Iterable: 반복자와 반복 가능한 객체의 세계 알아보기 Feb 19, 2024 pm 02:15 PM

Java 프로그래밍에서 Iterator 및 Iterable 인터페이스는 컬렉션의 요소를 처리하는 데 중요한 도구입니다. Iterator 인터페이스는 컬렉션 요소에 대한 반복적인 액세스를 위한 메서드를 제공하는 반면, Iterable 인터페이스는 컬렉션의 요소가 Iterator를 통해 액세스될 수 있도록 컬렉션의 반복성을 정의합니다. 둘 사이의 긴밀한 협력은 컬렉션 요소를 탐색하는 일반적인 방법을 제공합니다. Iterator 인터페이스 Iterator 인터페이스는 다음 메소드를 정의합니다. booleanhasNext(): 컬렉션에 아직 요소가 있는지 확인합니다. Enext(): 컬렉션의 다음 요소를 반환합니다. voidremove(): 현재 요소를 제거합니다. 반복 가능

Java Iterator와 Iterable: 우아한 코드 작성을 위한 단계 Java Iterator와 Iterable: 우아한 코드 작성을 위한 단계 Feb 19, 2024 pm 02:54 PM

Iterator 인터페이스 Iterator 인터페이스는 컬렉션을 순회하는 데 사용되는 인터페이스입니다. hasNext(), next() 및 Remove()를 포함한 여러 메소드를 제공합니다. hasNext() 메서드는 컬렉션에 다음 요소가 있는지 여부를 나타내는 부울 값을 반환합니다. next() 메서드는 컬렉션의 다음 요소를 반환하고 컬렉션에서 제거합니다. Remove() 메서드는 컬렉션에서 현재 요소를 제거합니다. 다음 코드 예제에서는 Iterator 인터페이스를 사용하여 컬렉션을 반복하는 방법을 보여줍니다. Listnames=Arrays.asList("John","Mary","Bob");Iterator

Java Iterator와 Iterable의 심층 비교: 장단점 분석 Java Iterator와 Iterable의 심층 비교: 장단점 분석 Feb 19, 2024 pm 04:20 PM

개념적 차이점: Iterator: Iterator는 컬렉션에서 값을 얻는 반복자를 나타내는 인터페이스입니다. MoveNext(), Current() 및 Reset()과 같은 메서드를 제공하여 컬렉션의 요소를 순회하고 현재 요소에 대해 작업을 수행할 수 있습니다. Iterable: Iterable은 반복 가능한 객체를 나타내는 인터페이스이기도 합니다. 컬렉션의 요소 탐색을 용이하게 하기 위해 Iterator 객체를 반환하는 Iterator() 메서드를 제공합니다. 사용법: Iterator: Iterator를 사용하려면 먼저 Iterator 객체를 얻은 후 MoveNext() 메서드를 호출하여 다음 객체로 이동해야 합니다.

Java Iterator와 Iterable: Java 컬렉션의 힘 활용 Java Iterator와 Iterable: Java 컬렉션의 힘 활용 Feb 19, 2024 pm 07:00 PM

Java에서 컬렉션은 이러한 요소를 저장, 검색 및 작동하기 위한 통합 인터페이스와 메서드를 제공하는 요소의 컬렉션입니다. Iterator 및 Iterable은 컬렉션 요소 순회를 위한 공통 메커니즘을 제공하는 두 가지 중요한 Java 인터페이스입니다. Iterator 인터페이스는 컬렉션 순회를 위한 hasNext() 및 next() 메소드를 정의합니다. hasNext() 메소드는 컬렉션에 탐색되지 않은 요소가 있는지 확인하는 데 사용되며, next() 메소드는 현재 요소를 반환하고 다음 요소로 이동하는 데 사용됩니다. Iterable 인터페이스는 컬렉션의 요소를 순회하기 위해 Iterator 객체를 반환하는 iterator() 메서드를 정의합니다.

Java Iterator 및 Iterable: 설명된 컬렉션 탐색의 핵심 Java Iterator 및 Iterable: 설명된 컬렉션 탐색의 핵심 Feb 20, 2024 am 10:27 AM

Iterator 소개 Iterator는 컬렉션 탐색을 위한 Java의 인터페이스입니다. 컬렉션의 요소에 순차적으로 액세스할 수 있는 메서드 집합을 제공합니다. Iterator를 사용하여 List, Set, Map과 같은 컬렉션 유형을 반복할 수 있습니다. 데모 코드: Listlist=newArrayList();list.add("one");list.add("two");list.add("two");Iteratoriterator=list.iterator();while(iter

Java Iterator 및 Iterable: Java 컬렉션 순회 메커니즘에 대한 심층 분석 Java Iterator 및 Iterable: Java 컬렉션 순회 메커니즘에 대한 심층 분석 Feb 19, 2024 pm 08:36 PM

Iterator 인터페이스 Iterator 인터페이스는 컬렉션 탐색을 위한 Java 컬렉션 프레임워크의 하위 수준 인터페이스입니다. 이는 두 가지 주요 메소드를 정의합니다: hasNext(): 컬렉션에 더 많은 요소가 있는지 확인합니다. next(): 컬렉션의 다음 요소를 반환합니다. Iterator 인터페이스는 컬렉션에서 현재 요소를 제거하는 데 사용되는 Remove() 메서드와 같은 일부 선택적 메서드도 정의합니다. Iterator 인터페이스 사용하기 Iterator 인터페이스를 사용하면 다음 단계에 따라 컬렉션을 탐색할 수 있습니다. 컬렉션의 Iterator 객체를 가져옵니다. 컬렉션에 추가 요소가 있는지 확인하려면 hasNext() 메서드를 사용하세요. 요소가 더 있으면 next() 메서드를 사용하여 다음 요소를 가져옵니다.

Java 문서 해석: HashSet 클래스의 iterator() 메소드 사용법에 대한 자세한 설명 Java 문서 해석: HashSet 클래스의 iterator() 메소드 사용법에 대한 자세한 설명 Nov 03, 2023 am 09:44 AM

Java 문서 해석: HashSet 클래스의 iterator() 메소드 사용법에 대한 자세한 설명이 필요합니다. Java 프로그래밍에서 HashSet은 일반적으로 사용되는 컬렉션 클래스 중 하나이며 Set 인터페이스를 상속합니다. AbstractSet 클래스. HashSet 클래스의 iterator() 메서드는 HashSet의 요소를 순회하기 위한 반복자 객체를 반환하는 데 사용됩니다. 이번 글에서는 HashSet 클래스의 iterator() 메소드 사용법을 자세히 설명하고,

Java Iterator 및 Iterable: 컬렉션 탐색의 비하인드 스토리 Java Iterator 및 Iterable: 컬렉션 탐색의 비하인드 스토리 Feb 19, 2024 pm 04:15 PM

Iterator(Iterator)와 Iterable 객체(Iterable)는 Java 컬렉션 프레임워크에서 매우 중요한 두 가지 인터페이스입니다. 컬렉션의 특정 구현을 알지 못해도 컬렉션의 요소를 반복할 수 있습니다. Iterator 인터페이스는 hasNext() 및 next()를 포함하여 컬렉션을 탐색하기 위한 메서드를 정의합니다. hasNext() 메서드는 컬렉션에 추가 요소가 있는지 확인하고, next() 메서드는 컬렉션의 다음 요소를 반환합니다. Iterable 인터페이스는 Iterator() 메소드인 Iterator를 생성하는 메소드를 정의합니다. 이 메서드는 컬렉션을 반복하는 데 사용할 수 있는 Iterator 개체를 반환합니다. 다음은 Itera를 사용하고 있습니다

See all articles