디자인 패턴이란 무엇입니까?
디자인 패턴은 복잡한 문제에 대한 솔루션입니다. 디자인 패턴은 특정 디자인 문제를 해결하는 방식으로 클래스와 인터페이스를 만드는 것입니다. 일반적으로 시스템을 설계하는 동안 몇 가지 문제가 발생하며 이러한 문제에 대한 일련의 설계 패턴이 있습니다. 디자인 패턴은 일반적으로 클래스, 인터페이스 및 해당 클래스 간의 관계를 포함하는 템플릿입니다.
디자인 패턴 유형:
창조적인 디자인 패턴:
이러한 유형의 패턴은 주어진 상황에 맞게 객체 생성을 처리합니다.
생성 수준에서는 시스템의 특정 부분을 독립적으로 생성하거나 함께 구성하여 유연성과 호환성을 보장하는 방법을 결정할 수 있습니다.
이 카테고리에 속하는 디자인 패턴 목록은 다음과 같습니다.
- 싱글턴: 이 디자인 패턴에서는 단 하나의 인스턴스만 가지며 해당 인스턴스는 애플리케이션 전체에서 사용됩니다.
싱글턴 디자인 패턴의 필수 요소:
- 비공개 생성자: 생성자를 비공개로 표시하는 것은 클래스 인스턴스가 하나만 생성되도록 하기 위해 매우 중요합니다.
- 비공개 정적 인스턴스: 클래스 메모리에 객체의 인스턴스가 하나만 있도록 하기 위해 비공개 액세스 수정자를 사용합니다.
- 공개 정적 메서드(접속자): 단일 인스턴스에 대한 전역 액세스 지점입니다. 이 방법은 기본적으로 인스턴스가 없으면 생성하고 이미 존재하는 경우 동일한 인스턴스를 반환합니다.
싱글턴 디자인 패턴 예시
public class Singleton { // Private static instance of the class private static Singleton instance; private int count; // Private constructor to prevent instantiation private Singleton() { // initialization code } // Public static method to provide access to the instance public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } // Example method public void getCount() { System.out.println("The value of count is: " + count); } public void increaseCount() { count++; } public void decreaseCount() { count--; } } public class Main { public static void main(String[] args) { // Get the single instance of Singleton Singleton singleton = Singleton.getInstance(); singleton.increaseCount(); singleton.getCount(); // Output: The value of count is: 1 // Get the same instance of Singleton Singleton anotherSingleton = Singleton.getInstance(); anotherSingleton.decreaseCount(); anotherSingleton.getCount(); // Output: The value of count is: 0 // Both singleton and anotherSingleton refer to the same instance } }
- Builder: Builder 패턴에서는 객체를 생성하는 방법을 단계별로 정의합니다. 또한 이 패턴은 유연성을 제공하므로 동일한 구성 프로세스를 사용하여 동일한 객체의 다양한 버전을 생성할 수 있습니다.
빌더 패턴의 주요 필수 사항:
- 제품:구성되고 있는 복합물입니다.
- 빌더 인터페이스: 제품의 다양한 부분을 생성하는 방법을 정의합니다. 이러한 메소드는 일반적으로 메소드 체이닝을 허용하기 위해 빌더 객체 자체를 반환합니다.
- Concrete Builder:Builder 인터페이스를 구현하고 제품의 일부를 생성하기 위한 특정 구현을 제공합니다.
빌더 패턴의 예:
이 예에서는 빌더 디자인 패턴을 사용하여 단계별로 재료를 추가하여 초콜릿 스프레드 빵을 만드는 방법을 보여줍니다.
// Product Class class Bread { private String bread; private String spread; private String chiaSeeds; private String pumpkinSeeds; public void setBread(String bread) { this.bread = bread; } public void setSpread(String spread) { this.spread = spread; } public void setChiaSeeds(String chiaSeeds) { this.chiaSeeds = chiaSeeds; } public void setPumpkinSeeds(String pumpkinSeeds) { this.pumpkinSeeds = pumpkinSeeds; } @Override public String toString() { return "Bread with " + spread + ", topped with " + chiaSeeds + " and " + pumpkinSeeds; } } // Builder Interface interface BreadBuilder { BreadBuilder addBread(); BreadBuilder addChocolateSpread(); BreadBuilder addChiaSeeds(); BreadBuilder addPumpkinSeeds(); Bread build(); } // Concrete Builder class ChocolateBreadBuilder implements BreadBuilder { private Bread bread = new Bread(); @Override public BreadBuilder addBread() { bread.setBread("Whole grain bread"); return this; } @Override public BreadBuilder addChocolateSpread() { bread.setSpread("Chocolate spread"); return this; } @Override public BreadBuilder addChiaSeeds() { bread.setChiaSeeds("Chia seeds"); return this; } @Override public BreadBuilder addPumpkinSeeds() { bread.setPumpkinSeeds("Pumpkin seeds"); return this; } @Override public Bread build() { return bread; } } // Client Code public class Main { public static void main(String[] args) { // Create a builder and build the chocolate spread bread BreadBuilder builder = new ChocolateBreadBuilder(); Bread myBread = builder.addBread() .addChocolateSpread() .addChiaSeeds() .addPumpkinSeeds() .build(); // Output the result System.out.println(myBread); } }
- 팩토리 메소드: 팩토리 메소드 패턴에서는 객체를 생성하는 방법을 정의하지만 생성될 특정 객체 유형을 하위 클래스가 결정할 수 있도록 허용합니다.
팩토리 패턴의 핵심 요소:
- 제품 인터페이스: 모든 제품에 대한 공통 인터페이스를 정의합니다.
- 콘크리트 제품: 제품 인터페이스를 구현합니다.
- 제작자: 팩토리 메소드를 선언합니다.
- 콘크리트 크리에이터: 다양한 콘크리트 제품을 반환하는 팩토리 메소드를 구현합니다.
// Product Interface interface Juice { void serve(); } // Concrete Product 1 class OrangeJuice implements Juice { @Override public void serve() { System.out.println("Serving Orange Juice."); } } // Concrete Product 2 class MangoJuice implements Juice { @Override public void serve() { System.out.println("Serving Mango Juice."); } } // Creator Abstract Class abstract class JuiceFactory { // Factory method public abstract Juice createJuice(); } // Concrete Creator 1 class OrangeJuiceFactory extends JuiceFactory { @Override public Juice createJuice() { return new OrangeJuice(); } } // Concrete Creator 2 class MangoJuiceFactory extends JuiceFactory { @Override public Juice createJuice() { return new MangoJuice(); } } // Client Code public class Main { public static void main(String[] args) { // Create an Orange Juice using its factory JuiceFactory orangeJuiceFactory = new OrangeJuiceFactory(); Juice orangeJuice = orangeJuiceFactory.createJuice(); orangeJuice.serve(); // Output: Serving Orange Juice. // Create a Mango Juice using its factory JuiceFactory mangoJuiceFactory = new MangoJuiceFactory(); Juice mangoJuice = mangoJuiceFactory.createJuice(); mangoJuice.serve(); // Output: Serving Mango Juice. } }
구조적 디자인 패턴
이 디자인 패턴은 주로 클래스와 객체가 더 큰 구조를 형성하도록 구성되는 방식에 중점을 둡니다. 객체와 클래스 간의 구성과 관계에 중점을 두고 구조를 단순화하고 유연성을 강화하며 유지 관리성을 향상시킵니다.
- 어댑터 패턴: 이 패턴에서는 호환되지 않는 인터페이스를 가진 객체가 함께 작동하도록 허용합니다. 이는 호환되지 않는 두 인터페이스 사이의 브리지 역할을 하여 기존 코드를 변경하지 않고도 통신할 수 있게 해줍니다.
어댑터 패턴의 핵심 요소:
- Target Interface: It is an interface that will solve the problem (bridging the gap between the incompatible interfaces).
- Client: The class or code that interacts with the target interface.
- Adaptee: This is the interface which is not compatible with the current client requirements.
- Adapter: Implements the target interface and contains an instance of the adaptee. It translates requests from the target interface to the adaptee’s interface, making them compatible.
// Target Interface (Menu) interface Menu { void orderDish(String dish); } // Adaptee (Chef) class Chef { public void prepareDish(String dishName) { System.out.println("Chef is preparing " + dishName + "."); } } // Adapter (Waiter) class Waiter implements Menu { private Chef chef; public Waiter(Chef chef) { this.chef = chef; } @Override public void orderDish(String dish) { chef.prepareDish(dish); } } // Client Code public class Restaurant { public static void main(String[] args) { Chef chef = new Chef(); Menu waiter = new Waiter(chef); // Customer places an order via the waiter waiter.orderDish("Spaghetti Carbonara"); // Output: Chef is preparing Spaghetti Carbonara. } }
- Facade pattern: Simplifies the interaction with a complex system by providing a unified interface (facade). Instead of directly calling several different methods across various objects, the client interacts with the facade, which internally manages those operations.
Key essentials of the facade design pattern:
- Facade: It is an interface that wraps all the complex subsystem interfaces and delegates the complex tasks to the subsystems that actually perform the work.
- Subsystem Classes: These are the classes that acutally perform the work.
An example of facade design pattern:
The example illustrates the Facade Pattern which simplifies the process of washing, drying, and pressing clothes. It hides the complexity of interacting with multiple subsystems behind a single, unified interface.
// Subsystem Classes class WashingMachine { public void wash() { System.out.println("Washing clothes."); } } class Dryer { public void dry() { System.out.println("Drying clothes."); } } class Iron { public void press() { System.out.println("Pressing clothes."); } } // Facade Class class LaundryFacade { private WashingMachine washingMachine; private Dryer dryer; private Iron iron; public LaundryFacade(WashingMachine washingMachine, Dryer dryer, Iron iron) { this.washingMachine = washingMachine; this.dryer = dryer; this.iron = iron; } public void doLaundry() { System.out.println("Starting the laundry process..."); washingMachine.wash(); dryer.dry(); iron.press(); System.out.println("Laundry process complete."); } } // Client Code public class Main { public static void main(String[] args) { WashingMachine washingMachine = new WashingMachine(); Dryer dryer = new Dryer(); Iron iron = new Iron(); LaundryFacade laundryFacade = new LaundryFacade(washingMachine, dryer, iron); // Use the facade to do the laundry laundryFacade.doLaundry(); } }
Behavioral design patterns
The patterns that fall under this category mainly deals with communication between objects and how they interact with each other.
- Iterator pattern: In the Iterator Pattern, we define a way to sequentially access elements of a collection without needing to use conventional methods, such as for loops or direct indexing. Instead, the pattern provides a standard interface (usually methods like next() and hasNext()) to traverse the collection. This approach abstracts the iteration process, allowing the client to navigate through the collection without needing to understand its internal structure or use traditional iteration methods.
Key essentials of this pattern are:
- Iterator Interface: We define all the methods such as next(), hasNext(), and currentItem().These are used to traverse the collection.
- Concrete Iterator: This is the concrete implementation of the iterator interface.
- Aggregate Interface: In this interface,we define methods to create iterators.All the methods returns an instance of the Iterator.
- Concrete Aggregate: It's just a concrete implementation of the aggregate interface.
Example of iterator pattern:
This example demostrates a simple usecase of iterators a employees object using iterator pattern.
// Iterator Interface interface Iterator { boolean hasNext(); Object next(); } // Aggregate Interface interface Aggregate { Iterator createIterator(); } // Employee Class class Employee { public String Name; public int Age; public String Department; public int EmployeeId; public Employee(String name, int age, String department, int employeeId) { this.Name = name; this.Age = age; this.Department = department; this.EmployeeId = employeeId; } } // Concrete Aggregate class EmployeeCollection implements Aggregate { private Employee[] employees; public EmployeeCollection(Employee[] employees) { this.employees = employees; } @Override public Iterator createIterator() { return new EmployeeIterator(this.employees); } } // Concrete Iterator class EmployeeIterator implements Iterator { private Employee[] employees; private int position = 0; public EmployeeIterator(Employee[] employees) { this.employees = employees; } @Override public boolean hasNext() { return position
- Strategy pattern: In this pattern we define a family of algorithms, and at the runtime we choose the algorithm.Instead of implementing a single algorithm directly, the code receives runtime instructions on which algorithm to use from a family of algorithms. This pattern allows the algorithm to vary independently from the clients that use it.
Key essentials of this pattern are:
1.Strategy Interface: Defines the common interface for all supported algorithms.
2.Concrete Strategies: Implement the Strategy interface with specific algorithms.
3.Context: Uses a Strategy to execute the algorithm.
Example of strategy pattern:
Imagine we are building an encoding system where we may need to use different encoding algorithms depending on the situation. We will demonstrate this system using the Strategy Pattern.
// Strategy Interface interface EncoderStrategy { void encode(String string); } // Concrete Strategy for Base64 Encoding class Base64Encoder implements EncoderStrategy { @Override public void encode(String string) { // Implement Base64 encoding logic here System.out.println("This method uses Base64 encoding algorithm for: " + string); } } // Concrete Strategy for MD5 Encoding class MD5Encoder implements EncoderStrategy { @Override public void encode(String string) { // Implement MD5 encoding logic here System.out.println("This method uses MD5 encoding algorithm for: " + string); } } // Context Class class EncoderContext { private EncoderStrategy strategy; public void setEncoderMethod(EncoderStrategy strategy) { this.strategy = strategy; } public void encode(String string) { strategy.encode(string); } } // Usage public class Main { public static void main(String[] args) { EncoderContext context = new EncoderContext(); // Use Base64 encoding method context.setEncoderMethod(new Base64Encoder()); context.encode("A34937ifdsuhfweiur"); // Use MD5 encoding method context.setEncoderMethod(new MD5Encoder()); context.encode("89743297dfhksdhWOJO"); } }
Explanation:
- Firstly, we define the interface for the
- Next, we create concrete implementations of the interfaces that we have defined.
- Finally, we use these implementations to observe how a change in the subject also updates its dependents.
- Observer pattern: behavioral design pattern that establishes a one-to-many dependency between objects. This means that when one object (the subject) changes its state, all its dependent objects (observers) are notified and updated automatically. This pattern is particularly useful for implementing distributed event-handling systems in event-driven software.
Key essentials of this pattern are:
- Subject: It is an object which holds the state and informs the observers when it updates it's state.
- Observer: An interface or abstract class that defines the update method, which is called when the subject’s state changes.
- Concrete Subject: A class that implements the Subject interface and maintains the state of interest to observers.
- Concrete Observer: A class that implements the Observer interface and updates its state to match the subject’s state.
Example of observer pattern:
In a stock trading application, the stock ticker acts as the subject. Whenever the price of a stock is updated, various observers—such as investors and regulatory bodies—are notified of the change. This allows them to respond to price fluctuations in real-time.
import java.util.ArrayList; import java.util.List; // Observer interface interface Observer { void update(String stockSymbol, double stockPrice); } // Subject interface interface Subject { void register(Observer o); void remove(Observer o); void notify(); } // Concrete Subject class Stock implements Subject { private List<observer> observers; private String stockSymbol; private double stockPrice; public Stock() { observers = new ArrayList(); } public void setStock(String stockSymbol, double stockPrice) { this.stockSymbol = stockSymbol; this.stockPrice = stockPrice; notify(); } @Override public void register(Observer o) { observers.add(o); } @Override public void remove(Observer o) { observers.remove(o); } @Override public void notify() { for (Observer observer : observers) { observer.update(stockSymbol, stockPrice); } } } // Concrete Observer class StockTrader implements Observer { private String traderName; public StockTrader(String traderName) { this.traderName = traderName; } @Override public void update(String stockSymbol, double stockPrice) { System.out.println("Trader " + traderName + " notified. Stock: " + stockSymbol + " is now $" + stockPrice); } } // Usage public class Main { public static void main(String[] args) { Stock stock = new Stock(); StockTrader trader1 = new StockTrader("Niharika"); StockTrader trader2 = new StockTrader("Goulikar"); stock.register(trader1); stock.register(trader2); stock.setStock("Niha", 9500.00); stock.setStock("Rika", 2800.00); } } </observer>
Explanation:
- Firstly, we define the interface for the subject which is responsible for sending updates. Similarly, we also define an interface for the observer, which is responsible for receiving updates.
- Next, we create concrete implementations of the interfaces that we have defined.
- Finally, we use these implementations to observe how a change in the subject also updates its dependents.
위 내용은 디자인 패턴: 일반적인 디자인 패턴에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

이 기사에서는 Java 프로젝트 관리, 구축 자동화 및 종속성 해상도에 Maven 및 Gradle을 사용하여 접근 방식과 최적화 전략을 비교합니다.

이 기사에서는 Maven 및 Gradle과 같은 도구를 사용하여 적절한 버전 및 종속성 관리로 사용자 정의 Java 라이브러리 (JAR Files)를 작성하고 사용하는 것에 대해 설명합니다.

이 기사는 카페인 및 구아바 캐시를 사용하여 자바에서 다단계 캐싱을 구현하여 응용 프로그램 성능을 향상시키는 것에 대해 설명합니다. 구성 및 퇴거 정책 관리 Best Pra와 함께 설정, 통합 및 성능 이점을 다룹니다.

이 기사는 캐싱 및 게으른 하중과 같은 고급 기능을 사용하여 객체 관계 매핑에 JPA를 사용하는 것에 대해 설명합니다. 잠재적 인 함정을 강조하면서 성능을 최적화하기위한 설정, 엔티티 매핑 및 모범 사례를 다룹니다. [159 문자]

Java의 클래스 로딩에는 부트 스트랩, 확장 및 응용 프로그램 클래스 로더가있는 계층 적 시스템을 사용하여 클래스로드, 링크 및 초기화 클래스가 포함됩니다. 학부모 위임 모델은 핵심 클래스가 먼저로드되어 사용자 정의 클래스 LOA에 영향을 미치도록합니다.


핫 AI 도구

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

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

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

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

안전한 시험 브라우저
안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

맨티스BT
Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

SecList
SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경
