跳至主要內容

Java设计模式

pptg大约 8 分钟

六大原则

  1. 单一职责原则
  2. 开闭原则: 开放扩展, 关闭修改(相同功能的if-else, 封装成接口)
  3. 里氏替换原则
  4. 依赖倒置: 抽象/接口不依赖实现类
  5. 接口隔离: 最小化接口
  6. 迪米特原则: 只和最直接的类通信

1. 创建型

1.1 单例模式

单例模式保证每次获取一个类的实例时,都是同一个实例,防止重复性的创建一些资源。单例模式的实现方式有很多,主要的区别体现在是否支持懒加载、是否线程安全等方面。

饿汉
// 迫不及待的准备好"食物", 所以叫饿汉
public class Singleton {
    public static final Singleton s = new Singleton();
    
    private Singleton(){}
    
    public static Singleton getInstance(){
        return s;
    }
}

注意

需要注意反序列化、线程安全、clone、反射可以破坏单例

1.2 建造者

建造者模式将复杂的构建过程和内部表示分离,适用于不同执行顺序的结果不同,或参数较多且存在默认值的场景。

package computer;

public class Computer {
    private Host host;
    private KeyBoard keyBoard;
    private Mouse mouse;
    private Screen screen;

    public static Builder Builder(){
        return new Builder();
    }
    
    private Computer(Computer.Builder builder){
        // 根据参数构建Computer
        this.host = new Host();
        this.keyBoard = new KeyBoard();
        this.mouse = new Mouse();
        this.screen = new Screen();
    }

    public static class Builder {
        // 默认策略
        private String host = "HP";
        private String keyBoard = "Rainy75";
        private String mouse = "Logic";
        private String screen = "Dell";

        private Builder(){}

        public Builder Host(String host){
            this.host = host;
            return this;
        }

        public Builder KeyBoard(String keyBoard){
            this.keyBoard = keyBoard;
            return this;
        }

        public Builder Mouse(String mouse){
            this.mouse = mouse;
            return this;
        }

        public Builder Screen(String screen){
            this.screen = screen;
            return this;
        }

        public Computer build(){
            return new Computer(this);
        }
    }
}

// 使用方法
Computer computer = Computer.Builder().Host("apple").build();

1.3 原型模式

原型模式用来解决创建重复对象时,初始化的资源消耗大、过程复杂的问题。

注意

  1. 简单的类通过Cloneable反而速度不如重新new一个
  2. 直接clone不行么?
public class Document{
    private ArrayList<String> mImages = new ArrayList<>();
    public Document() {}

    @Override
    protected Document clone() throws CloneNotSupportedException {
        try{
            Document document = (Document) super.clone();
            // 浅拷贝
            document.mImages = this.mImages;
            // 深拷贝
            document.mImages = (ArrayList<String>) this.mImages.clone();
            return document;
        }catch (CloneNotSupportedException e){
        }
        return null;
    }
}

1.4 工厂模式

工厂模式的介绍上,网上的很多文章说法都不太一样,这里根据自己的理解记录一下

1.4.1 简单工厂模式

简单工厂模式通过一个统一工厂,创建一系列继承自同一父类的产品。然而简单工厂模式不符合开闭原则,当新增一个产品时,仍需要修改case部分进行判断。

// Hp、Huawei、Xiaomi 都 extends Computer
public class EasyFactory {
    public static Computer product(String type){
        return switch (type) {
            case "Hp" -> new HpComputer();
            case "Huawei" -> new HuaweiComputer();
            case "Xiaomi" -> new XiaomiComputer();
            default -> null;
        };
    }
}

1.4.2 工厂模式

工厂模式定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

工厂模式
工厂模式
public interface ComputerFactory {
    Computer product();
}

public class HpFactory implements ComputerFactory {
    @Override
    public Computer product() {
        return new HpComputer();
    }
}

1.4.3 抽象工厂模式

抽象工厂模式是将多个相互关联的产品组合到一个抽象的工厂中,确保一个工厂生产的产品都是相互关联的。我理解为相比工厂模式从生产单一产品,变成了生产多个产品。

抽象工厂模式
抽象工厂模式
public interface AbstractFactory {
    Computer productComputer();
    Phone productPhone();
}

public class HpFactory implements AbstractFactory{
    @Override
    public Computer productComputer() {
        return new HpComputer();
    }

    @Override
    public Phone productPhone() {
        return new HpPhone();
    }
}

2. 行为型

2.1 策略模式

策略模式可以将原本用if-else来选择代码逻辑的场景进行包装,并提供统一上下文给外部调用。

策略模式
策略模式

比如程序中可能会调用原生、QQ、微信的电话,例子如下:

CallContext
public class CallContext {
    private final Call call;

    public CallContext(Call call) {
        this.call = call;
    }

    public void makeCall() {
        call.makeCall();
    }
}

2.2 状态模式

状态模式和策略模式类似,但状态模式更强调一个类在不同状态下具有不同的行为。所以在具体实现上,策略模式是直接将内部的实现细节暴露在construct上,而状态模式则是对外暴露setState方法,允许动态的改变状态。

Java设计模式 状态模式.png
Java设计模式 状态模式.png

比如一个手机在开机、关机两个状态下对拨打电话和发送短信的反馈会不同:

PhoneContext
public class PhoneContext{

    private PhoneState state;


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

    public void makeCall() {
        state.makeCall();
    }

    public void sendMsg() {
        state.sendMsg();
    }

    public void close(){
        state.close();
        state = new PhoneCloseState();
    }

    public void open(){
        state.open();
        state = new PhoneOpenState();
    }
}

2.3 责任链模式

责任链模式解决了一组程序的先后执行关系,处于链条上的程序均有机会执行代码,同时也可以阻断后续代码的执行。

责任链模式
责任链模式

考虑一个三级审批流程如下:

ExamineHandler
public abstract class ExamineHandler {
    private ExamineHandler next;

    public ExamineHandler next() {
        return next;
    }

    public ExamineHandler appendNext(ExamineHandler next) {
        this.next = next;
        return this;
    }

    public abstract void handle(String input);
}

2.4 观察者模式

观察者模式实现了订阅-发布系统,当一个对象改变时,其他所有依赖他的对象都会得到通知。

观察者模式
观察者模式

对于一个订阅具有两个观察者的代码如下:

Subject
public class Subject {
    private List<Observer> observers;

    public Subject() {
        this.observers = new ArrayList<>();
    }

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

    public void notifySubjects(){
        observers.forEach(Observer::update);
    }
}

2.5 模版方法模式

模版方法模式定义了程序的架构,并将具体的步骤延迟到子类中实现。

模版方法模式
模版方法模式

代码如下:

Template
public abstract class Template {
    public void execute(){
        stepOne();
        stepTwo();
        stepThree();
    }

    protected abstract void stepOne();

    protected abstract void stepTwo();

    protected abstract void stepThree();
}

3. 结构型

3.1 代理模式

代理模式通过对其他对象提供代理来控制对这个对象的访问。

代理模式
代理模式
PhoneProxy
public class PhoneProxy implements Phone{

    private Phone phone;

    public PhoneProxy(Phone phone) {
        this.phone = phone;
    }

    @Override
    public void makeCall() {
        System.out.println("ready to call");
        phone.makeCall();
        System.out.println("call finish");
    }
}

3.2 组合模式

组合模式将多个单体的对象组合成具有统一行为的合集

Java设计模式 组合模式.png
Java设计模式 组合模式.png
Composite
public abstract class Composite {
    protected String name;

    public Composite(String name) {
        this.name = name;
    }

    public abstract void makeCall();
}