23种设计模式再理解

立志于精炼好理解。一句话怎么绝不多半句。是为了方便自己脑子形成设计模式的思维导图。
如果你不了解每个模式类图结构。就不建议看了。这是有基础的再次理解。
1,简单工厂模式:通过一个类来负责创建其他类的实例,被创建的通常有共同的特点。
先看代码(手机为例):

package com.design.sampleFactory;

/**
 * 手机的基本功能
 */
public interface Phone {
    /*
     打电话
     */
    public void tellSomeone();

    /*
    发短息
     */
    public void sendMessage();
}

实现的类(自我命名为缺点类,因为当我每增加一款手机,就需要增加对应的实现类,繁杂):仅实现。
在这里插入图片描述
重点是简单工厂类:

方式一:

package com.design.sampleFactory;

/**
 * 生成手机实例的工厂
 */
public class SampleFactory {

    /*
    获取手机实例
     */
    public static Phone getOneOfPhone(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        return (Phone) Class.forName(className).newInstance();
    }

}

调用方式:

package com.design.sampleFactory;

// 简单工厂模式:通过一个类来负责创建其他类的实例,被创建的通常有共同的特点

// 比如手机系列
public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Phone applePhone = null;
        Phone oppoPhone = null;
        try {
            // 要传入相对路径😭。idea中原因不明。eclisp就可以
            applePhone = SampleFactory.getOneOfPhone("com.design.sampleFactory.ApplePhone");
            applePhone.sendMessage();
            oppoPhone = SampleFactory.getOneOfPhone("com.design.sampleFactory.OppoPhone");
            oppoPhone.sendMessage();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}

另外还两种方式(不过每次新增一个实例类,都要改工厂是不建议的):不推荐使用,扩展性很差

package com.design.sampleFactory;

/**
 * 生成手机实例的工厂
 */
public class SampleFactory {

    /*
    第二种
     */
    public static Phone getOneOfPhone(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        return (Phone) Class.forName(className).newInstance();
    }

    public static Phone getApplePhone() {
        return new ApplePhone();
    }
    
    /*
    第三者
    */
    public static Phone getPhone(String className) {
        if (className.equals("ApplePhone")) {
            return new ApplePhone();
        } else if (className.equals("OppoPhne")) {
            return new OppoPhone();
        }
        return null;
    }
}

2,工厂方法模式:为了满足开放封闭原则。本质未变。但需要新增一个oppo手机时,就得增加一个OppoPhone实例类和OppoFactory
在这里插入图片描述
工厂实现举例:

package com.design.FactoryMethod;

public class AppleFactory implements PhoneFactory {
    @Override
    public Phone getPhone() {
        return new ApplePhone();
    }
}

实现方式:

package com.design.FactoryMethod;

// 工厂方法模式:为了满足开放封闭原则。本质未变。

// 比如手机系列
public class Main {
    public static void main(String[] args) {
        // 通过苹果工厂来获取:
        AppleFactory af = new AppleFactory();
        af.getPhone().sendMessage();

        // 但是比如我们现在新增一个oppo手机,就得增加一个OppoPhone实例类和OppoFactory
        OppoFactory of = new OppoFactory();
        of.getPhone().sendMessage();
    }
}

3,抽象工厂模式:引入满足产品族概念。找了一张很好懂的图。
在这里插入图片描述
来实现上面的结果图:
按步骤即可:

产品接口类

package com.design.FactoryMethod;

public interface Product {
    void sendMesage();
}

产品实现类:
在这里插入图片描述

工厂类:

package com.design.FactoryMethod;

// 生成多个产品族
public interface AbstractFoctory {
    // 获得1产品
    public Product getProduct1();

    // 获得2产品
    public Product getProduct2();
}

工厂类实现:
在这里插入图片描述
测试:

package com.design.FactoryMethod;

public class Main {
    public static void main(String[] args) {
        Product1Factory p1 = new Product1Factory();
        p1.getProduct1().sendMesage();
        p1.getProduct2().sendMesage();

        Product2Factory p2 = new Product2Factory();
        p2.getProduct1().sendMesage();
        p2.getProduct2().sendMesage();
    }
}

4,单例模式(即只生成唯一一个全局实例对象)。
饿汉式:

package com.design.singleton;

/*
 饿汉式
 */
public class SQLPrimayId {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    private SQLPrimayId() {}

	// 饿的体现,没有就创建
    private static SQLPrimayId sqlPrimayId;
    public static SQLPrimayId getSQlInstace() {
        if (sqlPrimayId == null) {
            sqlPrimayId = new SQLPrimayId();
        }
        return sqlPrimayId;
    }
}

调试:

package com.design.singleton;

public class Main {
    public static void main(String[] args) {
        SQLPrimayId sql1 = SQLPrimayId.getSQlInstace();
        SQLPrimayId sql2 = SQLPrimayId.getSQlInstace();
        sql1.setId("123");
        sql2.setId("456");
        System.out.println(sql1.getId());
        System.out.println(sql2.getId());
    }
}

懒汉式:

package com.design.singleton;

/*
 饿汉式
 */
public class SQLPrimayId {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    private SQLPrimayId() {}

   // 懒的体现,初始创建创建
    private static SQLPrimayId sqlPrimayId = new SQLPrimayId(); 
    public static SQLPrimayId getSQlInstace() {
        return sqlPrimayId;
    }
}

上面的单线程是没问题。饿汉多线程是可以保证的。懒汉式就凉凉了。
解决办法之一,直接锁住整个方法:(但是效率极低)

package com.design.singleton;

/*
 饿汉式
 */
public class SQLPrimayId {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    private SQLPrimayId() {}

    private static SQLPrimayId sqlPrimayId;
    public static synchronized SQLPrimayId getSQlInstace() {
        if (sqlPrimayId == null) {
            sqlPrimayId = new SQLPrimayId();
        }
        return sqlPrimayId;
    }
}

因此引出双重检查。

package com.design.singleton;

/*
 饿汉式
 */
public class SQLPrimayId {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    private SQLPrimayId() {}

    private static volatile SQLPrimayId sqlPrimayId;
    public static SQLPrimayId getSQlInstace() {
        if (sqlPrimayId == null) {
            synchronized (SQLPrimayId.class) {
                if (sqlPrimayId == null) {
                    sqlPrimayId = new SQLPrimayId();
                }
            }
        }
        return sqlPrimayId;
    }
}

另外静态内部内也推荐使用:

package com.design.singleton;

/*
 静态内部类
 */
public class SQLPrimayId {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    private SQLPrimayId() {}

    private static class SQLInstacne {
        private static final SQLPrimayId SQL_PRIMAY_ID = new SQLPrimayId();
    }
    public static SQLPrimayId getSQlInstace() {
        return SQLInstacne.SQL_PRIMAY_ID;
    }
}

5,原型模式:复制得到原型对象数据。从而避免大量的get,set语句。

package com.design.singleton;
// 1,实现Cloneable
public class Student implements Cloneable {
    private int id;
    private String name;
    private String className;
    private String grade;

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
	
	// 2,提供方法,并实现克隆
    public Student clone() {
        try {
            return (Student) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

测试类:

package com.design.singleton;

public class Main {
    public static void main(String[] args) {
        Student stu1 = new Student();
        stu1.setId(12);
        stu1.setName("喵喵");
        stu1.setClassName("302");
        stu1.setGrade("2年级");

//        Student stu2 = new Student();
//        stu2.setId(11);
//        stu2.setName("酱酱");
//        stu1.setClassName("302");
//        stu1.setGrade("2年级");
        // 我们发现stu2和stu1两者很相似。
        Student stu2 = stu1.clone(); // stu2和stu1拥有相同的数据
        stu2.setId(11);
        stu2.setName("酱酱");
    }
}

以上我们发现都是基础类型。属于浅克隆。但是当一个类种还引用了其他的实体类或者其他对象集合,就属于深度克隆。
深度克隆类:

package com.design.singleton;

import java.util.ArrayList;
import java.util.List;

public class Student implements Cloneable {
    private int id;
    private String name;
    private String className;
    private String grade;
    private List<String> teachers;

    public List<String> getTeachers() {
        return teachers;
    }

    public void setTeachers(List<String> teachers) {
        this.teachers = teachers;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
	// 核心处理
    public Student clone() {
        try {
            // 先解决基本类型
            Student student = (Student) super.clone();
            // 在手动复制引用类型
            List<String> teachers = new ArrayList<>();
            for (String str : this.getTeachers()) {
                teachers.add(str);
            }
            student.setTeachers(teachers);
            return student;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

测试类:

package com.design.singleton;

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        Student stu1 = new Student();
        stu1.setId(12);
        stu1.setName("喵喵");
        stu1.setClassName("302");
        stu1.setGrade("2年级");
        List<String> list = new ArrayList<>();
        list.add("李凡");
        list.add("张武");
        stu1.setTeachers(list);

        Student stu2 = stu1.clone();
        stu2.setId(11);
        stu2.setName("酱酱");

        list.add("王五");
        stu1.setTeachers(list);
    }
}

解释下为什么需要下面的这段代码:

 // 在手动复制引用类型
            List<String> teachers = new ArrayList<>();
            for (String str : this.getTeachers()) {
                teachers.add(str);
            }
            student.setTeachers(teachers);

因为,它们上面stu1和stu2他们指向同一个引用,如果改变一个就会同时改变。所以上面的代码就是改变引用。你可以注释掉上面的试试哟!

6,建造者模式:用来隐藏符复合对象的创建。
1,参考如下:
内部内实现建造者模式
2,也可以有一个类,专门去set。然后返回对象。推荐用一,灵活性更高。

7,装饰者模式:对客服端透明的方式来扩展对象的功能(是实现子类的一种替换方式)。比如手机举例:基础手机,通过装饰者类实现功能扩展。
客户需要的手机类:

package com.design.singleton;

public interface Phone {
    // 每部手机都有的基础功能
    /*
     通话功能
     */
    public void tell();

    /*
    展示手机所有功能
     */
    public void show();
}

基础手机类:

package com.design.singleton;

public class P5G implements Phone {
    @Override
    public void tell() {
        System.out.println("通话");
    }

    @Override
    public void show() {
        this.tell();
        this.message();
    }

    public void message() {
        System.out.println("短信");
    }
}

抽象装饰类:

package com.design.singleton;

public abstract class Decorator implements Phone {

    private Phone phone;

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

    public Phone getPhone() {
        return phone;
    }

    public void setPhone(Phone phone) {
        this.phone = phone;
    }

}

手机升级5g类:

package com.design.singleton;

// 无限升级实现phone,继承装饰者实现扩展
public class P5GshoujiDecorator extends Decorator implements Phone {

    public P5GshoujiDecorator(Phone phone) {
        super(phone);
    }

    public void show() {
        // 以前的功能
        this.getPhone().show();
        // 新增功能
        this.gaoQingshiping();
    }

    public void gaoQingshiping() {
        System.out.println("高清视频");
    }

    @Override
    public void tell() {

    }
}

继续升级为无敌手机:

package com.design.singleton;

// 无限升级实现phone,继承装饰者实现扩展
public class P5GshoujiDecorator extends Decorator implements Phone {

    public P5GshoujiDecorator(Phone phone) {
        super(phone);
    }

    public void show() {
        // 以前的功能
        this.getPhone().show();
        // 新增功能
        this.gaoQingshiping();
    }

    public void gaoQingshiping() {
        System.out.println("高清视频");
    }

    @Override
    public void tell() {

    }
}

客户端实现升级:

package com.design.singleton;

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        // 5G手机实现 new P5G()为基础手机
        P5GshoujiDecorator p5Gshouji = new P5GshoujiDecorator(new P5G());
        //p5Gshouji.show();
        // 5G手机升级为无敌手机出现
        PWudishoujiDecorator wudishouji = new PWudishoujiDecorator(p5Gshouji);
        wudishouji.show();
    }
}

简单来说,举例手机卡,最基础的手机卡类,我们给他一个装饰类。这样我们可以从基础升级到5G卡,也可以有4G升级到5G卡。内部怎么做的客户端不在乎,它只需要知道这个可以这么升级就可以了。

8,策略模式:对一系列算法接口进行封装,为所有算法顶一个抽象的算法接口。(较为简单)。实际种打折就用策略模式就还不错。符合开闭原则。
策略接口:

package com.design.strategy;

public interface Strategy {
    // 加密
    public void encrype();
}

MDS加密算法:

package com.design.strategy;

public class MDSStrategy implements Strategy {
    @Override
    public void encrype() {
        System.out.println("MDS加密");
    }
}

MD5Jami算法:

package com.design.strategy;

public class MDStrategy implements Strategy {
    @Override
    public void encrype() {
        System.out.println("MD5加密");
    }
}

策略封装类:

package com.design.strategy;

public class Context {
    private Strategy strategy;
    public Context(Strategy strategy) {
        this.strategy =strategy;
    }

    public void encrypt() {
        // 实现加密
        this.strategy.encrype();
    }
}

客户端测试:

package com.design.strategy;


public class Main {
    public static void main(String[] args) {
        // new MDStrategy() 这决定起作用的那个,也可MD5
        Context context = new Context(new MDStrategy());
        context.encrypt();
    }
}

9,观察者模式(重要):行为模式之一。它的作用是当一个对象的状态发生改变时,能够自动通知其他关联对象,自动刷新对象状态。
被观察者:被观察的对象。当被观察者状态变法,需要通知队列中所有观察者对象,被观察者需要添加,删除,通知一个观察者对象的队列。
观察者:接口或者抽象类。当被观察者状态发生改变时,观察者通过一个callback函数得到通知。
两者都有实现类,去扩展业务实现。

被观察者:

package com.design.observer;

import jdk.nashorn.internal.objects.annotations.Getter;

import java.util.Observable;

//  **被观察者继承实现 Observable 里面有各种方法运用值得研究**
public class Student extends Observable {

    private String name;

    private String chaoXi;

    private String daJia;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getChaoXi() {
        return chaoXi;
    }

    public void setChaoXi(String chaoXi) {
        this.chaoXi = chaoXi;
        //是否状态以改变
        this.setChanged();
        // 观察有抄袭
        this.notifyObservers();
    }

    public String getDaJia() {
        return daJia;
    }

    public void setDaJia(String daJia) {
        this.daJia = daJia;
        //是否状态以改变,默认true
        this.setChanged();
        // 发现有打架
        this.notifyObservers();
    }
}package com.design.observer;

import jdk.nashorn.internal.objects.annotations.Getter;

import java.util.Observable;

//  被观察者继承实现 Observable 里面有各种方法运用值得研究
public class Student extends Observable {

    private String name;

    private String chaoXi;

    private String daJia;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getChaoXi() {
        return chaoXi;
    }

    public void setChaoXi(String chaoXi) {
        this.chaoXi = chaoXi;
        //是否状态以改变
        this.setChanged();
        // 观察有抄袭 可传你的需要业务
        this.notifyObservers("有抄袭");
    }

    public String getDaJia() {
        return daJia;
    }

    public void setDaJia(String daJia) {
        this.daJia = daJia;
        //是否状态以改变,默认true
        this.setChanged();
        // 发现有打架
        this.notifyObservers("发现有打架");
    }
}


观察者:

package com.design.observer;

import java.util.Observable;
import java.util.Observer;

// 观察者需要实现Observer
public class Teacher implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        // Object arg这个传改变,或其他业务相关参数
        System.out.println("学生有违纪现象:" +arg);
        // 业务代码位置
    }
}

测试类:

package com.design.observer;


public class Main {
    public static void main(String[] args) {
        Student studentA = new Student();
        // 给学生注册老师作为观察者
        studentA.addObserver(new Teacher());
        studentA.setName("王五");
        studentA.setChaoXi("有抄袭");
        // 删除所有观察者
        // studentA.deleteObservers();
    }
}

结果:
在这里插入图片描述
10,享元模式:通过与其他类似对象共享数据来减小内存占用。
比如;apple的两个p是指向同一个对象。

基本字母类:

package com.design.chararctor;

public class MyChar {
    private char myChar;

    public MyChar(char myChar) {
        this.myChar = myChar;
    }

    public char getMyChar() {
        return myChar;
    }

    public void setMyChar(char myChar) {
        this.myChar = myChar;
    }


}

字母工厂(内有池子保存):

package com.design.chararctor;

import java.util.HashMap;
import java.util.Map;

public class MycharFactory {
    // 池子:保存已有对象
    private Map<Character, MyChar> charPool;

    public MycharFactory() {
        charPool = new HashMap<>();
    }

    // 从池子获取
    public MyChar getMychar(Character character){
        // 从池子获取
        MyChar myChar = charPool.get(character);
        if (myChar == null) {
            // 池子没有创建并添加进池子
            myChar = new MyChar(character);
            charPool.put(character,myChar);
        }
        return myChar;
    }
}

测试类:

package com.design.chararctor;


import com.design.observer.Student;
import com.design.observer.Teacher;

public class Main {
    public static void main(String[] args) {
        MycharFactory factory = new MycharFactory();
        MyChar myChar1 = factory.getMychar('a');
        MyChar myChar2 = factory.getMychar('p');
        MyChar myChar3 = factory.getMychar('p');
        MyChar myChar4 = factory.getMychar('l');
        MyChar myChar5 = factory.getMychar('e');
        if (myChar2 == myChar3) {
            // 两者公用一个对象
            System.out.println(true);
        } else {
            System.out.println(false);
        }
    }
}

结果:
在这里插入图片描述
11,代理模式。
参考:
以前详细写过动态代理链接

12,外观模式。是一组有类似功能的类群(模块或者子系统)。这个一致的简单界面被称为外观模式。
比如有三个子系统,客户端可以一次调用一个,两个,三个。不可能类访问一样访问一次,两次,三次。
子系统A:

package com.design.facade;

/**
 * 子系统A
 */
public class SystemA {
    public void doSomething() {
        System.out.println("子系统A");
    }
}

子系统B:

package com.design.facade;

/**
 * 子系统B
 */
public class SystemB {
    public void doSomething() {
        System.out.println("子系统B");
    }
}

子系统C:

package com.design.facade;

/**
 * 子系统C
 */
public class SystemC {
    public void doSomething() {
        System.out.println("子系统C");
    }
}

外观模式:

package com.design.facade;

// 外观模式
public class Facade {

    private SystemA systemA;
    private SystemB systemB;
    private SystemC systemC;

    public Facade() {
        systemA = new SystemA();
        systemB = new SystemB();
        systemC = new SystemC();
    }

    public void ABCUse() {
        this.systemA.doSomething();
        this.systemB.doSomething();
        this.systemC.doSomething();
    }

    public void ABUse() {
        this.systemA.doSomething();
        this.systemB.doSomething();
    }

    public void AUse() {
        this.systemA.doSomething();
    }
}

客户端测试:你想要更多的情况,在Facade添加即可

package com.design.facade;

public class Main {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.ABCUse();
        // facade.ABUse();
        // facade.AUse();
    }
}

13,组合模式。通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个对象树。
类结构图:
在这里插入图片描述简单举例:访问文件夹就是这个逻辑。文件的添加删除等。以下display为operation,其对应很名明显。

文件接口:

package com.design.composite;

import java.util.List;

public interface MyFile {

    /*
    显示文件名: 正真的业务实现
     */
    public void showName();

    /*
    添加文件 (核心一)
     */
    public boolean addFile(MyFile myFile);

    /*
    删除文件 (核心一)
     */
    public boolean deleteFile(MyFile myFile);

    /*
    获取下一个结点(核心一)
     */
    public List<MyFile> getNextChild();
}

单文件类:

package com.design.composite;

import java.util.List;

/**
 * 单文件类
 */
public class MyFileIml implements MyFile {

    private String file;

    public MyFileIml(String file) {
        this.file = file;
    }

    @Override
    public void showName() {
        System.out.println(file);
    }

    @Override
    public boolean addFile(MyFile myFile) {
        return false;
    }

    @Override
    public boolean deleteFile(MyFile myFile) {
        return false;
    }

    @Override
    public List<MyFile> getNextChild() {
        return null;
    }
}

文件夹类:

package com.design.composite;

import com.design.facade.SystemB;

import java.util.ArrayList;
import java.util.List;

/**
 * 文件夹类
 */
public class Floder implements MyFile {
    private String file;
    // 文件夹池
    private List<MyFile> filePool;

    public Floder(String file) {
        this.file = file;
        filePool = new ArrayList<MyFile>();
    }

    @Override
    public void showName() {
        System.out.println(file);
    }

    @Override
    public boolean addFile(MyFile myFile) {
        return filePool.add(myFile);
    }

    @Override
    public boolean deleteFile(MyFile myFile) {
        return filePool.remove(myFile);
    }

    @Override
    public List<MyFile> getNextChild() {
        return filePool;
    }
}

测试类:

package com.design.composite;

import java.util.List;

public class Main {
    public static void main(String[] args) {
        // C盘创建
        Floder rootCpan = new Floder("C:");
        // 目录appdata
        Floder appData = new Floder("appData");
        // 文件zy.txt
        MyFileIml zy = new MyFileIml("zy.txt");

        // C盘下有appData文件夹和zy.txt文件
        rootCpan.addFile(appData);
        rootCpan.addFile(zy);

        // appData目录下有文件zy.ini和目录qq
        Floder qq = new Floder("qq");
        MyFileIml zyini = new MyFileIml("zy.ini");
        appData.addFile(qq);
        appData.addFile(zyini);

        // 递归实现访问
        display(rootCpan);
    }

    /**
     * 通过一个对象访问对象树(核心二)
     * @param rootCpan
     */
    public static void display(MyFile rootCpan) {
        // 自身显示
        rootCpan.showName();
        // 获得子树
        List<MyFile> child = rootCpan.getNextChild();
        for (MyFile file: child) {
            // 是文件MyFileIml
            if (file instanceof MyFileIml) {
                file.showName();
            } else {
                // 是目录
                display(file);
            }
        }
    }
}

结果:
在这里插入图片描述
14,桥接模式。类的最小设计原则,把抽象和实现分离开,保证各部分的独立性。
比如,不同的车,有不同的引擎。将车和引擎分开,通过桥接实现增加车的种类。

引擎接口:

package com.design.bridage;

public interface Engine {
    public void installEngine();
}

引擎2000实现:

package com.design.bridage;

public class Engine2000 implements Engine {
    @Override
    public void installEngine() {
        System.out.println("安装2000引擎");
        // 这里应该是具体业务代码位置
    }
}

引擎2200实现:

package com.design.bridage;

public class Engine2200 implements Engine {
    @Override
    public void installEngine() {
        System.out.println("安装2200引擎");
        // 这里应该是具体业务代码位置
    }
}

引擎和车的桥接类:

package com.design.bridage;

/**
 * 桥接类
 */
public abstract class BridageCar{

    private Engine engine;

    public BridageCar(Engine engine) {
        this.engine = engine;
    }

    public abstract void installEngine();

    public Engine getEngine() {
        return engine;
    }

    public void setEngine(Engine engine) {
        this.engine = engine;
    }


}

通过桥接实现小轿车:

package com.design.bridage;

/**
 * 通过桥接实现小轿车
 */
public class SmallCar extends BridageCar{
    public SmallCar(Engine engine) {
        super(engine);
    }

    @Override
    public void installEngine() {
        // 车的业务代码
        System.out.print("小轿车:");
        this.getEngine().installEngine();
    }
}

客服端测试类:

package com.design.bridage;


public class Main {
    public static void main(String[] args) {
        // 生产引擎为2000小轿车
        SmallCar smallCar = new SmallCar(new Engine2000());
        smallCar.installEngine();
    }
}

接下来,比如我要生产2200引擎的大卡车。通过车和引擎的桥接类实现大卡车即可。你也可以继续增加车的类型。我们发现她很好的满足了最小开放和封闭原则。

  // 比如已经有了bigCar
  BigCar bigCar = new BigCar(new Engine2200());
  bigCar .installEngine();

15,适配器模式(adapter)。通过适配器模式可以改变已有的类的接口形式。现实举例,手机需要5V电压,家里220V电压。中间充电器作为适配器,降压给手机。
代码中往往由于某些接口或功能不成熟,要做升级。但是不能每次大规模的去改动,大面积的修改。为了降低修改面。我们采用了适配器模式。改动后,你最多需要修改几个适配器类就可以了。

电压类:

package com.design.adapter;

/**
 * 电流类
 */
public class Current {
     // 国家供应电压
    public void privide220(){
        System.out.println("使用220V电压");
    }
}

适配器类:

package com.design.adapter;

// 引用方式实现适配器
public class Adapter {
    private Current current;

    public Adapter(Current current) {
        this.current = current;
    }

    // 适配改为5V电压
    public void use5V() {
        this.current.privide220();
        System.out.println("使用适配器变为5V");
    }
}

测试类:

package com.design.adapter;


public class Main {
    public static void main(String[] args) {
        Adapter adapter = new Adapter(new Current());
        adapter.use5V();
    }
}

16,解释器模式:特殊的设计模式(不常用,不多说)。interpreter模式是一种简单的解释器结构。用于特定语言的解释。

17,中介者模式。类之间的交互行为统一放到mediator中。对象通过mediator进行交互。
举例:媒人说亲。

抽象人对象(有媒人):

package com.design.mediator;

public abstract class Person {
    private String name;
    private String condition;
    private Mediator mediator;

    public abstract void getPartner(Person person);

    public Person(String name, String condition, Mediator mediator) {
        this.name = name;
        this.condition = condition;
        this.mediator = mediator;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCondition() {
        return condition;
    }

    public void setCondition(String condition) {
        this.condition = condition;
    }

    public Mediator getMediator() {
        return mediator;
    }

    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }
}

男人通过Mediator媒人注册

package com.design.mediator;

/**
 * 男人
 */
public class Man extends Person {

    public Man(String name, String condition, Mediator mediator) {
        super(name, condition, mediator);
    }

    // 男人注册、找媒人搭线
    public void getPartner(Person person) {
        this.getMediator().setMan(this);
        this.getMediator().getMeeting(person);
    }
}

女人注册

package com.design.mediator;

/**
 * 女人
 */
public class Woman extends Person {

    public Woman(String name, String condition, Mediator mediator) {
        super(name, condition, mediator);
    }
    // 女人注册、找媒人搭线
    public void getPartner(Person person) {
        this.getMediator().setWoman(this);
        this.getMediator().getMeeting(person);
    }
}

中介者媒人:

package com.design.mediator;

public class Mediator {
    private Man man;
    private Woman woman;

    public void setMan(Man man) {
        this.man = man;
    }

    public void setWoman(Woman woman) {
        this.woman = woman;
    }
    // 媒人介绍男女相认
    public void getMeeting(Person person) {
        if (person instanceof  Man) {
            this.setMan((Man) person);
        } else {
            this.setWoman((Woman) person);
        }
        // 判断条件
        if (man != null && woman != null) {
            if (man.getCondition() == woman.getCondition()) {
                System.out.println("合适");
            } else {
                System.out.println("不合适");
            }
        }
    }
}

测试类:

package com.design.mediator;

public class Main {
    public static void main(String[] args) {
        // 中介媒人
        Mediator mediator = new Mediator();
        // 男人
        Person zhangsan = new Man("张三","有钱",mediator);
        // 女人
        Person lixue = new Woman("李雪","有钱", mediator);
        // 通过媒人找到对方。
        zhangsan.getPartner(lixue);
    }
}

结果:
在这里插入图片描述
18,职责链模式:该模式构造一系列分担不同职责的类对象来共同完成一个任务。这些类就像工作流程链条一样紧密。
例子:电脑组装,工厂A生成芯片交给工厂B,B利用芯片生产主机交给工厂C,C利用主机和显示屏组成电脑。

电脑组装抽象类:

package com.design.cor;

public abstract class Computer {

    protected Computer computer;
    /**
   设置下一步
    */
    public void setNextStep(Computer computer){
        this.computer =computer;
    }
    /**
     * 组装
     */
    public abstract void buildComputer();
}

工厂A:

package com.design.cor;

public class FactoryA extends Computer {
    @Override
    public void buildComputer() {
        System.out.println("生成芯片交给FactoryB");
        if (this.computer != null) {
            this.computer.buildComputer();
        }
    }
}

工厂B:

package com.design.cor;

public class FactoryB extends Computer {
    @Override
    public void buildComputer() {
        System.out.println("生成芯片交给FactoryC");
        if (this.computer != null) {
            this.computer.buildComputer();
        }
    }
}

工厂C:

package com.design.cor;

public class FactoryC extends Computer {
    @Override
    public void buildComputer() {
        System.out.println("生成完成");
        if (this.computer != null) {
            this.computer.buildComputer();
        }
    }
}

测试类:

package com.design.cor;


public class Main {
    public static void main(String[] args) {
        // 工厂
        Computer A = new FactoryA();
        Computer B = new FactoryB();
        Computer C = new FactoryC();
        // 设置生成顺序(这个顺序可变)
        A.setNextStep(B);
        B.setNextStep(C);
        // 开始组装
        A.buildComputer();
    }
}

结果:
在这里插入图片描述
我们稍加修改。设置下一步的同时返回下一步:

package com.design.cor;

public abstract class Computer {

    protected Computer computer;
    /**
   设置下一步
    */
    public Computer setNextStep(Computer computer){
        this.computer =computer;
        // 给他返回Computer
        return this.computer;
    }
    /**
     * 组装
     */
    public abstract void buildComputer();
}

package com.design.cor;


public class Main {
    public static void main(String[] args) {
        // 工厂
        Computer A = new FactoryA();
        Computer B = new FactoryB();
        Computer C = new FactoryC();
        // 设置生成顺序(这个顺序可变)
        A.setNextStep(B).setNextStep(C);
        A.buildComputer();

    }
}

19,迭代模式:把对容器中包含的内部对象的访问委让给外部类,使用Iterator遍历,按顺序进行遍历访问。常见使用Iterator遍历。
两种方式,一种模仿Iterator逻辑实现。二是实现Iterator。

内部对象类(女人):

package com.design.iterator;

public class Woman {
    private String name;
    private String type;

    public Woman(String name, String type) {
        this.name = name;
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

把对容器中包含的内部对象的访问委让给外部类:

package com.design.iterator;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 容器类,并提供一个供外部迭代的类
 */
public class MeinvList {
    private List<Woman> meinvList;
    private int index;

    public MeinvList() {
        this.meinvList = new ArrayList<>();
    }

    public void addWomen(Woman woman){
        this.meinvList.add(woman);
    }
    // 向外部提供
    public Itra Iterator() {
        return new Itra();
    }
    // 通过实现Iterator实现
    public class Itra implements Iterator {

        @Override
        public boolean hasNext() {
            if (meinvList.size() <= index) {
                return false;
            }
            return true;
        }

        @Override
        public Object next() {
            return meinvList.get(index++);
        }

        @Override
        public void remove() {

        }
    }
}

上面这个类也可以自己模仿Iterator写,但不推荐。
测试类:

package com.design.iterator;

import java.util.Iterator;

public class Main {
    public static void main(String[] args) {
        MeinvList meinvList = new MeinvList();

        Woman liuyifei = new Woman("刘亦菲","古风");
        Woman tanyan = new Woman("唐嫣","气质型");
        meinvList.addWomen(liuyifei);
        meinvList.addWomen(tanyan);

        Iterator it = meinvList.Iterator();
        while (it.hasNext()) {
            Woman woman = (Woman) it.next();
            System.out.println("名字:" + woman.getName() + ",类型:"+woman.getType());
        }
    }
}

测试结果:
在这里插入图片描述
20,模板方法模式:用于存在多个具有同样的操作步骤的应用场景,但是某些具体的操作细节却各不相同。
通过继承实现:

抽象类:抽象方法用具体方法调用

package com.design.TemplateMethod;

public abstract class Computer {

    //电脑组装抽象方法
    public abstract void buildMain();
    public abstract void buildScreen();
    // 组装具体方法调用抽象方法
    public void buildComputer() {
        this.buildMain();
        this.buildScreen();
    }
}

通过继承实现抽象方法的具体业务:
生产苹果电脑:

package com.design.TemplateMethod;

public class AppleComputer extends Computer{
    // 抽象具体业务实现
    @Override
    public void buildMain() {
        System.out.println("苹果主机");
    }

    @Override
    public void buildScreen() {
        System.out.println("苹果显示屏");
    }
}

生产thinkpad电脑:

package com.design.TemplateMethod;

public class ThinkpadComputer extends Computer{
    // 抽象具体业务实现
    @Override
    public void buildMain() {
        System.out.println("联想主机");
    }

    @Override
    public void buildScreen() {
        System.out.println("联想显示屏");
    }
}

测试类:

package com.design.TemplateMethod;


public class Main {
    public static void main(String[] args) {
        Computer apple = new AppleComputer();
        Computer thingkpad = new ThinkpadComputer();
        apple.buildComputer();
        thingkpad.buildComputer();
    }
}

测试结果:

在这里插入图片描述
21,备忘录模式:(Menento)作用是保存对象的内部状态,需要时undo/rollback恢复对象以前的状态。
显示种很多场景,比如按ctrl+z可以回退、浏览器的回退等。其实可以想象,就是存储操作,一定条件下调用存储恢复。
多类(实际记得拆分出来):

package com.design;

public class MementoModel {
    public static void main(String[] args)
    {
        Originator or=new Originator();
        Caretaker cr=new Caretaker();
        or.setState("S0");
        System.out.println("初始状态:"+or.getState());
        cr.setMemento(or.createMemento()); //保存状态
        or.setState("S1");
        System.out.println("新的状态:"+or.getState());
        or.restoreMemento(cr.getMemento()); //恢复状态
        System.out.println("恢复状态:"+or.getState());
    }
}
//备忘录
class Memento
{
    private String state;
    public Memento(String state)
    {
        this.state=state;
    }
    public void setState(String state)
    {
        this.state=state;
    }
    public String getState()
    {
        return state;
    }
}
//发起人
class Originator
{
    private String state;
    public void setState(String state)
    {
        this.state=state;
    }
    public String getState()
    {
        return state;
    }
    public Memento createMemento()
    {
        return new Memento(state);
    }
    public void restoreMemento(Memento m)
    {
        this.setState(m.getState());
    }
}
//管理者
class Caretaker
{
    private Memento memento;
    public void setMemento(Memento m)
    {
        memento=m;
    }
    public Memento getMemento()
    {
        return memento;
    }
}

结果:
在这里插入图片描述
22,状态模式:主要解决的是当控制一个对象状态转换的条件过于复杂。把判断转移到表示不同状态的类中。从而简化判断逻辑。
多类(实际记得拆分出来):

package com.design;

public class StatePatternClient {
    public static void main(String[] args)
    {
        Context context=new Context();    //创建环境
        context.handle();    //处理请求
        context.handle();
    }
}
// 环境类(通过环境设置状态)
class Context
{
    private State state;
    //定义环境类的初始状态
    public Context()
    {
        this.state=new ConcreteStateA();
    }
    //设置新状态
    public void setState(State state)
    {
        this.state=state;
    }
    //读取状态
    public State getState()
    {
        return(state);
    }
    //对请求做处理
    public void handle()
    {
        state.Handle(this);
    }
}
//抽象状态类
abstract class State
{
    public abstract void Handle(Context context);
}
//具体状态A类
class ConcreteStateA extends State
{
    public void Handle(Context context)
    {
        System.out.println("当前状态是 A.");
        // 状态A执行完,设置为B
        context.setState(new ConcreteStateB());
    }
}
//具体状态B类
class ConcreteStateB extends State
{
    public void Handle(Context context)
    {
        System.out.println("当前状态是 B.");
        // 状态B实现完,将状态设置为B
        context.setState(new ConcreteStateA());
    }
}

23,命令模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。

举例:客人点餐。

package com.design;

/**
 * 比如点餐
 */
public class CommandPattern {
    public static void main(String[] args) {
        Command cmd = new ConcreteCommand();
        Invoker ir = new Invoker(cmd);
        System.out.println("客人喊服务员");
        // 客人喊服务员
        ir.call();
    }
}

//调用者(客人找服务员,同时服务员要执行下单并执行给厨师)
class Invoker {
    private Command command;

    public Invoker(Command command) {
        // 客人和服务员的关系
        this.command = command;
    }

    //    public void setCommand(Command command)
//    {
//        this.command=command;
//    }
    // 客人找服务员
    public void call() {
        System.out.println("我点芹菜香干肉丝 +辣");
        // 同时服务员要执行下单并执行给厨师
        command.execute();
    }
}

//抽象命令
interface Command {
    public abstract void execute();
}

//具体命令(服务员)
class ConcreteCommand implements Command {
    private Receiver receiver;

    ConcreteCommand() {
        // 服务员和厨师的关系
        receiver = new Receiver();
    }

    public void execute() {
        // 服务员通知厨师
        receiver.action();
    }
}

//接收者(厨师)
class Receiver {
    public void action() {
        System.out.println("我要做做芹菜香干肉丝 + 辣");
    }
}

24,访问者模式(很难):集合对象中存在多种不同的元素,且每种元素也存在多种不同的访问者和处理方式。
例如,公园中存在多个景点,也存在多个游客,不同的游客对同一个景点的评价可能不同;

不想理解这个😭:

package com.design;

import java.util.*;

public class VisitorPattern {
    public static void main(String[] args) {
        ObjectStructure os = new ObjectStructure();
        os.add(new ConcreteElementA());
        os.add(new ConcreteElementB());
        Visitor visitor = new ConcreteVisitorA();
        os.accept(visitor);
        System.out.println("------------------------");
        visitor = new ConcreteVisitorB();
        os.accept(visitor);
    }
}

//抽象访问者
interface Visitor {
    void visit(ConcreteElementA element);

    void visit(ConcreteElementB element);
}

//具体访问者A类
class ConcreteVisitorA implements Visitor {
    public void visit(ConcreteElementA element) {
        System.out.println("具体访问者A访问-->" + element.operationA());
    }

    public void visit(ConcreteElementB element) {
        System.out.println("具体访问者A访问-->" + element.operationB());
    }
}

//具体访问者B类
class ConcreteVisitorB implements Visitor {
    public void visit(ConcreteElementA element) {
        System.out.println("具体访问者B访问-->" + element.operationA());
    }

    public void visit(ConcreteElementB element) {
        System.out.println("具体访问者B访问-->" + element.operationB());
    }
}

//抽象元素类
interface Element {
    void accept(Visitor visitor);
}

//具体元素A类
class ConcreteElementA implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public String operationA() {
        return "具体元素A的操作。";
    }
}

//具体元素B类
class ConcreteElementB implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public String operationB() {
        return "具体元素B的操作。";
    }
}

//对象结构角色
class ObjectStructure {
    private List<Element> list = new ArrayList<Element>();

    public void accept(Visitor visitor) {
        Iterator<Element> i = list.iterator();
        while (i.hasNext()) {
            ((Element) i.next()).accept(visitor);
        }
    }

    public void add(Element element) {
        list.add(element);
    }

    public void remove(Element element) {
        list.remove(element);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值