JavaRush /Java-Blog /Random-DE /Level 37. Antworten auf Interviewfragen zum Levelthema
lichMax
Level 40
Санкт-Петербург

Level 37. Antworten auf Interviewfragen zum Levelthema

Veröffentlicht in der Gruppe Random-DE
Guten Tag. Auch auf diese Fragen habe ich keine Antworten gefunden. Ich beschloss, die Antworten, die ich für mich selbst zusammengestellt hatte, zu veröffentlichen. Stufe 37. Antworten auf Interviewfragen zum Thema Stufe - 1Hier sind die eigentlichen Fragen: Fragen zum Interview:
  1. Was sind Designmuster?
  2. Welche Designmuster kennen Sie?
  3. Erzählen Sie uns etwas über das Singleton-Muster? Wie mache ich es threadsicher?
  4. Erzählen Sie uns etwas über das Factory-Muster?
  5. Erzählen Sie uns etwas über das AbstractFactory-Muster
  6. Erzählen Sie uns etwas über das Adaper-Muster und seine Unterschiede zum Wrapper?
  7. Erzählen Sie uns etwas über das Proxy-Muster
  8. Was ist ein Iterator? Welche Schnittstellen im Zusammenhang mit Iteratoren kennen Sie?
  9. Warum brauchen wir die Arrays-Klasse?
  10. Warum brauchen wir die Collections-Klasse?
Hier sind meine Antworten: Meine Antworten:
  1. Entwurfsmuster sind etablierte und erfolgreiche Lösungen für die häufigsten Probleme, die beim Entwurf und der Entwicklung von Programmen oder Teilen davon auftreten.

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

  3. Wenn in einem Programm nur eine Instanz einer Klasse vorhanden sein muss, wird das Muster verwendet Singleton. Es sieht so aus (verzögerte Initialisierung):

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

    Um es Thread-sicher zu machen, können Sie der Methode getInstance()einen Modifikator hinzufügen synchronized. Dies wird jedoch nicht die beste (aber die einfachste) Lösung sein. getInstanceEine viel bessere Lösung besteht darin, die Methode folgendermaßen zu schreiben (doppelt überprüftes Sperren):

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

  4. Ein Muster Factoryist ein generatives Muster. Es ermöglicht Ihnen, Objekte bei Bedarf zu erstellen (z. B. unter bestimmten Bedingungen). Es sieht aus wie das:

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

    Es gibt auch eine Variation dieses Musters namens FactoryMethod. Nach diesem Muster werden in einer Methode abhängig von den eingehenden Eingabedaten (Parameterwerten) unterschiedliche Objekte erstellt. Alle diese Objekte müssen einen gemeinsamen Vorfahren (oder eine gemeinsame implementierte Schnittstelle) haben. Es sieht aus wie das:

    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;
    		}
    	}
    }

    Klassen Object1und Object2erben Object3von der Klasse CommonClass.

  5. Ein Muster Abstract Factoryist auch ein generatives Designmuster. Nach diesem Muster entsteht eine abstrakte Fabrik, die als Vorlage für mehrere konkrete Fabriken dient. Hier ist ein Beispiel:

    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. Ein Muster Adapterist ein Strukturmuster. Seine Implementierung ermöglicht die Verwendung eines Objekts eines Typs, wenn ein Objekt eines anderen Typs erforderlich ist (normalerweise abstrakte Typen). Eine Beispielimplementierung dieses Musters:

    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 — это структурный паттерн проектирования. Он нужен для того, чтобы контролировать доступ к Wieому-то ein Objektу. Для этого пишется класс по типу "обёртка", то есть внутрь класса передаётся исходный ein Objekt, реализующий некий интерфейс, сам класс тоже реализует этот интерфейс, и в каждом методе этого класса вызывается похожий метод у исходного ein Objektа. Реализация того же интерфейса, что и у исходного ein Objektа, позволяет подменить исходный ein Objekt прокси-ein Objektом. Также это позволяет, не меняя исходного ein Objektа, "навешивать" на его методы Wieую-то специальную дополнительную функциональность (например, логирование, проверка прав доступа, кэширование и т.д.). Пример:

    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. Итератор — это специальный внутренний ein Objekt коллекции, который позволяет последовательно перебирать элементы этой коллекций. Этот ein Objekt должен реализовывать интерфейс Iterator<E>, либо ListIterator<E> (для списков). Также, для того, чтобы перебирать элементы коллекции, коллекция должна поддерживать интерфейс Iterable<E>. Интерфейс Iterable<E> содержит всего один метод — iterator(), который позволяет извне получить доступ к итератору коллекции.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. Die Klasse Arraysist eine Dienstprogrammklasse, die für eine Vielzahl von Array-Manipulationen entwickelt wurde. Diese Klasse verfügt über Methoden zum Umwandeln eines Arrays in eine Liste, zum Durchsuchen eines Arrays, zum Kopieren eines Arrays, zum Vergleichen von Arrays, zum Abrufen eines Array-Hashcodes, zum Darstellen eines Arrays als Zeichenfolge usw.

  10. Die Klasse Collectionsist eine Dienstprogrammklasse für die Arbeit mit Sammlungen. Diese Klasse verfügt über Methoden zum Hinzufügen von Elementen zu einer Sammlung, zum Füllen einer Sammlung mit Elementen, zum Durchsuchen einer Sammlung, zum Kopieren einer Sammlung, zum Vergleichen einer Sammlung, zum Finden der maximalen und minimalen Elemente einer Sammlung sowie Methoden zum Erhalten spezifischer Modifikationen von Sammlungen von bekannte Typen (zum Beispiel können Sie eine Thread-sichere Sammlung oder eine unveränderliche Sammlung mit einem Element erhalten).

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