JavaRush /Blog Java /Random-VI /Cấp độ 37. Trả lời các câu hỏi phỏng vấn về chủ đề cấp độ...
lichMax
Mức độ
Санкт-Петербург

Cấp độ 37. Trả lời các câu hỏi phỏng vấn về chủ đề cấp độ

Xuất bản trong nhóm
Xin chào. Một lần nữa, tôi không tìm thấy câu trả lời cho những câu hỏi này. Tôi quyết định đăng câu trả lời mà tôi đã biên soạn cho chính mình. Level 37. Trả lời câu hỏi phỏng vấn về chủ đề cấp độ - 1Dưới đây là những câu hỏi thực tế :
  1. Các mẫu thiết kế là gì?
  2. Bạn biết những mẫu thiết kế nào?
  3. Hãy cho chúng tôi biết về mẫu Singleton? Làm thế nào để làm cho nó an toàn?
  4. Hãy cho chúng tôi biết về mẫu Nhà máy?
  5. Hãy cho chúng tôi biết về mẫu Tóm tắt
  6. Hãy cho chúng tôi biết về mẫu Adaper, sự khác biệt của nó với Wrapper?
  7. Hãy cho chúng tôi biết về mẫu Proxy
  8. Trình vòng lặp là gì? Bạn biết những giao diện nào liên quan đến iterator?
  9. Tại sao chúng ta cần lớp Arrays?
  10. Tại sao chúng ta cần lớp Collections?
Đây là câu trả lời của tôi: Câu trả lời của tôi:
  1. Các mẫu thiết kế là các giải pháp thành công, được thiết lập tốt cho các vấn đề phổ biến nhất phát sinh trong quá trình thiết kế và phát triển chương trình hoặc các bộ phận của chúng.

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

  3. Khi bạn chỉ cần một phiên bản của một lớp tồn tại trong một chương trình, mẫu này sẽ được sử dụng Singleton. Nó trông như thế này (khởi tạo lười biếng):

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

    Để làm cho luồng này an toàn, bạn có thể thêm getInstance()công cụ sửa đổi vào phương thức synchronized. Nhưng đây sẽ không phải là giải pháp tốt nhất (nhưng đơn giản nhất). Một giải pháp tốt hơn nhiều là viết phương thức getInstancetheo cách này (khóa kiểm tra hai lần):

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

  4. Một mô hình Factorylà một mô hình sáng tạo. Nó cho phép bạn tạo các đối tượng theo yêu cầu (ví dụ: trong một số điều kiện nhất định). Nó trông như thế này:

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

    Ngoài ra còn có một biến thể của mẫu này được gọi là FactoryMethod. Theo mẫu này, các đối tượng khác nhau được tạo theo một phương thức, tùy thuộc vào dữ liệu đầu vào đến (giá trị tham số). Tất cả các đối tượng này phải có một tổ tiên chung (hoặc một giao diện có thể triển khai chung). Nó trông như thế này:

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

    Các lớp Object1Object2kế Object3thừa từ lớp CommonClass.

  5. Một mẫu Abstract Factorycũng là một mẫu thiết kế sáng tạo. Theo mẫu này, một nhà máy trừu tượng được tạo ra để làm mẫu cho một số nhà máy cụ thể. Đây là một ví dụ:

    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. Một mẫu Adapterlà một mẫu cấu trúc. Việc triển khai nó cho phép một đối tượng thuộc một loại được sử dụng khi cần có một đối tượng thuộc loại khác (thường là các loại trừu tượng). Một ví dụ triển khai mẫu này:

    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. Lớp này Arrayslà một lớp tiện ích được thiết kế cho nhiều thao tác mảng. Lớp này có các phương thức để biến một mảng thành một danh sách, tìm kiếm trong một mảng, sao chép một mảng, so sánh các mảng, lấy mã băm của mảng, biểu diễn một mảng dưới dạng một chuỗi, v.v.

  10. Lớp này Collectionslà lớp tiện ích để làm việc với các bộ sưu tập. Lớp này có các phương thức để thêm các phần tử vào một bộ sưu tập, điền các phần tử vào một bộ sưu tập, tìm kiếm một bộ sưu tập, sao chép một bộ sưu tập, so sánh một bộ sưu tập, tìm các phần tử tối đa và tối thiểu của một bộ sưu tập, cũng như các phương thức để có được các sửa đổi cụ thể của các bộ sưu tập của các loại đã biết (ví dụ: bạn có thể nhận được bộ sưu tập an toàn theo luồng hoặc bộ sưu tập bất biến với một phần tử).

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION