设计模式

1,什么是设计模式:(GoF23)

设计模式是前辈们对代码开发经验的总结,是解决一系列问题特定的套路,是一套用来提高代码可复用性,可维护性,可读性,稳健性以及安全性的解决方案。

  • 创建型模式(如何创建一个对象,让对象的创建和使用分离)
    单例模式,工厂模式,抽象工厂模式,建造模式,原型模式

  • 结构型模式(将类和对象按照某种布局组成更大的结构)
    适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式

  • 行为型模式(描述类和对象之间如何相互协作)
    模板方法模式,命令模式,迭代器模式,观察者模式,中介者模式,备忘录模式,解释器模式,状态模式,策略模式,职责链模式,访问者模式

2,面向对象(oop)七大原则

  • 开闭原则:对扩展开放,对修改关闭

  • 里氏替换原则:继承必须确保父类所拥有的性质在子类中仍然成立

  • 依赖倒置原则:要面向接口编程,不要面向实现编程

  • 单一职责原则:控制类的力度大小,将对象解耦,提高其内聚性(一个方法尽量只做一件事)

  • 接口隔离原则:要为个各类建立它们需要的专用接口

  • 迪米特原则:只与你的直接朋友交谈,不跟“陌生人”说话(Class:A->B->C)

  • 合成复用原则:先使用组合或者聚合等观看关系来实现,其次才考虑使用继承关系实现(is a,has a)

3,设计模式

1.单例模式

单例模式,一般用于比较大,复杂的对象,只初始化一次,应该还有一个private的构造函数,使得不能用new来实例化对象,只能调用getInstance方法来得到对象,而getInstance保证了每次调用都返回相同的对象。

  • 饿汉式
package com.kuan.single;

//饿汉式单例(一上来就加载)
public class Hungry {

    //可能会浪费空间
    private Byte[] data1=new Byte[1024*1024*1024];
    private Byte[] data2=new Byte[1024*1024*1024];
    private Byte[] data3=new Byte[1024*1024*1024];

    //构造器单有
    private Hungry(){

    }

    private static final Hungry HUNGRY=new Hungry();

    public static Hungry getInstance(){
        return HUNGRY;
    }
}

  • DCL懒汉式
package com.kuan.single;

import java.lang.reflect.Constructor;

//懒汉式单例
public class LazyMan {

    private static boolean light=false;

    //构造器私有
    private LazyMan(){
        synchronized (LazyMan.class){
            if(light==false){
                light=true;
            }else {
                throw new RuntimeException("不要试图使用反射破坏异常");
            }
        }
        System.out.println(Thread.currentThread().getName());
    }

    private volatile static LazyMan lazyMan;

    //双重检测锁的懒汉式单例+原子性操作,避免指令重排 DCL懒汉式
    public static LazyMan getInstance(){
        //LazyMan为空再去创建(懒汉式)
        if(lazyMan==null){
            synchronized (LazyMan.class) {
                if (lazyMan == null) {
                    lazyMan = new LazyMan();//不是一个原子性操作
                    /*
                    * 1,分配内存空间
                    * 2,执行构造方法,初始化对象
                    * 3,把这个对象只指向这个空间
                    *
                    * 指令重排
                    * 123
                    * 132
                    * */
                }
            }
        }
        return lazyMan;
    }

    //反射,破坏单例
    public static void main(String[] args) throws Exception {
//        LazyMan instance=LazyMan.getInstance();
        //获得构造器
        Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
        //无视私有构造器,破坏私有权限
        declaredConstructor.setAccessible(true);
        //通过反射创建对象
        LazyMan instance = declaredConstructor.newInstance();
        LazyMan instance2 = declaredConstructor.newInstance();

        //若instance1和instance2都通过newInstance创建,单例模式又被破坏(红绿灯)

        System.out.println(instance);
        System.out.println(instance2);

    }
}

  • 静态内部类
package com.kuan.single;

//静态内部类单例
public class Holder {

    private Holder(){

    }

    public static Holder getInstance(){
        return InnerClass.HOLDER;
    }

    public static class InnerClass{
        private static final Holder HOLDER=new Holder();
    }
}

  • 以上单例不安全,因为有反射
  • 枚举 enum
package com.kuan.single;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

// enum本身也是一个class
public enum  EnumSingle {

    INSTANCE;

    public EnumSingle getInstance(){
        return INSTANCE;
    }
}

class Test{

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        EnumSingle instance1 = EnumSingle.INSTANCE;
        Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
        declaredConstructor.setAccessible(true);
        EnumSingle instance2 = declaredConstructor.newInstance();

        System.out.println(instance1);
        System.out.println(instance2);
    }
}

枚举类型的最终反编译源码构造器:有参构造(String.class,int.class)!

2.工厂模式

作用:实现了创建者和调用者分离,满足开闭原则,依赖倒转原则,迪米特法则

核心本质:
1.实例化对象不使用new,用工厂方法代替,
2.将选择实现类,创建对象同意管理和控制,将调用者和实现类解耦

  • 简单工厂模式(新增产品,需要扩展已有代码)

image

创建car接口

package com.kuan.factory.simple;

public interface Car {
    void name();
}

创建CarFactory工厂

package com.kuan.factory.methodfactory;

//工厂方法模式
public interface CarFactory {
    Car getCar();
}

Car对象

package com.kuan.factory.simple;

public class TesiLa implements Car {
    @Override
    public void name() {
        System.out.println("特斯拉");
    }
}

package com.kuan.factory.simple;

public class WuLin implements Car {
    @Override
    public void name() {
        System.out.println("五菱");
    }
}

测试

package com.kuan.factory.simple;

public class Consumer {
    public static void main(String[] args) {
//        TesiLa tesiLa = new TesiLa();
//        WuLin wuLin = new WuLin();

        //使用工厂创建
        Car car = CarFactory.getCar("五菱");
        Car car1 = CarFactory.getCar("特斯拉");

        car.name();
        car1.name();
    }
}

  • 工厂方法模式

image

Car接口

package com.kuan.factory.methodfactory;

public interface Car {
    void name();
}

CarFactory接口

package com.kuan.factory.methodfactory;

//工厂方法模式
public interface CarFactory {
    Car getCar();
}

car对象

package com.kuan.factory.methodfactory;

public class TesiLa implements Car {
    @Override
    public void name() {
        System.out.println("特斯拉");
    }
}

car对象的Factory

package com.kuan.factory.methodfactory;

public class TesiLaFactory implements CarFactory {
    @Override
    public Car getCar() {
        return new TesiLa();
    }
}

car对象1

package com.kuan.factory.methodfactory;

public class WuLin implements Car {
    @Override
    public void name() {
        System.out.println("五菱");
    }
}

car对象Factory

package com.kuan.factory.methodfactory;

public class WuLinFactory implements CarFactory {
    @Override
    public Car getCar() {
        return new WuLin();
    }
}

测试

package com.kuan.factory.methodfactory;

public class Consumer {
    public static void main(String[] args) {
	//从对应的carFactory中拿到相应的car
        Car car = new WuLinFactory().getCar();
        Car car1 = new TesiLaFactory().getCar();

        Car car2 = new DaZhongFactory().getCar();

        car.name();
        car1.name();
        car2.name();
    }
}
  • 抽象工厂模式(围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂)

image

创建手机工厂接口

package com.kuan.factory.abstract1;
//手机接口
public interface IPhoneProduct {
    void star();
    void shutDown();
    void sendSms();
    void setting();
}

创建路由工厂接口

package com.kuan.factory.abstract1;
//路由接口
public interface IRouterProduct {
    void star();
    void shutDown();
    void openWifi();
    void setting();
}

小米手机实现

package com.kuan.factory.abstract1;
//小米手机
public class XiaomiPhone implements IPhoneProduct {
    @Override
    public void star() {
        System.out.println("开启小米手机");
    }

    @Override
    public void shutDown() {
        System.out.println("关闭小米手机");
    }

    @Override
    public void sendSms() {
        System.out.println("小米发短信");
    }

    @Override
    public void setting() {
        System.out.println("小米设置");
    }
}

小米路由实现

package com.kuan.factory.abstract1;
//小米路由器
public class XiaomiRouter implements IRouterProduct {
    @Override
    public void star() {
        System.out.println("开启小米路由器");
    }

    @Override
    public void shutDown() {
        System.out.println("关闭小米路由器");
    }

    @Override
    public void openWifi() {
        System.out.println("开启小米wifi");
    }

    @Override
    public void setting() {
        System.out.println("小米wifi设置");
    }
}

华为手机实现

package com.kuan.factory.abstract1;
//华为手机
public class HuaweiPhone implements IPhoneProduct {
    @Override
    public void star() {
        System.out.println("开启华为手机");
    }

    @Override
    public void shutDown() {
        System.out.println("关闭华为手机");
    }

    @Override
    public void sendSms() {
        System.out.println("华为手机发短信");
    }

    @Override
    public void setting() {
        System.out.println("华为手机设置");
    }
}

华为路由实现

package com.kuan.factory.abstract1;
//华为路由器
public class HuaweiRouter implements IRouterProduct {
    @Override
    public void star() {
        System.out.println("开启华为路由器");
    }

    @Override
    public void shutDown() {
        System.out.println("关闭华为路由器");
    }

    @Override
    public void openWifi() {
        System.out.println("开启华为wifi");
    }

    @Override
    public void setting() {
        System.out.println("华为wifi设置");
    }
}

创建抽象产品工厂(超级工厂)

package com.kuan.factory.abstract1;
//抽象产品工厂(超级工厂)
public interface IProductFactory {
    //生产手机
    IPhoneProduct iPhoneProduct();

    //生产路由器
    IRouterProduct iRouterProduct();
}

测试

package com.kuan.factory.abstract1;

public class Cilent {
    public static void main(String[] args) {

        System.out.println("=======小米系列产品========");
        //小米工厂
        XiaomiFactory xiaomiFactory = new XiaomiFactory();

        IPhoneProduct iPhoneProduct = xiaomiFactory.iPhoneProduct();
        iPhoneProduct.sendSms();
        iPhoneProduct.setting();

        IRouterProduct iRouterProduct = xiaomiFactory.iRouterProduct();
        iRouterProduct.openWifi();
        iRouterProduct.setting();

        System.out.println("=======华为系列产品========");
        //华为工厂
        HuaweiFactory huaweiFactory = new HuaweiFactory();

        IPhoneProduct iPhoneProduct1 = huaweiFactory.iPhoneProduct();
        iPhoneProduct1.sendSms();
        iPhoneProduct1.setting();

        IRouterProduct iRouterProduct1 = huaweiFactory.iRouterProduct();
        iRouterProduct1.openWifi();
        iRouterProduct1.setting();
    }
}

3.建造者模式

  • 常规的Builder模式,导演类Director在Builder模式中有重要作用,用于指导具体的构建者如何构建产品,控制调用先后次序,并向调用者返回完整的产品类,某些情况下需要简化系统结构,将Director和抽象建造者进行结合

image

创建抽象建造者

package com.kuan.factory.builder;

//抽象的建造者
public abstract class Builder {
    abstract void buildA();//地基
    abstract void buildB();//钢筋水泥
    abstract void buildC();//铺电线
    abstract void buildD();//粉刷

    //完工:得到产品
    abstract Product getProduct();
}

创建产品

package com.kuan.factory.builder;
//产品:房子
public class Product {

    private String buildA;
    private String buildB;
    private String buildC;
    private String buildD;


    public String getBuildA() {
        return buildA;
    }

    public void setBuildA(String buildA) {
        this.buildA = buildA;
    }

    public String getBuildB() {
        return buildB;
    }

    public void setBuildB(String buildB) {
        this.buildB = buildB;
    }

    public String getBuildC() {
        return buildC;
    }

    public void setBuildC(String buildC) {
        this.buildC = buildC;
    }

    public String getBuildD() {
        return buildD;
    }

    public void setBuildD(String buildD) {
        this.buildD = buildD;
    }

    @Override
    public String toString() {
        return "Product{" +
                "buildA='" + buildA + '\'' +
                ", buildB='" + buildB + '\'' +
                ", buildC='" + buildC + '\'' +
                ", buildD='" + buildD + '\'' +
                '}';
    }
}

创建具体的建造者

package com.kuan.factory.builder;
//具体的建造者
public class Worker extends Builder {

    private Product product;

    public Worker() {
        product = new Product();
    }

    @Override
    void buildA() {
        product.setBuildA("地基");
        System.out.println("地基");
    }

    @Override
    void buildB() {
        product.setBuildA("钢筋水泥");
        System.out.println("钢筋水泥");
    }

    @Override
    void buildC() {
        product.setBuildA("铺电线");
        System.out.println("铺电线");
    }

    @Override
    void buildD() {
        product.setBuildA("粉刷");
        System.out.println("粉刷");
    }

    @Override
    Product getProduct() {
        return product;
    }
}

创建Director指挥类,指导工人构建一个工程并返回一个完整的工程

package com.kuan.factory.builder;

//指挥:核心,负责指挥构建一个工程,工程如何构建,由他决定
public class Director {

    //指挥工人按照一定顺序建造
    public Product build(Builder builder){
        builder.buildA();
        builder.buildB();
        builder.buildC();
        builder.buildD();

        return builder.getProduct();
    }
}

测试

package com.kuan.factory.builder;

public class Test {
    public static void main(String[] args) {

        Director director = new Director();
        Product product = director.build(new Worker());
        product.toString();
    }
}
  • 通过静态内部类实现零件的无需装配构造,这种方式更加灵活,更符合定义,

4.原型模式

Clone()

  1. 实现一个接口 Cloneable
  2. 重写一个方法 clone()

浅克隆,深克隆,详见上一篇java基础。

结构型模式:

5.适配器模式(usb网线转换接口)

角色分析:
1.目标接口(Usb):客户所期待的接口,目标可以是具体的或抽象的类,也可以是接口
2.需要适配的类(网线):需要适配的类或适配者类
3.适配器(usb转换器):通过包装一个需要适配的对象,把原接口转换成目标接口

posted @ 2021-06-25 23:45  Chcode  阅读(102)  评论(0)    收藏  举报