JavaRush /Blog Java /Random-ES /Nivel 37. Respuestas a las preguntas de la entrevista sob...
lichMax
Nivel 40
Санкт-Петербург

Nivel 37. Respuestas a las preguntas de la entrevista sobre el tema del nivel.

Publicado en el grupo Random-ES
Hola. Nuevamente, tampoco encontré respuestas a estas preguntas. Decidí publicar las respuestas que compilé por mí mismo. Nivel 37. Respuestas a las preguntas de la entrevista sobre el tema del nivel - 1Aquí están las preguntas reales: Preguntas para la entrevista:
  1. ¿Qué son los patrones de diseño?
  2. ¿Qué patrones de diseño conoces?
  3. ¿Cuéntanos sobre el patrón Singleton? ¿Cómo hacerlo seguro para subprocesos?
  4. ¿Cuéntanos sobre el patrón Factory?
  5. Cuéntanos sobre el patrón AbstractFactory
  6. ¿Cuéntanos sobre el patrón Adaptador, sus diferencias con Wrapper?
  7. Cuéntanos sobre el patrón Proxy
  8. ¿Qué es un iterador? ¿Qué interfaces relacionadas con el iterador conoces?
  9. ¿Por qué necesitamos la clase Arrays?
  10. ¿Por qué necesitamos la clase Colecciones?
Aquí están mis respuestas: Mis respuestas:
  1. Los patrones de diseño son soluciones exitosas y bien establecidas a los problemas más comunes que surgen durante el diseño y desarrollo de programas o sus partes.

  2. Singleton, Factory, Abstract Factory, Template method, Strategy, Pool, Adapter, Proxy, Bridge. MVC_

  3. Cuando necesita que solo exista una instancia de una clase en un programa, se utiliza el patrón Singleton. Se ve así (inicialización diferida):

    clas Singleton {
    	private Singleton instance;
    
    	private Singleton() {}
    
    	public static Singletot getInstance() {
    		if (instance == null)
    			instance = new Singleton();
    		return instance;
    	}
    }

    Para que sea seguro para subprocesos, puede agregar getInstance()un modificador al método synchronized. Pero esta no será la mejor solución (sino la más sencilla). Una solución mucho mejor es escribir el método getInstancede esta manera (bloqueo verificado dos veces):

    public static synchronized Singleton getInstance() {
    	if (instance == null)
    		synchronized(Singleton.class) {
    			instance = new Singleton();
    		}
    	return instance;
    }

  4. Un patrón Factoryes un patrón generativo. Le permite crear objetos bajo demanda (por ejemplo, bajo ciertas condiciones). Se parece a esto:

    class Factory{
    	public static Object1 getObject1() {
    		return new Object1();
    	}
    
    	public static Object2 getObject2() {
    		return new Object2();
    	}
    
    	public static Object3 getObject3() {
    		return new Object3();
    	}
    }

    También existe una variación de este patrón llamada FactoryMethod. Según este patrón, se crean diferentes objetos en un método, dependiendo de los datos de entrada entrantes (valores de parámetros). Todos estos objetos deben tener un ancestro común (o una interfaz implementable común). Se parece a esto:

    class FactoryMethod {
    	public enum TypeObject {
    		TYPE1,
    		TYPE2,
    		TYPE3
    	}
    
    	public static CommonClass getObject(TypeObject type) {
    		switch(type) {
    			case TYPE1:
    				return new Object1();
    			case TYPE2:
    				return new Object2();
    			case TYPE3:
    				return new Object3();
    			default:
    				return null;
    		}
    	}
    }

    Clases Object1y Object2heredar Object3de la clase CommonClass.

  5. Un patrón Abstract Factorytambién es un patrón de diseño generativo. Según este patrón, se crea una fábrica abstracta que sirve como plantilla para varias fábricas concretas. He aquí un ejemplo:

    class Human {}
    
    class Boy extends Human {}
    class TeenBoy extends Human {}
    class Man extends Human {}
    class OldMan extends Human {}
    
    class Girl extends Human {}
    class TeenGirl extends Human {}
    class Woman extends Human {}
    class OldWoman extends Human {}
    
    interface AbstractFactory {
    	Human getPerson(int age);
    }
    
    class FactoryMale implements AbstractFactory {
    	public Human getPerson(int age) {
    		if (age < 12)
    			return new Boy();
    		if (age >= 12 && age <= 20)
    			return new TeenBoy();
    		if (age > 20 && age < 60)
    			return new Man();
    		return new OldMan();
    	}
    }
    
    сlass FactoryFemale implements AbstractFactory {
    	public Human getPerson(int age) {
    		if (age < 12)
    			return new Girl();
    		if (age >= 12 && age <= 20)
    			return new TeenGirl();
    		if (age > 20 && age < 60)
    			return new Woman();
    		return new OldWoman();
    	}
    }

  6. Un patrón Adapteres un patrón estructural. Su implementación permite utilizar un objeto de un tipo cuando se requiere un objeto de otro tipo (normalmente tipos abstractos). Un ejemplo de implementación de este patrón:

    interface TotalTime {
    	int getTotalSeconds();
    }
    interface Time {
    	int getHours();
    	int getMinutes();
    	int getSeconds();
    }
    
    class TimeAdapter extends TotalTime {
    	private Time time;
    	public TimeAdapter(Time time) {
    		this.time = time;
    	}
    	public int getTotalTime() {
    		return time.getSeconds + time.getMinutes * 60 + time.getHours * 60 * 60;
    	}
    }
    
    class TotalTimeAdapter extends Time {
    	private TotalTime totalTime;
    	public TotalTimeAdapter(TotalTime totalTime) {
    		this.totalTime = totalTime;
    	}
    
    	public int getSeconds() {
    		return totalTime % 60;
    	}
    
    	public int getMinutes() {
    		return (totalTime / 60) % 60;
    	}
    
    	public int getHours() {
    		return totaltime/ (60 * 60) ;
    	}
    }
    
    class Main {
    	public static void main(String[] args) {
    		Time time = new Time() {
    			public int getSeconds() {
    				return LocalTime.now().getSecond();
    			}
    
    			public int getMinutes() {
    				return LocalTime.now().getMinute();
    			}
    
    			public int getHours() {
    				return LocalTime.now().getHour() ;
    			}
    		};
    
    		TotalTime totalTime = new TimeAdapter(time);
    		System.out.println(totalTime.getTotalSeconds());
    
    		TotalTime totalTime2 = new TotalTime() {
    			public int getTotalSeconds() {
    				LocalTime currTime = LocalTime.now();
    				return currTime.getSecond() + currTime.getMinute * 60 + currTime.getHour * 60 * 60;
    			}
    		};
    
    		Time time2 = new TotalTimeAdapter(totalTime2);
    		System.out.println(time2.getHours + ":" + time2.getMinutes() + ":" + time2.getSeconds());
    	}
    }

    При реализации паттерна Wrapper создаётся класс, который оборачивает исходный класс и реализует тот же интерфейс, который реализует исходный класс. Таким образом, это позволяет расширить функциональность исходного класса и использовать новый класс там, где ожидается использование исходного класса. Это отличается от реализации паттерна Adapter тем, что в данном случае используется один интерфейс (тот же, что есть у исходного класса). В паттерне Adapter же используется два интерфейса, и класс, который оборачивает экземпяр исходного класса, реализует совсем другой инферфейс, не интерфейс исходного класса.

  7. Паттерн Proxy — это структурный паттерн проектирования. Он нужен для того, чтобы контролировать доступ к Cómoому-то un objetoу. Для этого пишется класс по типу "обёртка", то есть внутрь класса передаётся исходный un objeto, реализующий некий интерфейс, сам класс тоже реализует этот интерфейс, и в каждом методе этого класса вызывается похожий метод у исходного un objetoа. Реализация того же интерфейса, что и у исходного un objetoа, позволяет подменить исходный un objeto прокси-un objetoом. Также это позволяет, не меняя исходного un objetoа, "навешивать" на его методы Cómoую-то специальную дополнительную функциональность (например, логирование, проверка прав доступа, кэширование и т.д.). Пример:

    interface Bank {
    	void setUserMoney(User user, double money);
    	double getUserMoney(User user);
    }
    
    class CitiBank implements Bank { //оригинальный класс
    	public void setUserMoney(User user, double money) {
    		UserDAO.update(user,money);
    	}
    
    	public double getUserMoney(User user) {
    		UserDAO.getUserMoney(user);
    	}
    }
    
    class SecurityProxyBank implements Bank {
    	private Bank bank;
    
    	public SecurityProxyBank(Bank bank) {
    		this.bank = bank;
    	}
    
    	public void setUserMoney(User user, double money) {
    		if (!SecurityManager.authorize(user,BankAccounts.Manager)
    			throw new SecurityException("User can't change money value");
    
    		UserDAO.update(user,money);
    	}
    
    	public double getUserMoney(User user) {
    		if (!SecurityManager.authorize(user,BankAccounts.Manager)
    			throw new SecurityException("User can't get money value");
    
    		UserDAO.getUserMoney(user);
    	}

  8. Итератор — это специальный внутренний un objeto коллекции, который позволяет последовательно перебирать элементы этой коллекций. Этот un objeto должен реализовывать интерфейс Iterator<E>, либо ListIterator<E> (для списков). Также, для того, чтобы перебирать элементы коллекции, коллекция должна поддерживать интерфейс Iterable<E>. Интерфейс Iterable<E> содержит всего один метод — iterator(), который позволяет извне получить доступ к итератору коллекции.

    Интерфейс Iterator<E> содержит следующие методы:

    • boolean hasNext() — проверяет, есть ли в коллекции ещё Cómoой-то элемент

    • E next() — позволяет получить очередной элемент коллекции (после получения elemento, внутренний курсор итератора передвигается на следующий элемент коллекции)

    • void remove() — удаляет текущий элемент из коллекции

    Интерфейс же ListIterator<E> содержит такие методы:

    • boolean hasNext() — проверяет, существуют ли ещё один элемент в коллекции (следующий за текущим)

    • E next() — возвращает очередной элемент коллекции (и передвигает внутренний курсок итератора на следующий элемент)

    • int nextIndex() — возвращает индекс следующего elemento

    • void set(E e) — устанавливает significado текущего elemento void add(E e). Добавляет элемент в конец списка.

    • boolean hasPrevious() — проверяет, существует ли Cómoой-то элемент в коллекции перед данным элементом

    • E previous() — возвращает текущий элемент коллекции и переводит курсор на предыдущий элемент коллекции

    • int previousIndex — возвращает индекс предыдущего elemento коллекции

    • void remove() — удаляет текущий элемент коллекции

    • void add(E e) — добавляет элемент e после текущего elemento коллекции

  9. La clase Arrayses una clase de utilidad diseñada para una variedad de manipulaciones de matrices. Esta clase tiene métodos para convertir una matriz en una lista, buscar en una matriz, copiar una matriz, comparar matrices, obtener un código hash de matriz, representar una matriz como una cadena, etc.

  10. La clase Collectionses una clase de utilidad para trabajar con colecciones. Esta clase tiene métodos para agregar elementos a una colección, llenar una colección con elementos, buscar una colección, copiar una colección, comparar una colección, encontrar los elementos máximos y mínimos de una colección, así como métodos para obtener modificaciones específicas de colecciones de tipos conocidos (por ejemplo, puede obtener una colección segura para subprocesos o una colección inmutable con un elemento).

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION