设计模式

2 阅读6分钟

一、总览

image.png

image.png

二、设计的七大原则

2.1 开闭原则

扩展新类而不是修改旧类

2.2 里氏替换原则

继承父类而不去改变父类(继承必须确保超类所拥有的性质在子类中仍然成立,就是要修改父类留给子类的方法,而不是修改覆写父类的方法)

2.3 依赖倒置原则

面向接口编程,而不是面向实现类(写代码时候应该是面向他的接口层去编写,而不去关注具体的实现细节)

2.4 单一职责原则

每个类只负责自己的事情,而不是变成万能

2.5 接口隔离原则

各个类建立自己的专用接口,而不是建立万能接口(A、B两个类应该订一属于各自的接口提供对外实现,而不是把A和B的所有接口放在一个类里面)

2.6 迪米特法则

最少知识原则(无需直接交互的两个类,如果需要交互,使用中间者。例:A依赖B、C、D、E的功能,把B、C、D、E都放在了A里面)

过度使用迪米特法则会使系统产生大量的中介类,从而增加系统的复杂性,使模块之间的通信效率降低

2.7 合成复用原则

优先组合,其次继承(A有两个方法,B有10个,A要用B的方法则直接在A中添加一个属性就是B即可,而不是继承B)

又叫组合/聚合复用原则(Composition/Aggregate Reuse Principle,CARP) 软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现

三、24种模式

3.1 创建型模式

关注“怎样创建出对象?”“将对象的创建与使用分离”。降低系统的耦合度

  • 对象的创建由相关的工厂来完成;(各种工厂模式)
  • 对象的创建由一个建造者来完成;(建造者模式)
  • 对象的创建由原来对象克隆完成;(原型模式)
  • 对象始终在系统中只有一个实例;(单例模式)

3.1.1 单例模式

一个单一的类,负责创建自己的对象,同时确保系统中只有单个对象被创建

  • 什么场景用到?
  1. 多线程中的线程池
  2. 数据库的连接池
  3. 系统环境信息
  4. 上下文(ServletContext)
  5. ......

懒汉式代码

public class Person {
    private String name;
    private String age;

    //懒汉、饿汉
    private volatile static Person instance;  

    //构造器私有,外部不能实例化
    private Person() {
        System.out.println("创建了Person");
    }


    //提供给外部的方法
    //1、public static synchronized Person guiguBoss() 锁太大
    //2、双重检查锁+内存可见性(设计模式)
    public static Person guiguBoss() {
        //如果没有再去创建
        if (instance == null) {
            synchronized (Person.class) {
                if(instance == null){
                    Person person = new Person();
                    //多线程问题
                    instance = person;
                }
            }
        }
        return instance;
    }

}

3.1.2 原型(Prototype)模式

  • 原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。
  • 本体给外部提供一个克隆体进行使用

3.1.3 工厂模式

对象的使用工厂来创建。

工厂模式(Factory Pattern)提供了一种创建对象的最佳方式。我们不必关心对象的创建细节,只需要根据不同情况获取不同产品即可

image.png

3.1.3.1 简单工厂模式

image.png

1、工厂的抽象产品

/**
 * 工厂的产品
 */
public abstract class AbstractCar {

    String engine;
    public abstract void run();
}

2、要造的最终产品

public class MiniCar extends AbstractCar{

    public MiniCar(){
        this.engine = "四缸水平对置发动机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--> 嘟嘟嘟...");
    }
}
/**
 * 具体产品
 */
public class VanCar extends AbstractCar{
    public VanCar(){
        this.engine = "单杠柴油机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--》嗒嗒嗒....");
    }
}

3、使用工场创建

/**
 * 简单工厂
 * 1、产品数量极少
 */
public class WuLinSimpleFactory {


    public AbstractCar newCar(String type){

        //核心方法:一切从简
        if("van".equals(type)){
            return new VanCar();
        }else if("mini".equals(type)){
            return new MiniCar();
        }

        //.....

        //更多的产品,违反开闭原则。应该直接扩展出一个类来造
        return null;
    }
}
public class MainTest {

    public static void main(String[] args) {

        WuLinSimpleFactory factory = new WuLinSimpleFactory();

        AbstractCar van = factory.newCar("van");
        AbstractCar mini = factory.newCar("mini");
        AbstractCar zz = factory.newCar("zz");
        van.run();
        mini.run();

    }
}
3.1.3.2 工厂方法模式

简单工厂模式违反开闭原则,新加一个则需要修改工厂类。那么可以把工厂进行抽象。

image.png

1、要造的抽象产品

/**
 * 工厂的产品
 *
 * 怎么把一个功能提升一个层次:定义抽象(抽象类,接口)
 * 抽象类,接口  就会有多实现,多实现自然就有多功能
 */
public abstract class AbstractCar {

    String engine;
    public abstract void run();
}

2、具体产品

public class MiniCar extends AbstractCar {

    public MiniCar(){
        this.engine = "四缸水平对置发动机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--> 嘟嘟嘟...");
    }
}
/**
 * 具体产品
 */
public class VanCar extends AbstractCar {
    public VanCar(){
        this.engine = "单杠柴油机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--》嗒嗒嗒....");
    }
}

3、工厂

/**
 * 抽象工厂的层级
 */
public abstract class AbstractCarFactory {

    public abstract AbstractCar newCar();

}
/**
 * minicar分厂
 */
public class WulinMinCarFactory extends AbstractCarFactory{
    @Override
    public AbstractCar newCar() {
        return new MiniCar();
    }
}
public class WulinVanCarFactory extends AbstractCarFactory {
    @Override
    public AbstractCar newCar() {
        return new VanCar();
    }
}

4、测试

直接扩展抽象工厂类即可。但是产品单一,因此可以再把AbstractCarFactory上一层进行抽象

public class MainTest {

    public static void main(String[] args) {
        AbstractCarFactory carFactory = new WulinMinCarFactory();
        AbstractCar abstractCar = carFactory.newCar();
        abstractCar.run();


        carFactory = new WulinVanCarFactory();
        AbstractCar abstractCar1 = carFactory.newCar();

        abstractCar1.run();
    }
}
3.1.3.3 抽象工厂

image.png

1、造的产品

产品1

/**
 * 工厂的产品
 *
 * 怎么把一个功能提升一个层次:定义抽象(抽象类,接口)
 * 抽象类,接口  就会有多实现,多实现自然就有多功能
 */
public abstract class AbstractCar {

    String engine;
    public abstract void run();
}
/**
 * 具体产品
 */
public class VanCar extends AbstractCar {
    public VanCar(){
        this.engine = "单杠柴油机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--》嗒嗒嗒....");
    }
}
public class RacingCar extends AbstractCar {

    public RacingCar(){
        this.engine = "v8发动机";
    }
    @Override
    public void run() {
        System.out.println(engine+"=--嗖.....");
    }
}

产品2

/**
 * 抽象产品
 */
public abstract class AbstractMask {

    Integer price;
    public abstract void protectedMe();
}
public class N95Mask  extends AbstractMask{
    public N95Mask(){
        this.price = 2;
    }

    @Override
    public void protectedMe() {
        System.out.println("N95口罩....超级防护");
    }
}
public class CommonMask  extends AbstractMask{
    public CommonMask(){
        price = 1;
    }
    @Override
    public void protectedMe() {
        System.out.println("普通口罩....简单保护...请及时更换");
    }
}

2、工厂

集团总厂,定义可以建造的对象种类。可以造车造口罩

* 总厂规范:
 * Wulin集团
 *
 * 使用接口;
 */
public abstract class WulinFactory {

    abstract AbstractCar newCar();
    abstract AbstractMask newMask();
}

车总厂

/**
 * wulin 汽车集团
 */
public  abstract  class WulinCarFactory extends WulinFactory{
    @Override
    abstract  AbstractCar newCar();

    // 不要子类实现
    @Override 
    AbstractMask newMask() {
        return null;
    }
}

口罩总厂

/**
 * wulin口罩集团
 */
public abstract class WulinMaskFactory extends WulinFactory{
    @Override
    AbstractCar newCar() {
        return null;
    }


    abstract AbstractMask newMask();
}

具体的厂1

/**
 * 普通口罩
 */
public class WulinHangZhouMaskFactory extends WulinMaskFactory {

    @Override
    AbstractMask newMask() {
        return new CommonMask();
    }
}
/**
 * 分厂:N95口罩
 */
public class WulinWuHanMaskFactory  extends WulinMaskFactory{

    @Override
    AbstractMask newMask() {
        return new N95Mask();
    }
}

具体的产2

public class WulinVanCarFactory extends WulinCarFactory{
    @Override
    AbstractCar newCar() {
        return new VanCar();
    }

}
public class WulinRacingCarFactory extends WulinCarFactory {
    @Override
    AbstractCar newCar() {
        return new RacingCar();
    }
}

3、测试

/**
 * 抽象出来。
 *      可以抽象成接口(只有方法),可以抽象成抽象类(有些属性也需要用)
 */
public class MainTest {

    public static void main(String[] args) {

        WulinFactory wulinFactory = new WulinWuHanMaskFactory();

        AbstractMask abstractMask = wulinFactory.newMask();
        abstractMask.protectedMe();


        wulinFactory = new WulinHangZhouMaskFactory();
        AbstractMask abstractMask1 = wulinFactory.newMask();
        abstractMask1.protectedMe();
    }
}