JavaRush /Java Blog /Random-JA /レベル 37. レベルのトピックに関するインタビューの質問への回答
lichMax
レベル 40
Санкт-Петербург

レベル 37. レベルのトピックに関するインタビューの質問への回答

Random-JA グループに公開済み
こんにちは。繰り返しますが、これらの質問に対する答えも見つかりませんでした。自分用にまとめた回答を投稿することにしました。 レベル 37. レベル - 1 のトピックに関するインタビューの質問への回答実際の質問は次のとおりです。 面接の質問:
  1. デザインパターンとは何ですか?
  2. どのようなデザインパターンを知っていますか?
  3. シングルトンパターンについて教えてください。スレッドセーフにする方法は?
  4. Factoryパターンについて教えてください。
  5. AbstractFactory パターンについて教えてください
  6. Adaper パターンと Wrapper との違いについて教えてください。
  7. Proxyパターンについて教えてください
  8. イテレータとは何ですか? イテレータに関連するインターフェイスをご存知ですか?
  9. なぜ Arrays クラスが必要なのでしょうか?
  10. Collections クラスが必要な理由は何ですか?
私の答えは次のとおりです。 私の答えは次のとおりです。
  1. デザイン パターンは、プログラムまたはその一部の設計および開発中に発生する最も一般的な問題に対する、確立された成功した解決策です。

  2. Singleton、、、、、、、、、、。Factory_ _ _ _ _ _ _ _Abstract FactoryTemplate methodStrategyPoolAdapterProxyBridgeMVC

  3. プログラム内に存在するクラスのインスタンスが 1 つだけ必要な場合は、パターンが使用されますSingleton。次のようになります (遅延初期化)。

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

    スレッドセーフにするために、メソッドにgetInstance()修飾子を追加できますsynchronized。ただし、これは最善の解決策ではありません (ただし、最も単純な解決策です)。より良い解決策は、getInstance次のようにメソッドを記述することです (二重チェックされたロック)。

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

  4. パターンはFactory生成パターンです。これにより、オンデマンド (たとえば、特定の条件下) でオブジェクトを作成できます。次のようになります。

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

    このパターンには、 と呼ばれるバリエーションもありますFactoryMethod。このパターンによれば、受信する入力データ (パラメーター値) に応じて、1 つのメソッドで異なるオブジェクトが作成されます。これらすべてのオブジェクトには、共通の祖先 (または共通の実装可能なインターフェイス) が必要です。次のようになります。

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

    クラスObject1Object2およびObject3クラスから継承しますCommonClass

  5. パターンはAbstract Factoryジェネレーティブ デザイン パターンでもあります。このパターンに従って、複数の具体的なファクトリのテンプレートとして機能する抽象ファクトリが作成されます。以下に例を示します。

    
    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. パターンとはAdapter構造的なパターンのことです。その実装により、ある型のオブジェクトを、別の型のオブジェクト (通常は抽象型) が必要な場合に使用できるようになります。このパターンの実装例:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. このクラスは、Arraysさまざまな配列操作用に設計されたユーティリティ クラスです。このクラスには、配列をリストに変換する、配列を検索する、配列をコピーする、配列を比較する、配列のハッシュコードを取得する、配列を文字列として表現するなどのメソッドがあります。

  10. このクラスは、Collectionsコレクションを操作するためのユーティリティ クラスです。このクラスには、コレクションへの要素の追加、コレクションへの要素の入力、コレクションの検索、コレクションのコピー、コレクションの比較、コレクションの最大要素と最小要素の検索を行うためのメソッドに加え、コレクションの特定の変更を取得するためのメソッドがあります。既知の型 (たとえば、スレッドセーフなコレクションまたは 1 つの要素を含む不変のコレクションを取得できます)。

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION