一篇文章教你学会设计模式

设计原则有哪些?

设计模式是软件开发中用于解决常见问题的最佳实践。这些模式通过提供可复用的解决方案,帮助开发者提高代码的可维护性、可读性和可扩展性。设计模式的设计原则是一组指导方针,用于确保模式的有效性和实用性。以下是设计模式的一些核心设计原则:

  1. 开闭原则(Open/Closed Principle, OCP)

    • 软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着当需要增加新功能时,应通过扩展现有代码来实现,而不是修改已有代码。
  2. 里氏替换原则(Liskov Substitution Principle, LSP)

    • 子类必须能够替换它们的基类而不影响程序的正确性。这要求子类必须严格遵循基类所定义的行为契约。
  3. 依赖倒置原则(Dependency Inversion Principle, DIP)

    • 高层模块不应该依赖于低层模块,二者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。这有助于减少模块间的耦合度。
  4. 接口隔离原则(Interface Segregation Principle, ISP)

    • 客户端不应该被强迫依赖它们不使用的方法;接口应该小而专,客户端应该只依赖它们需要的方法。这有助于减少代码的冗余和复杂性。
  5. 单一职责原则(Single Responsibility Principle, SRP)

    • 一个类应该只有一个引起它变化的理由,即一个类只负责一个功能或一个职责。这有助于增强类的可维护性和可读性。
  6. 迪米特法则(Law of Demeter, LOD)

    • 一个对象应该对其他对象有最少的了解,只与直接朋友(即字段、局部变量、参数中的对象)通信。这有助于减少模块间的依赖和通信复杂度。
  7. 好莱坞原则(Hollywood Principle)

    • “别找我们,我们会找你”。这个原则强调组件应该尽量做到“不要调用我们,我们会调用你”。这通常通过事件驱动架构或回调机制来实现。
  8. 无重复自己原则(Don’t Repeat Yourself, DRY)

    • 系统中每一个独特的知识都必须有一个且仅有一个没有歧义的、权威的表示。这有助于减少代码重复,提高代码的可维护性。
  9. 稳定抽象原则(Stable Abstractions Principle, SAP)

    • 抽象层不应该依赖于细节层的不稳定性。这意味着应该尽量将不稳定的细节隐藏在稳定的抽象背后。
  10. 共同封闭原则(Common Closure Principle, CCP)

    • 包中的所有类应该一起被重用。如果重用了包中的一个类,那么通常也需要重用包中的其他类。这有助于保持包的内聚性。

这些原则并不是孤立的,它们相辅相成,共同指导设计模式的创建和应用。通过遵循这些原则,开发者可以设计出更加健壮、灵活和可维护的软件系统。

设计模式有哪些

设计模式是一种在软件设计中常用的模板,它提供了解决常见问题的标准方法。根据它们的功能和用途,设计模式通常被分为三类:创建型模式、结构型模式和行为型模式。以下是每种类型的详细列表及其简要说明:

创建型模式(Creational Patterns)

创建型模式主要关注对象的创建机制,使得系统更加灵活且易于扩展。

  1. 单例模式(Singleton Pattern)

    • 描述:确保一个类只有一个实例,并提供一个全局访问点。
    • 应用场景:日志文件、缓存、线程池等需要唯一实例的情况。
  2. 工厂方法模式(Factory Method Pattern)

    • 描述:定义一个用于创建对象的接口,让子类决定实例化哪一个类。
    • 应用场景:创建具有不同实现的对象,但希望保持一致的创建接口。
  3. 抽象工厂模式(Abstract Factory Pattern)

    • 描述:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
    • 应用场景:创建一组相关的对象,这些对象属于不同的类,但需要协调工作。
  4. 建造者模式(Builder Pattern)

    • 描述:允许逐步构建复杂的对象,直到最终构建完成。
    • 应用场景:创建复杂的对象,特别是对象的构建过程需要多个步骤或参数。
  5. 原型模式(Prototype Pattern)

    • 描述:允许复制现有的对象而不是重新创建新的对象,这可以提高效率。
    • 应用场景:对象创建成本较高,且对象之间只有少量差异时。

结构型模式(Structural Patterns)

结构型模式关注类或对象的组合,通过这种方式简化系统的组织结构。

  1. 适配器模式(Adapter Pattern)

    • 描述:允许不兼容的接口协同工作。
    • 应用场景:现有类库中的接口与当前需求不匹配时,可以通过适配器进行转换。
  2. 装饰器模式(Decorator Pattern)

    • 描述:允许动态地给对象添加新的功能。
    • 应用场景:需要在不修改对象的前提下增加额外的功能。
  3. 代理模式(Proxy Pattern)

    • 描述:为其他对象提供一种代理以控制对这个对象的访问。
    • 应用场景:延迟初始化、权限控制、远程代理等。
  4. 桥接模式(Bridge Pattern)

    • 描述:将抽象部分与实现部分分离,使它们可以独立变化。
    • 应用场景:类的继承层次过于复杂,需要将抽象部分和实现部分分开管理。
  5. 组合模式(Composite Pattern)

    • 描述:允许你将对象组合成树形结构来表示部分-整体的层次结构。
    • 应用场景:需要处理树形结构的数据,如文件系统、图形界面等。
  6. 外观模式(Facade Pattern)

    • 描述:提供一个统一的接口,用来访问子系统中的一组接口。
    • 应用场景:简化复杂的子系统接口,提供一个高层次的接口。
  7. 享元模式(Flyweight Pattern)

    • 描述:通过共享已经存在的对象来减少创建新对象的数量,从而节省内存。
    • 应用场景:大量相似对象需要高效存储和管理时。

行为型模式(Behavioral Patterns)

行为型模式关注对象之间的责任分配和通信机制。

  1. 策略模式(Strategy Pattern)

    • 描述:定义了一系列可互换的算法,并将它们封装起来。
    • 应用场景:需要在运行时动态选择算法时。
  2. 观察者模式(Observer Pattern)

    • 描述:定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。
    • 应用场景:事件驱动系统、消息订阅系统等。
  3. 命令模式(Command Pattern)

    • 描述:将请求封装成对象,从而使你可以用不同的请求、队列或者日志来参数化其他对象。
    • 应用场景:需要将请求排队或记录请求日志,以及支持可撤销操作。
  4. 状态模式(State Pattern)

    • 描述:允许一个对象在其内部状态改变时改变其行为,看起来像是改变了其类。
    • 应用场景:对象的行为依赖于其内部状态,并且需要在运行时根据状态改变行为。
  5. 责任链模式(Chain of Responsibility Pattern)

    • 描述:使多个对象有机会处理请求,从而避免请求的发送者和接收者之间的耦合。
    • 应用场景:处理请求的方式有多种,且不确定哪个对象会最终处理请求。
  6. 解释器模式(Interpreter Pattern)

    • 描述:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
    • 应用场景:需要解析和执行简单的语言表达式。
  7. 迭代器模式(Iterator Pattern)

    • 描述:提供一种方法顺序访问一个聚合对象中的各个元素,而不需要暴露该对象的内部表示。
    • 应用场景:遍历集合中的元素,而不暴露集合的内部结构。
  8. 中介者模式(Mediator Pattern)

    • 描述:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
    • 应用场景:多个对象之间存在复杂的交互关系,希望通过一个中介对象来管理这些关系。
  9. 备忘录模式(Memento Pattern)

    • 描述:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
    • 应用场景:需要保存一个对象的某个状态,以便在将来恢复这个状态。

这些设计模式各有其特点和适用场景,正确选择和应用设计模式可以使代码更加灵活、可维护和可扩展。希望这些信息对你有所帮助!如果你有任何具体的问题或需要进一步的解释,请随时提问。

易混淆设计模式举例

在设计模式中,有些模式由于名称相似或应用场景相近,容易被混淆。下面是一些常见的易混淆的设计模式及其区别的详细讲解:

1. 工厂方法模式(Factory Method Pattern) vs 抽象工厂模式(Abstract Factory Pattern)

工厂方法模式

  • 描述:定义一个用于创建对象的接口,让子类决定实例化哪一个类。
  • 核心:一个抽象工厂方法,由子类具体实现。
  • 应用场景:当你希望客户端代码不必关心对象的创建细节,而是通过一个统一的接口来获取对象。
  • 示例
    interface Product {
        void use();
    }
    
    class ConcreteProduct implements Product {
        @Override
        public void use() {
            System.out.println("Using ConcreteProduct");
        }
    }
    
    abstract class Creator {
        public final Product factoryMethod() {
            return createProduct();
        }
    
        protected abstract Product createProduct();
    }
    
    class ConcreteCreator extends Creator {
        @Override
        protected Product createProduct() {
            return new ConcreteProduct();
        }
    }
    

抽象工厂模式

  • 描述:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  • 核心:一个抽象工厂接口,包含多个创建方法,由具体的工厂类实现。
  • 应用场景:当你需要创建一组相关的对象,这些对象属于不同的类,但需要协调工作。
  • 示例
    interface AbstractFactory {
        ProductA createProductA();
        ProductB createProductB();
    }
    
    interface ProductA {}
    interface ProductB {}
    
    class ConcreteProductA implements ProductA {}
    class ConcreteProductB implements ProductB {}
    
    class ConcreteFactory implements AbstractFactory {
        @Override
        public ProductA createProductA() {
            return new ConcreteProductA();
        }
    
        @Override
        public ProductB createProductB() {
            return new ConcreteProductB();
        }
    }
    

2. 原型模式(Prototype Pattern) vs 建造者模式(Builder Pattern)

原型模式

  • 描述:允许复制现有的对象而不是重新创建新的对象,这可以提高效率。
  • 核心:通过克隆现有的对象来创建新的对象。
  • 应用场景:对象创建成本较高,且对象之间只有少量差异时。
  • 示例
    interface Prototype {
        Prototype clone();
    }
    
    class ConcretePrototype implements Prototype {
        private String id;
    
        public ConcretePrototype(String id) {
            this.id = id;
        }
    
        @Override
        public Prototype clone() {
            return new ConcretePrototype(this.id);
        }
    
        public String getId() {
            return id;
        }
    }
    

建造者模式

  • 描述:允许逐步构建复杂的对象,直到最终构建完成。
  • 核心:通过一步步设置对象的属性来构建对象。
  • 应用场景:创建复杂的对象,特别是对象的构建过程需要多个步骤或参数。
  • 示例
    class Product {
        private String partA;
        private String partB;
    
        public void setPartA(String partA) {
            this.partA = partA;
        }
    
        public void setPartB(String partB) {
            this.partB = partB;
        }
    }
    
    interface Builder {
        void buildPartA();
        void buildPartB();
        Product getResult();
    }
    
    class ConcreteBuilder implements Builder {
        private Product product = new Product();
    
        @Override
        public void buildPartA() {
            product.setPartA("Part A");
        }
    
        @Override
        public void buildPartB() {
            product.setPartB("Part B");
        }
    
        @Override
        public Product getResult() {
            return product;
        }
    }
    
    class Director {
        private Builder builder;
    
        public Director(Builder builder) {
            this.builder = builder;
        }
    
        public void construct() {
            builder.buildPartA();
            builder.buildPartB();
        }
    }
    

3. 装饰器模式(Decorator Pattern) vs 代理模式(Proxy Pattern)

装饰器模式

  • 描述:允许动态地给对象添加新的功能。
  • 核心:通过包装对象来增加新的行为,而不改变原有的接口。
  • 应用场景:需要在不修改对象的前提下增加额外的功能。
  • 示例
    abstract class Component {
        public abstract void operation();
    }
    
    class ConcreteComponent extends Component {
        @Override
        public void operation() {
            System.out.println("Operation in ConcreteComponent");
        }
    }
    
    abstract class Decorator extends Component {
        protected Component component;
    
        public Decorator(Component component) {
            this.component = component;
        }
    
        @Override
        public void operation() {
            component.operation();
        }
    }
    
    class ConcreteDecorator extends Decorator {
        public ConcreteDecorator(Component component) {
            super(component);
        }
    
        @Override
        public void operation() {
            super.operation();
            addedBehavior();
        }
    
        private void addedBehavior() {
            System.out.println("Added behavior from ConcreteDecorator");
        }
    }
    

代理模式

  • 描述:为其他对象提供一种代理以控制对这个对象的访问。
  • 核心:通过代理对象来间接访问目标对象,可以在访问前后添加额外的操作。
  • 应用场景:延迟初始化、权限控制、远程代理等。
  • 示例
    interface Subject {
        void request();
    }
    
    class RealSubject implements Subject {
        @Override
        public void request() {
            System.out.println("Request handled by RealSubject");
        }
    }
    
    class Proxy implements Subject {
        private RealSubject realSubject;
    
        @Override
        public void request() {
            if (realSubject == null) {
                realSubject = new RealSubject();
            }
            realSubject.request();
        }
    }
    

4. 策略模式(Strategy Pattern) vs 状态模式(State Pattern)

策略模式

  • 描述:定义了一系列可互换的算法,并将它们封装起来。
  • 核心:不同的算法实现同一个接口,客户端可以根据需要选择不同的算法。
  • 应用场景:需要在运行时动态选择算法时。
  • 示例
    interface Strategy {
        void algorithmInterface();
    }
    
    class ConcreteStrategyA implements Strategy {
        @Override
        public void algorithmInterface() {
            System.out.println("Algorithm A");
        }
    }
    
    class ConcreteStrategyB implements Strategy {
        @Override
        public void algorithmInterface() {
            System.out.println("Algorithm B");
        }
    }
    
    class Context {
        private Strategy strategy;
    
        public Context(Strategy strategy) {
            this.strategy = strategy;
        }
    
        public void contextInterface() {
            strategy.algorithmInterface();
        }
    }
    

状态模式

  • 描述:允许一个对象在其内部状态改变时改变其行为,看起来像是改变了其类。
  • 核心:通过不同的状态对象来表示不同的状态,并且状态对象之间可以互相切换。
  • 应用场景:对象的行为依赖于其内部状态,并且需要在运行时根据状态改变行为。
  • 示例
    interface State {
        void handle(Context context);
    }
    
    class ConcreteStateA implements State {
        @Override
        public void handle(Context context) {
            System.out.println("Handling with ConcreteStateA");
            context.setState(new ConcreteStateB());
        }
    }
    
    class ConcreteStateB implements State {
        @Override
        public void handle(Context context) {
            System.out.println("Handling with ConcreteStateB");
            context.setState(new ConcreteStateA());
        }
    }
    
    class Context {
        private State state;
    
        public Context(State state) {
            this.state = state;
        }
    
        public void setState(State state) {
            this.state = state;
        }
    
        public void request() {
            state.handle(this);
        }
    }
    

5. 观察者模式(Observer Pattern) vs 发布-订阅模式(Publish-Subscribe Pattern)

观察者模式

  • 描述:定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。
  • 核心:一个主题对象和多个观察者对象,主题对象负责通知观察者对象。
  • 应用场景:事件驱动系统、消息订阅系统等。
  • 示例
    import java.util.ArrayList;
    import java.util.List;
    
    interface Observer {
        void update(String message);
    }
    
    interface Subject {
        void attach(Observer observer);
        void detach(Observer observer);
        void notifyObservers(String message);
    }
    
    class ConcreteSubject implements Subject {
        private List<Observer> observers = new ArrayList<>();
    
        @Override
        public void attach(Observer observer) {
            observers.add(observer);
        }
    
        @Override
        public void detach(Observer observer) {
            observers.remove(observer);
        }
    
        @Override
        public void notifyObservers(String message) {
            for (Observer observer : observers) {
                observer.update(message);
            }
        }
    }
    
    class ConcreteObserver implements Observer {
        @Override
        public void update(String message) {
            System.out.println("Received: " + message);
        }
    }
    

发布-订阅模式

  • 描述:类似于观察者模式,但更强调消息的发布和订阅机制,通常通过中间件(如消息队列)来解耦发布者和订阅者。
  • 核心:发布者发布消息到消息队列,订阅者从消息队列中订阅消息。
  • 应用场景:分布式系统中的消息传递、事件通知等。
  • 示例
    import java.util.ArrayList;
    import java.util.List;
    
    interface Subscriber {
        void receive(String message);
    }
    
    interface Publisher {
        void subscribe(Subscriber subscriber);
        void unsubscribe(Subscriber subscriber);
        void publish(String message);
    }
    
    class MessageQueue implements Publisher {
        private List<Subscriber> subscribers = new ArrayList<>();
    
        @Override
        public void subscribe(Subscriber subscriber) {
            subscribers.add(subscriber);
        }
    
        @Override
        public void unsubscribe(Subscriber subscriber) {
            subscribers.remove(subscriber);
        }
    
        @Override
        public void publish(String message) {
            for (Subscriber subscriber : subscribers) {
                subscriber.receive(message);
            }
        }
    }
    
    class EmailSubscriber implements Subscriber {
        @Override
        public void receive(String message) {
            System.out.println("Email received: " + message);
        }
    }
    
    class SMSSubscriber implements Subscriber {
        @Override
        public void receive(String message) {
            System.out.println("SMS received: " + message);
        }
    }
    

这些设计模式虽然在某些方面有相似之处,但它们的核心思想和应用场景有所不同。理解这些差异有助于在实际开发中选择合适的设计模式。希望这些解释对你有所帮助!如果有任何具体的问题或需要进一步的解释,请随时提问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

问道飞鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值