博客
关于我
【硬核】23种设计模式娓娓道来,助你优雅的编写出漂亮代码!
阅读量:450 次
发布时间:2019-03-06

本文共 11208 字,大约阅读时间需要 37 分钟。

设计模式入门

引言

在软件开发中,设计模式就像是一把精准的工具包,可以帮助我们应对常见的设计挑战。通过学习和理解这些模式,我们能够写出更规范、更高效的代码,同时在面试中也能成为一道亮眼的选手。

设计模式分类

设计模式主要分为三大类:

1. 创建型模式

这些模式关注对象的创建过程,主要包括:

  • 工厂方法模式:通过工厂来统一创建产品,延迟对象的创建。
  • 抽象工厂模式:创建一组相关对象,提供统一的接口。
  • 单例模式:确保一个类只有一个实例。
  • 建造者模式:将对象的构建过程与其表示分离。
  • 原型模式:通过拷贝现有对象来创建新对象,节省资源。

2. 结构型模式

这些模式关注对象的结构,主要包括:

  • 适配器模式:将一个类的接口转换为另一个类的接口。
  • 装饰模式:动态地给一个对象添加额外职责。
  • 代理模式:为一个对象提供一个替代对象,以控制其访问。
  • 迭代器模式:提供一种方法访问一个容器对象中的各个元素。
  • 组合模式:将对象组合成树形结构,表示“部分-整体”关系。

3. 行为型模式

这些模式关注对象的行为,主要包括:

  • 策略模式:定义一组算法,允许动态切换。
  • 模板方法模式:定义一个操作的框架,子类可以重定义部分逻辑。
  • 观察者模式:定义对象间的一对多依赖关系。
  • 责任链模式:使多个对象都有机会处理请求。
  • 命令模式:将请求封装成一个对象,便于管理和撤销。
  • 备忘录模式:在不破坏封装性的前提下,捕获对象的内部状态。
  • 访问者模式:封装作用于某种数据结构中的各元素的操作。
  • 状态模式:让一个对象的行为改变,类似于状态的变化。
  • 解释器模式:定义一种语言的文法,并定义一个解释器。
  • 中介者模式:用一个中介对象封装一系列对象交互。

单例模式

概念

确保某一个类只有一个实例,并通过自行实例化向系统提供该实例。

使用场景

  • 需要生成唯一序列号的环境。
  • 在多线程环境下需要一个共享访问点或共享数据。
  • 创建一个对象需要消耗大量资源。
  • 定义大量静态常量和静态方法的环境。

代码示例

public class Singleton {    private static final Singleton singleton = new Singleton();    private Singleton() {}    public static Singleton getSingleton() {        return singleton;    }    public static void doSomething() {}}

工厂模式

概念

定义一个用于创建对象的接口,让子类决定实例化哪一个类。

使用场景

  • jdbc 连接数据库
  • 硬件访问
  • 需要降低对象的产生和销毁成本

结构

  • 简单工厂模式:一个工厂类,通过静态方法创建对象。
  • 多个工厂类:每个工厂负责创建对应的产品。
  • 代替单例模式:通过工厂方法模式创建单一实例。
  • 延迟初始化:通过工厂缓存创建的对象。

代码示例

public abstract class Creator {    public abstract 
T createProduct(Class
clazz);}

抽象工厂模式

概念

为创建一组相关或相互依赖的对象提供一个接口,不需要指定具体类。

使用场景

  • 不同操作系统的设备管理
  • 需要一组相关对象的创建

代码示例

public abstract class AbstractCreator {    public abstract AbstractProductA createProductA();    public abstract AbstractProductB createProductB();}

模板方法模式

概念

定义一个操作的框架,子类可以重定义部分逻辑。

使用场景

  • 多个子类有公有的方法,逻辑基本相似
  • 需要重构时,抽取相同代码到父类中

结构

  • 抽象模板:提供基本操作和模板方法
  • 具体模板:实现父类定义的抽象方法

代码示例

public abstract class AbstractClass {    public abstract void TemplateMethod();    public void SpecificMethod() {        System.out.println("抽象类中的具体方法被调用...");    }}

建造者模式

概念

将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。

使用场景

  • 不同的构建顺序产生不同的结果
  • 产品类非常复杂,构建顺序影响最终结果

结构

  • Product 产品类:实现模板方法模式
  • Builder 抽象建造者:规范产品组建
  • ConcreteBuilder 具体建造者:实现抽象类方法并返回对象
  • Director 导演类:安排已有模块的顺序

代码示例

public class ConcreteProduct extends Builder {    private Product product = new Product();    public void setPart() {}    public Product buildProduct() {        return product;    }}

代理模式

概念

为其他对象提供一种代理,以控制对该对象的访问。

结构

  • Subject 被观察者:定义被观察者的接口
  • RealSubject 具体主题:实现业务逻辑
  • Proxy 代理主题:控制对真实主题的访问

分类

  • 普通代理:调用者知道代理的存在
  • 强制代理:调用者不知道代理的存在
  • 动态代理:根据接口生成代理

代码示例

public class Client {    private A a = new A();    public void methodA() {        a.doSomething();    }}

原型模式

概念

用原型实例指定创建对象的种类,并通过拷贝这些原型创建新对象。

使用场景

  • 资源消耗较高的对象创建
  • 需要多个修改者访问相同对象

优点

  • 性能优良:内存拷贝比直接new性能好
  • 逃避构造函数约束:构造函数不执行

代码示例

public class PrototypeClass implements Cloneable {    @Override    public PrototypeClass clone() {        try {            return (PrototypeClass) super.clone();        } catch (CloneNotSupportedException e) {            throw new RuntimeException(e);        }    }}

中介者模式

概念

用一个中介对象封装一系列对象交互,使对象耦合松散。

使用场景

  • 对多个对象之间交互耦合较大的系统

结构

  • Mediator 抽象中介者:定义通信接口
  • ConcreteMediator 具体中介者:实现中介者的逻辑
  • Colleague 同事角色:知道中介者,并通过它通信

代码示例

public abstract class Mediator {    protected ConcreteColleague1 c1;    protected ConcreteColleague2 c2;    public abstract void doSomething1();    public abstract void doSomething2();}

命令模式

概念

将请求封装成一个对象,便于管理和撤销。

使用场景

  • GUI 开发中的按钮点击
  • 模拟 DOS 命令
  • 触发-反馈机制

结构

  • Receiver 接收者:执行命令的角色
  • Command 命令角色:封装请求
  • Invoker 调用者:执行命令

代码示例

public class Invoker {    private Command command;    public void setCommand(Command command) {        this.command = command;    }    public void action() {        this.command.execute();    }}

责任链模式

概念

使多个对象都有机会处理请求,避免耦合。

结构

  • Handler 抽象处理者:定义处理方法
  • ConcreteHandler 具体处理者:实现抽象方法
  • Director 导演类:设置处理链

代码示例

public abstract class Handler {    private Handler nextHandler;    public Response handleMessage(Request request) {        if (this.getHandlerLevel().equals(request.getRequestLevel())) {            return this.echo(request);        } else {            if (this.nextHandler != null) {                return this.nextHandler.handleMessage(request);            } else {                // 没有适当的处理者            }        }        return response;    }    public void setNext(Handler _handler) {        this.nextHandler = _handler;    }    protected abstract Level getHandlerLevel();    protected abstract Response echo(Request request);}

装饰模式

概念

动态地给一个对象添加额外职责。

使用场景

  • 扩展一个类的功能
  • 动态地给一个对象增加功能
  • 对一批兄弟类进行改装或加装

结构

  • Component 抽象构件:定义基本接口
  • ConcreteComponent 具体构件:实现抽象接口
  • Decorator 装饰角色:增加额外职责
  • ConcreteDecorator 具体装饰角色:实现额外职责

代码示例

public class BufferedReader implements Reader {    private Reader reader;    public void readLine() {        read();        System.out.println("并且仅仅读取一行");    }}

策略模式

概念

定义一组算法,允许动态切换算法。

使用场景

  • 算法需要自由切换
  • 屏蔽算法规则
  • 算法数量较多

结构

  • Context 封装角色:提供算法切换接口
  • Strategy 抽象策略:定义算法接口
  • ConcreteStrategy 具体策略:实现抽象方法

代码示例

public enum Calculator {    ADD("+") {        public int exec(int a, int b) {            return a + b;        }    }, SUB("-") {        public int exec(int a, int b) {            return a - b;        }    };    String value;    private Calculator(String _value) {        this.value = _value;    }    public String getValue() {        return this.value;    }    public abstract int exec(int a, int b);}

适配器模式

概念

将一个类的接口转换为另一个类的接口。

使用场景

  • 接口不匹配
  • 系统扩展需要使用新类

结构

  • Target 目标角色:定义期望接口
  • Adaptee 源角色:被适配的类
  • Adapter 适配器角色:实现转换

代码示例

public class Adapter extends Target {    private Adaptee adaptee;    public Adapter(Adaptee adaptee) {        this.adaptee = adaptee;    }    public void request() {        adaptee.specificRequest();    }}

迭代器模式

概念

提供一种方法访问容器对象中的各个元素。

结构

  • Iterator 抽象迭代器:定义访问方法
  • ConcreteIterator 具体迭代器:实现抽象接口
  • Aggregate 抽象容器:提供创建迭代器的方法
  • ConcreteAggregate 具体容器:实现容器接口

代码示例

public class ConcreteIterator implements Iterator {    private List list = new ArrayList();    private int cursor = 0;    public boolean hasNext() {        return cursor != list.size();    }    public Object next() {        Object obj = null;        if (this.hasNext()) {            obj = this.list.get(cursor++);        }        return obj;    }}

组合模式

概念

将对象组合成树形结构,表示“部分-整体”关系。

使用场景

  • 树形菜单
  • 文件和文件夹管理

结构

  • Component 抽象构件:定义基本接口
  • Leaf 叶子构件:没有子节点的叶子对象
  • Composite 树枝构件:组合构件形成树形结构

代码示例

public class Composite extends Component {    private List componentArrayList = new ArrayList();    public void add(Component component) {        this.componentArrayList.add(component);    }    public void remove(Component component) {        this.componentArrayList.remove(component);    }    public List getChildren() {        return this.componentArrayList;    }}

观察者模式

概念

定义对象间的一对多依赖关系,自动通知依赖对象。

使用场景

  • 关联行为场景
  • 事件多级触发
  • 跨系统消息交换

结构

  • Subject 被观察者:管理观察者并通知
  • Observer 观察者:接收消息并更新
  • ConcreteSubject 具体被观察者:实现业务逻辑
  • ConcreteObserver 具体观察者:实现更新逻辑

代码示例

public abstract class Subject {    private Vector obsVector = new Vector();    public void addObserver(Observer o) {        this.obsVector.add(o);    }    public void delObserver(Observer o) {        this.obsVector.remove(o);    }    public void notifyObservers() {        for (Observer o : this.obsVector) {            o.update();        }    }}

门面模式

概念

为一个子系统提供一个统一的接口,屏蔽内部细节。

使用场景

  • 子系统独立
  • 外界对子系统的访问仅限于黑箱操作
  • 预防低水平人员带来的风险

结构

  • Facade 门面角色:委派子系统方法
  • subsystem 子系统角色:独立运行的模块

代码示例

public class Client {    private A a = new A();    private B b = new B();    private C c = new C();    public void methodA() {        a.doSomething();    }    public void methodB() {        b.doSomething();    }    public void methodC() {        c.doSomething();    }}

备忘录模式

概念

在不破坏封装性的前提下,捕获对象的内部状态。

使用场景

  • 需要保存和恢复数据的状态
  • 提供可回滚操作
  • 数据库连接的事务管理

结构

  • Originator 发起人角色:记录内部状态
  • Memento 备忘录角色:存储发起人状态
  • Caretaker 备忘录管理员:管理备忘录

代码示例

public class BeanUtils {    public static HashMap backupProp(Object bean) {        HashMap result = new HashMap();        try {            BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());            PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();            for (PropertyDescriptor des : descriptors) {                String fieldName = des.getName();                if (!fieldName.equalsIgnoreCase("class")) {                    Method getter = des.getReadMethod();                    Object fieldValue = getter.invoke(bean, new Object[] {});                    result.put(fieldName, fieldValue);                }            }        } catch (Exception e) {            // 异常处理        }        return result;    }    public static void restoreProp(Object bean, HashMap propMap) {        try {            BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());            PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();            for (PropertyDescriptor des : descriptors) {                String fieldName = des.getName();                if (propMap.containsKey(fieldName)) {                    Method setter = des.getWriteMethod();                    setter.invoke(bean, new Object[]{propMap.get(fieldName)});                }            }        } catch (Exception e) {            // 异常处理        }    }}

访问者模式

概念

封装作用于数据结构中的各元素的操作。

使用场景

  • 对数据结构中的对象进行多种操作
  • 避免操作耦合

结构

  • Visitor 抽象访问者:定义访问元素的方法
  • ConcreteVisitor 具体访问者:实现访问方法
  • Element 抽象元素:接受访问者的方法
  • ConcreteElement 具体元素:实现 accept 方法

代码示例

public class CompensationVisitor implements Visitor {    @Override    public void Visit(Employee element) {        System.out.println("'s Compensation is " + (element.getDegree() * element.getVacationDays() * 10));    }}

状态模式

概念

当一个对象的内在状态改变时,允许其行为改变,类似于改变了其类。

使用场景

  • 行为随状态改变而改变的场景
  • 条件判断语句的替代

结构

  • State 抽象状态角色:定义状态接口
  • ConcreteState 具体状态角色:实现状态行为
  • Context 环境角色:管理状态切换

代码示例

public abstract class State {    protected Context context;    public void setContext(Context _context) {        this.context = _context;    }    public abstract void handle1();    public abstract void handle2();}

解释器模式

概念

给定一门语言,定义其文法,并定义一个解释器来解释语言句子。

使用场景

  • 简单语法解释
  • 重复出现的问题

结构

  • AbstractExpression 抽象解释器:定义解释任务
  • TerminalExpression 终结符表达式:实现文法元素操作
  • NonterminalExpression 非终结符表达式:实现文法规则
  • Context 环境角色:管理解释器

代码示例

public class TerminalExpression extends AbstractExpression {    @Override    public void interpret(Context ctx) {        // 实现与语法规则中的终结符相关联的解释操作    }}public class NonterminalExpression extends AbstractExpression {    @Override    public void interpret(Context ctx) {        // 实现与语法规则中的非终结符相关联的解释操作    }}

享元模式

概念

通过共享对象来有效支持大量的细粒度对象。

使用场景

  • 系统中存在大量相似对象
  • 对象的信息可以分为内部状态和外部状态

结构

  • Flyweight 抽象享元角色:定义外部状态和内部状态的接口
  • ConcreteFlyweight 具体享元角色:实现抽象角色的业务逻辑
  • FlyweightFactory 享元工厂:管理享元对象池

代码示例

public class FlyweightFactory {    private static HashMap
pool = new HashMap<>(); public static Flyweight getFlyweight(String extrinsic) { Flyweight flyweight = pool.get(extrinsic); if (flyweight == null) { flyweight = new ConcreteFlyweight1(extrinsic); pool.put(extrinsic, flyweight); } return flyweight; }}

桥梁模式

概念

将抽象和实现解耦,使其能够独立变化。

使用场景

  • 不希望使用继承的场景
  • 接口或抽象类不稳定的场景
  • 需要高重用性的场景

结构

  • Abstraction 抽象化角色:定义抽象行为并引用实现化角色
  • Implementor 实现化角色:实现抽象角色的接口
  • RefinedAbstraction 修正抽象化角色:引用实现化角色进行修正
  • ConcreteImplementor 具体实现化角色:实现接口或抽象类方法

代码示例

public abstract class Abstraction {    private Implementor imp;    public Abstraction(Implementor _imp) {        this.imp = _imp;    }    public void request() {        this.imp.doSomething();    }    public Implementor getImp() {        return imp;    }}

总结

设计模式是前人总结的经验宝库,它们为我们提供了一套解决常见问题的标准方案。通过不断学习和实践这些模式,我们能够写出更规范、更高效的代码,同时在面试中也能展现出专业的知识。

转载地址:http://vwbfz.baihongyu.com/

你可能感兴趣的文章
No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
查看>>
no connection could be made because the target machine actively refused it.问题解决
查看>>
No Datastore Session bound to thread, and configuration does not allow creation of non-transactional
查看>>
No fallbackFactory instance of type class com.ruoyi---SpringCloud Alibaba_若依微服务框架改造---工作笔记005
查看>>
No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalanc
查看>>
No mapping found for HTTP request with URI [/...] in DispatcherServlet with name ...的解决方法
查看>>
No mapping found for HTTP request with URI [/logout.do] in DispatcherServlet with name 'springmvc'
查看>>
No module named 'crispy_forms'等使用pycharm开发
查看>>
No module named cv2
查看>>
No module named tensorboard.main在安装tensorboardX的时候遇到的问题
查看>>
No module named ‘MySQLdb‘错误解决No module named ‘MySQLdb‘错误解决
查看>>
No new migrations found. Your system is up-to-date.
查看>>
No qualifying bean of type XXX found for dependency XXX.
查看>>
No qualifying bean of type ‘com.netflix.discovery.AbstractDiscoveryClientOptionalArgs<?>‘ available
查看>>
No resource identifier found for attribute 'srcCompat' in package的解决办法
查看>>
no session found for current thread
查看>>
No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
查看>>
NO.23 ZenTaoPHP目录结构
查看>>
no1
查看>>
NO32 网络层次及OSI7层模型--TCP三次握手四次断开--子网划分
查看>>