>  기사  >  Java  >  일반적으로 사용되는 7가지 Java 디자인 패턴에 대해 심층적으로 이해하세요.

일반적으로 사용되는 7가지 Java 디자인 패턴에 대해 심층적으로 이해하세요.

王林
王林원래의
2023-12-23 13:01:10720검색

일반적으로 사용되는 7가지 Java 디자인 패턴에 대해 심층적으로 이해하세요.

Java 디자인 패턴 이해: 일반적으로 사용되는 7가지 디자인 패턴 소개, 구체적인 코드 예제가 필요합니다.

Java 디자인 패턴은 소프트웨어 디자인 문제에 대한 보편적인 솔루션으로 널리 받아들여지는 디자인 아이디어와 행동 ​​강령을 제공합니다. 디자인 패턴은 코드 구조를 더 잘 구성하고 계획하는 데 도움이 되므로 코드의 유지 관리, 읽기 및 확장성이 향상됩니다. 이 글에서는 Java에서 일반적으로 사용되는 7가지 디자인 패턴을 소개하고 해당 코드 예제를 제공합니다.

  1. 싱글턴 패턴:
    싱글턴 패턴은 클래스에 인스턴스가 하나만 있고 전역 액세스 지점을 제공하도록 보장합니다. 이는 리소스를 공유해야 하거나 개체 수가 제한되는 시나리오에서 유용합니다. 다음은 싱글톤 패턴의 코드 예입니다.
public class Singleton {

    private static Singleton instance;

    private Singleton() {
        // 私有构造函数,防止外部实例化
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  1. Factory 패턴:
    팩토리 패턴은 팩토리 클래스를 통해 객체를 생성하고 객체 생성 프로세스를 캡슐화합니다. 이렇게 하면 개체의 특정 구현 세부 정보를 숨길 수 있어 클라이언트 코드가 더욱 간결해지고 확장 가능해집니다. 다음은 팩토리 패턴의 코드 예입니다.
public interface Shape {
    void draw();
}

public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Circle::draw()");
    }
}

public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Rectangle::draw()");
    }
}

public class ShapeFactory {
    public Shape getShape(String shapeType) {
        if (shapeType == null) {
            return null;
        }
        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
            return new Rectangle();
        }
        return null;
    }
}
  1. Observer 패턴:
    Observer 패턴은 객체의 상태가 변경되면 해당 객체의 상태에 따라 업데이트됩니다. 자동으로. 이는 이벤트 중심, 게시-구독 및 GUI 개발에 유용합니다. 다음은 Observer 패턴의 코드 예입니다.
import java.util.ArrayList;
import java.util.List;

public class Subject {
    private List<Observer> observers = new ArrayList<>();
    private int state;

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        notifyAllObservers();
    }

    public void attach(Observer observer) {
        observers.add(observer);
    }

    public void notifyAllObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}

public abstract class Observer {
    protected Subject subject;
    public abstract void update();
}

public class BinaryObserver extends Observer {
    public BinaryObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    public void update() {
        System.out.println("Binary String: " + Integer.toBinaryString(subject.getState()));
    }
}

public class OctalObserver extends Observer {
    public OctalObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    public void update() {
        System.out.println("Octal String: " + Integer.toOctalString(subject.getState()));
    }
}

public class HexObserver extends Observer {
    public HexObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    public void update() {
        System.out.println("Hex String: " + Integer.toHexString(subject.getState()));
    }
}

public class ObserverPatternDemo {
    public static void main(String[] args) {
        Subject subject = new Subject();
        new BinaryObserver(subject);
        new OctalObserver(subject);
        new HexObserver(subject);

        System.out.println("First state change: 15");
        subject.setState(15);
        System.out.println("Second state change: 10");
        subject.setState(10);
    }
}
  1. Builder 패턴(Builder 패턴):
    Builder 패턴을 사용하면 객체의 구성 프로세스를 분리하여 동일한 구성 프로세스를 사용하여 다양한 표현을 만들 수 있습니다. 이렇게 하면 코드 유연성과 가독성이 향상되고 빌드 매개변수가 너무 많아지는 문제가 방지됩니다. 다음은 빌더 패턴의 코드 예입니다.
public class Computer {
    private String cpu;
    private String memory;
    private String disk;
    // 省略其他属性和方法
}

public interface ComputerBuilder {
    ComputerBuilder setCpu(String cpu);
    ComputerBuilder setMemory(String memory);
    ComputerBuilder setDisk(String disk);
    Computer build();
}

public class BasicComputerBuilder implements ComputerBuilder {
    private Computer computer;

    public BasicComputerBuilder() {
        computer = new Computer();
    }

    public ComputerBuilder setCpu(String cpu) {
        computer.setCpu(cpu);
        return this;
    }

    public ComputerBuilder setMemory(String memory) {
        computer.setMemory(memory);
        return this;
    }

    public ComputerBuilder setDisk(String disk) {
        computer.setDisk(disk);
        return this;
    }

    public Computer build() {
        return computer;
    }
}

public class Director {
    private ComputerBuilder computerBuilder;

    public Director(ComputerBuilder computerBuilder) {
        this.computerBuilder = computerBuilder;
    }

    public Computer construct() {
        return computerBuilder
                .setCpu("i5")
                .setMemory("8GB")
                .setDisk("1TB")
                .build();
    }
}

public class BuilderPatternDemo {
    public static void main(String[] args) {
        ComputerBuilder computerBuilder = new BasicComputerBuilder();
        Director director = new Director(computerBuilder);
        Computer computer = director.construct();

        System.out.println(computer.toString());
    }
}
  1. 프로토타입 패턴:
    프로토타입 패턴은 기존 개체를 다시 만드는 대신 기존 개체를 복사하여 새 개체를 만듭니다. 이는 특히 객체의 초기화 프로세스가 복잡한 경우 객체 생성 효율성을 향상시킬 수 있습니다. 다음은 프로토타입 패턴의 코드 예제입니다.
public abstract class Shape implements Cloneable {
    private String id;
    protected String type;
    
    abstract void draw();

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
    
    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}

public class Circle extends Shape {
    public Circle() {
        type = "Circle";
    }

    public void draw() {
        System.out.println("Inside Circle::draw() method.");
    }
}

public class Rectangle extends Shape {
    public Rectangle() {
        type = "Rectangle";
    }

    public void draw() {
        System.out.println("Inside Rectangle::draw() method.");
    }
}

public class ShapeCache {
    private static Map<String, Shape> shapeMap = new HashMap<>();

    public static Shape getShape(String shapeId) {
        Shape cachedShape = shapeMap.get(shapeId);
        return (Shape) cachedShape.clone();
    }

    public static void loadCache() {
        Circle circle = new Circle();
        circle.setId("1");
        shapeMap.put(circle.getId(), circle);

        Rectangle rectangle = new Rectangle();
        rectangle.setId("2");
        shapeMap.put(rectangle.getId(), rectangle);
    }
}

public class PrototypePatternDemo {
    public static void main(String[] args) {
        ShapeCache.loadCache();

        Shape clonedShape1 = ShapeCache.getShape("1");
        System.out.println("Shape: " + clonedShape1.getType());

        Shape clonedShape2 = ShapeCache.getShape("2");
        System.out.println("Shape: " + clonedShape2.getType());
    }
}
  1. 어댑터 패턴:
    어댑터 패턴은 클래스의 인터페이스를 클라이언트가 예상하는 다른 인터페이스로 변환합니다. 이는 기존 코드를 변경하지 않고도 호환되지 않는 인터페이스가 함께 작동할 수 있는 기능을 제공합니다. 다음은 어댑터 패턴의 코드 예입니다.
public interface MediaPlayer {
    void play(String audioType, String fileName);
}

public interface AdvancedMediaPlayer {
    void playVlc(String fileName);

    void playMp4(String fileName);
}

public class VlcPlayer implements AdvancedMediaPlayer {
    public void playVlc(String fileName) {
        System.out.println("Playing vlc file. Name: " + fileName);
    }

    public void playMp4(String fileName) {
        // 空实现
    }
}

public class Mp4Player implements AdvancedMediaPlayer {
    public void playVlc(String fileName) {
        // 空实现
    }

    public void playMp4(String fileName) {
        System.out.println("Playing mp4 file. Name: " + fileName);
    }
}

public class MediaAdapter implements MediaPlayer {
    AdvancedMediaPlayer advancedMediaPlayer;

    public MediaAdapter(String audioType) {
        if (audioType.equalsIgnoreCase("vlc")) {
            advancedMediaPlayer = new VlcPlayer();
        } else if (audioType.equalsIgnoreCase("mp4")) {
            advancedMediaPlayer = new Mp4Player();
        }
    }

    public void play(String audioType, String fileName) {
        if (audioType.equalsIgnoreCase("vlc")) {
            advancedMediaPlayer.playVlc(fileName);
        } else if (audioType.equalsIgnoreCase("mp4")) {
            advancedMediaPlayer.playMp4(fileName);
        }
    }
}

public class AudioPlayer implements MediaPlayer {
    MediaAdapter mediaAdapter;

    public void play(String audioType, String fileName) {
        if (audioType.equalsIgnoreCase("mp3")) {
            System.out.println("Playing mp3 file. Name: " + fileName);
        } else if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {
            mediaAdapter = new MediaAdapter(audioType);
            mediaAdapter.play(audioType, fileName);
        } else {
            System.out.println("Invalid media. " + audioType + " format not supported");
        }
    }
}

public class AdapterPatternDemo {
    public static void main(String[] args) {
        AudioPlayer audioPlayer = new AudioPlayer();
        audioPlayer.play("mp3", "beyond_the_horizon.mp3");
        audioPlayer.play("mp4", "alone.mp4");
        audioPlayer.play("vlc", "far_far_away.vlc");
        audioPlayer.play("avi", "mind_me.avi");
    }
}
  1. 전략 패턴:
    전략 패턴은 일련의 알고리즘을 정의하고 각 알고리즘을 서로 교체할 수 있도록 캡슐화합니다. 이를 통해 코드의 다른 부분에 영향을 주지 않고 알고리즘을 쉽게 전환하거나 새 알고리즘을 확장할 수 있습니다. 다음은 전략 패턴의 코드 예시입니다.
public interface Strategy {
    int doOperation(int num1, int num2);
}

public class OperationAdd implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

public class OperationSubtract implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

public class OperationMultiply implements Strategy {
    public int doOperation(int num1, int num2) {
        return num1 * num2;
    }
}

public class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}

public class StrategyPatternDemo {
    public static void main(String[] args) {
        Context context = new Context(new OperationAdd());
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

        context = new Context(new OperationSubtract());
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

        context = new Context(new OperationMultiply());
        System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
    }
}

위의 예시 코드를 통해 자바에서 흔히 사용되는 7가지 디자인 패턴에 대해 간략하게 소개합니다. 각 디자인 패턴에는 서로 다른 시나리오와 애플리케이션이 있으며 서로 다른 프로젝트에서 작동할 수 있습니다. 이 글이 디자인 패턴을 이해하고 적용하며, 코드 품질과 개발 효율성을 높이는 데 도움이 되기를 바랍니다.

위 내용은 일반적으로 사용되는 7가지 Java 디자인 패턴에 대해 심층적으로 이해하세요.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.