# 设计模式

设计模式

设计模式总览

请添加图片描述


单例模式

类图

请添加图片描述

定义

一个类只有一个实例,该类能自己创建该类的一个实例。

特点

  • 单例类只有一个实例对象。
  • 单例对象必须由该类自己创建。
  • 单例类对外提供一个访问该单例的全局访问点。

单例模式的实现方式

  • 懒汉模式:加载类的时候没有生成单例模式,调用生成实例对象的方法的时候创建单例。
public class LazySingleton {

    //保证lazySingleton在线程中同步
    private static volatile LazySingleton lazySingleton = null;
    //保证类不在别的地方被实例化
    private LazySingleton() {
    }
    //synchronize保证线程安全
    public static synchronized LazySingleton getInstance() {
        if (lazySingleton == null) {
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
}
  • 饿汉模式:类一旦加载就创建一个单例。创建的这个对象之后就不会再改变,所以是线程安全的。
public class HungrySingleton {
    private static final HungrySingleton hungrySingleton = new HungrySingleton();
    private HungrySingleton() {
    }
    public static HungrySingleton getInstance() {
        return hungrySingleton;
    }
}

工厂模式

类图

请添加图片描述

定义

对象的实际创建工作推迟到子类当中。

特点

  • 用户主需要知道工厂的名称,则可得到对应的产品,无需知道产品的创建过程。
  • 系统增加产品时只需添加具体产品类和对应的具体工厂类,无需对原工厂进行修改。
  • 每增加一个产品就得增加一个具体产品类和和一个对应的具体工厂类。

实现方式

  • 提供产品的接口
public interface Product {
    public void show();
}
  • 具体产品1实现产品接口
public class ProductImpl1 implements Product {
    @Override
    public void show() {
        System.out.println("我生产了1");
    }
}
  • 具体产品2实现产品接口
public class ProductImpl2 implements Product {
    @Override
    public void show() {
        System.out.println("我生产了2");
    }
}
  • 抽象工厂,提供生成产品的方法
public interface AbstractFactory {
    public Product getInstance();
}
  • 实现产品生成
public class FactoryTest {
    public static void main(String[] args) {
        CreateFactory1 createFactory1 = new CreateFactory1();
        createFactory1.getInstance();
        CreateFactory2 createFactory2 = new CreateFactory2();
        createFactory2.getInstance();
    }
    static class CreateFactory1 implements AbstractFactory {
        @Override
        public Product getInstance() {
            System.out.println("工厂1生产产品");
            ProductImpl1 productImpl1 = new ProductImpl1();
            productImpl1.show();
            return productImpl1;
        }
    }
    static class CreateFactory2 implements AbstractFactory {
        @Override
        public Product getInstance() {
            System.out.println("工厂2生产产品");
            ProductImpl2 productImpl2 = new ProductImpl2();
            productImpl2.show();
            return productImpl2;
        }
    }
}

抽象工厂模式

类图

请添加图片描述

定义

是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

特点

  • 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
  • 当增加一个新的产品族时不需要修改原代码。

实现方式

  • 形状类以及具体的图形
public interface Shape {
    /**
     * 画形状
     */
    void draw();
}
public class Rectangle implements Shape {

    private static final Logger logger = LoggerFactory.getLogger(Rectangle.class);

    public static final String SHAPE = "rectangle";

    @Override
    public void draw() {
        logger.info("我是长方形");
    }
}
public class Square implements Shape {

    private static final Logger logger = LoggerFactory.getLogger(Square.class);

    public static final String SHAPE = "square";

    @Override
    public void draw() {
        logger.info("我是矩形");
    }
}

  • 颜色以及具体的颜色
public interface Color {
    /**
     * 填充颜色
     */
    void fill();
}
public class Green implements Color {

    private static final Logger logger = LoggerFactory.getLogger(Green.class);


    public static final String COLOR = "green";

    @Override
    public void fill() {
        logger.info("填充绿色");
    }
}
public class Red implements Color {

    private static final Logger logger = LoggerFactory.getLogger(Red.class);

    public static final String COLOR = "red";

    @Override
    public void fill() {
        logger.info("填充红色");
    }
}
  • 得到颜色和形状的抽象工厂
public abstract class AbstractFactory {

    public abstract Color getColor(String color);
    public abstract Shape getShape(String shape);

}
  • 得到具体颜色、具体形状的方法
public class ColorFactory extends AbstractFactory {

    public static final String TYPE = "color";

    @Override
    public Color getColor(String color) {
        if (color == null) {
            return null;
        } else if (Red.COLOR.equalsIgnoreCase(color)) {
            return new Red();
        } else if (Green.COLOR.equalsIgnoreCase(color)) {
            return new Green();
        }
        return null;
    }

    @Override
    public Shape getShape(String shape) {
        return null;
    }
}
public class ShapeFactory extends AbstractFactory {

    public static final String TYPE = "shape";

    @Override
    public Color getColor(String color) {
        return null;
    }

    @Override
    public Shape getShape(String shape) {
        if (shape == null) {
            return null;
        }
        if (Rectangle.SHAPE.equalsIgnoreCase(shape)) {
            return new Rectangle();
        } else if (Square.SHAPE.equalsIgnoreCase(shape)) {
            return new Square();
        }
        return null;
    }
}
  • 得到颜色或者形状的工厂
public class FactoryProducer {

    /**
     * 获取工厂实例
     *
     * @param type 工厂类型
     * @return AbstractFactory
     */
    public static AbstractFactory getFactoryInstance(String type) {
        if (ShapeFactory.TYPE.equalsIgnoreCase(type)) {
            return new ShapeFactory();
        } else if (ColorFactory.TYPE.equalsIgnoreCase(type)) {
            return new ColorFactory();
        }
        return null;
    }
}
  • 根据传入的东西判断得到具体的形状或者具体的颜色
public static void main(String[] args) {
    //获取形状工厂
    AbstractFactory shape = FactoryProducer.getFactoryInstance("shape");

    Shape rectangle = Objects.requireNonNull(shape).getShape("rectangle");
    rectangle.draw();

    Shape square = shape.getShape("square");
    square.draw();

    // 获取颜色工厂
    AbstractFactory colorFactory = FactoryProducer.getFactoryInstance("COLOR");
    Color color1 = Objects.requireNonNull(colorFactory).getColor("RED");
    color1.fill();
}

观察者模式

类图

请添加图片描述

简单理解

  • 观察者模式是一种行为性模式,定义对象之间的一对多的依赖关系,当一个对象状态改变时候依赖于它的对象的状态会相应的更新。

使用场景

  • 关联行为场景,关联行为是可拆分的,事件多级触发。
  • 消息队列、时间总线处理机制。
  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制

实例代码

  • 抽象类定义观察者共同的方法
public abstract class Observer {

    protected Subject subject;

    /**
     * 通知观察者状态
     */
    public abstract void update();

}

  • 定义具体的观察者
public class ObserverOne extends Observer {

    private static final Logger logger = LoggerFactory.getLogger(ObserverOne.class);

    public ObserverOne(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        logger.info("ObserverOne 收到通知!");
    }
}

public class ObserverTwo extends Observer{

    private static final Logger logger = LoggerFactory.getLogger(ObserverTwo.class);

    public ObserverTwo(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        logger.info("ObserverTwo 收到通知!");
    }
}

  • 定义主题
public class Subject {

    /**
     * 定义观察者的集合 使用vector 线程安全
     */
    private final Vector<Observer> observerList = new Vector<>();

    private int state;

    /**
     * 注册观察者
     *
     * @param observer 观察者
     */
    public void registerObserver(Observer observer) {
        observerList.add(observer);
    }

    /**
     * 通知所有的观察者
     */
    public void notifyAllObservers() {
        for (Observer observer : observerList) {
            observer.update();
        }
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        notifyAllObservers();
    }
}
  • 测试代码
public class AppTest {

    private static final Logger logger = LoggerFactory.getLogger(AppTest.class);

    @Test
    public void test() {
        Subject subject = new Subject();

        new ObserverOne(subject);
        new ObserverTwo(subject);

        logger.info("第一次状态改变:12");
        subject.setState(12);

        logger.info("第二次状态改变:8");
        subject.setState(8);
    }

}

策略模式

类图

请添加图片描述

简单理解

  • 在接口中定义方法,不同的实现类在重写的方法中做出不同的操作。

使用场景

  • 当符合场景时候可以替换if、else

实例代码

  • 策略接口
public interface Strategy {

    /**
     * 计算数值
     *
     * @param num1 num1
     * @param num2 num2
     * @return int
     */
    int calculate(int num1, int num2);

}
  • 策略实现类
public class CalculateAdd implements Strategy {

    @Override
    public int calculate(int num1, int num2) {
        return num1 + num2;
    }

}
public class CalculateSub implements Strategy {

    @Override
    public int calculate(int num1, int num2) {
        return num1 - num2;
    }

}
  • 控制类
public class Context {

    private Strategy strategy;

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

    public int executeStrategy(int num1, int num2) {
        return strategy.calculate(num1, num2);
    }
}

  • 测试类
public class AppTest {


    private static final Logger logger = LoggerFactory.getLogger(AppTest.class);

    @Test
    public void test(){
        Context context = new Context(new CalculateAdd());
        int i = context.executeStrategy(1, 2);
        logger.info(String.valueOf(i));

        context = new Context(new CalculateSub());
        int i1 = context.executeStrategy(2, 3);
        logger.info(String.valueOf(i1));
    }

}

模板方法模式

类图

请添加图片描述

简单理解

  • 在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

实例代码

  • 抽象父类
public abstract class AbstractCookMeal {

    // 去市场
    abstract void moveToMarket();

    // 购买蔬菜
    abstract void buyVegetables();

    // 回家
    abstract void goHome();

    // 做饭
    abstract void cookMeal();


    public void doCooking(){
        moveToMarket();
        buyVegetables();
        goHome();
        cookMeal();
    }
    
}
  • 子类
public class PeopOneCookMeal extends AbstractCookMeal {

    private static final Logger logger = LoggerFactory.getLogger(PeopOneCookMeal.class);

    private String name;

    public PeopOneCookMeal(String name) {
        this.name = name;
    }

    @Override
    void moveToMarket() {
        logger.info(this.name + "去超市!");
    }

    @Override
    void buyVegetables() {
        logger.info(this.name + "买蔬菜!");
    }

    @Override
    void goHome() {
        logger.info(this.name + "回家!");
    }

    @Override
    void cookMeal() {
        logger.info(this.name + "做饭!");
    }
}
  • 测试
/**
  * 模板模式
  * <p>
  * 使用继承关系:父类中定义相关的一系列行为,不同的子类通过继承抽象父类实现不同的行为
  */
@Test
public void test() {
    PeopOneCookMeal oneCookMeal = new PeopOneCookMeal("张三");
    oneCookMeal.doCooking();
}

原型模式

类图

请添加图片描述

简单理解

  • 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。

关键代码:

  • 实现克隆操作,在 JAVA 继承 Cloneable,重写 clone()
  • 原型模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些"易变类"拥有稳定的接口。

实例代码

  • 实现Cloneable接口,重写对象的 clone 方法
/**
 * 机器人实现 Cloneable
 *
 * @author LiDong
 * @version 1.0.0
 * @createTime 2021年11月14日 11:00:00
 */
public class Robot implements Cloneable {

    private String sno;
    private String name;

    public Robot(String sno, String name) {
        this.sno = sno;
        this.name = name;
    }


    /**
     * 克隆 Robot 的实例
     *
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() {
        Robot robot = null;
        try {
            robot = (Robot) super.clone();
        } catch (Exception e) {
            System.out.println("error occurred while cloning robot: " + e.getMessage());
        }
        return robot;
    }

    @Override
    public String toString() {
        return "Robot{" +
                "sno='" + sno + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}
  • 测试类
public class ProtoTypeTest {

    private static final Logger logger = LoggerFactory.getLogger(ProtoTypeTest.class);

    @Test
    public void test() {
        Robot robot = new Robot("1001", "张三");

        Robot robot1 = (Robot) robot.clone();
        Robot robot2 = (Robot) robot.clone();
        Robot robot3 = (Robot) robot.clone();
        Robot robot4 = (Robot) robot.clone();
        Robot robot5 = (Robot) robot.clone();
        Robot robot6 = (Robot) robot.clone();

        logger.info("info: " + robot);
        logger.info("info: " + robot1);
        logger.info("info: " + robot2);
        logger.info("info: " + robot3);
        logger.info("info: " + robot4);
        logger.info("info: " + robot5);
        logger.info("info: " + robot6);
    }
}
  • 简单理解就是快速创建克隆对象

代理模式

  • 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

静态代理

类图

请添加图片描述

静态代理的代理关系在编译期间就已经确定了的。它适合于代理类较少且确定的情况。如果委托类多了那么,就得要写好多代理方法。

  • 公用接口
/**
 * UserService 接口
 * @author root
 */
public interface UserService {
    
    /**
     * 接口中的方法
     */
    void methodTest();
}
  • 被代理的类:实现接口
public class UserServiceImpl implements UserService {

    private static final Logger log = Logger.getLogger(String.valueOf(UserServiceImpl.class));

    @Override
    public void methodTest() {
        log.info("UserServiceImpl 中 methodTest()");
    }
}

  • 代理类:实现接口,维护一个被代理的对象
public class UserServiceProxyImpl implements UserService {

    private static final Logger log = Logger.getLogger(String.valueOf(UserServiceImpl.class));

    /**
     * 维护的需要代理的对象
     */
    private final UserService userService;

    public UserServiceProxyImpl(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void methodTest() {
        log.info("UserServiceProxy 中 methodTest() 开始...");
        userService.methodTest();
        log.info("UserServiceProxy 中 methodTest() 结束...");
    }
}
  • 测试方法
/**
  * 静态代理
  */
@Test
public void test1() {
    UserService userService = new UserServiceImpl();
    UserServiceProxyImpl userServiceProxy = new UserServiceProxyImpl(userService);
    // 用代理类执行 UserServiceImpl 中test1()
    userServiceProxy.methodTest();
}

JDK 动态代理

类图

请添加图片描述

  • 通过实现 InvocationHandler 接口创建自己的调用处理器;通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。动态代理主要是性能问题。

  • 公用接口

/**
 * UserService 接口
 * @author root
 */
public interface UserService {

    /**
     * 接口中的方法
     */
    void methodTest();
}
  • 被代理的类:实现接口
public class UserServiceImpl implements UserService {

    private static final Logger log = Logger.getLogger(String.valueOf(UserServiceImpl.class));

    @Override
    public void methodTest() {
        log.info("UserServiceImpl 中 methodTest()");
    }
}
  • 代理类:实现InvocationHandler接口,维护一个被代理的对象,重写invoke()
public class DynamicUserServiceProxy implements InvocationHandler {

    private static final Logger log = Logger.getLogger(String.valueOf(UserServiceProxyImpl.class));

    /**
     * 代理对象
     */
    private final Object object;

    public DynamicUserServiceProxy(Object object) {
        this.object = object;
    }

    /**
     * 为目标对象生成代理对象
     */
    public Object getProxyInstance() {
        log.info("-----> 开始生成代理对象...");
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    }

    /***
     * 重写 invoke 方法再里面实现业务逻辑
     * @param object 对象
     * @param method 方法
     * @param args 参数
     * @return Object
     */
    @Override
    public Object invoke(Object object, Method method, Object[] args) throws Throwable {
        log.info("-----> invoke()...");
        //这里就可以进行所谓的AOP编程了
        //在调用具体函数方法前,执行功能处理
        log.info("Aop开始...");
        return method.invoke(this.object, args);
    }

}
  • 测试方法
/**
  * JDK 动态代理
  */
@Test
public void test2() {
    UserService userService = new UserServiceImpl();
    DynamicUserServiceProxy dynamicUserServiceProxy = new DynamicUserServiceProxy(userService);
    UserService userService1 = (UserService) dynamicUserServiceProxy.getProxyInstance();
    userService1.methodTest();
}

Cglib代理

类图

请添加图片描述

  • cglib代理无需实现接口,通过生成类字节码实现代理,比反射稍快,不存在性能问题,但cglib会继承目标对象,需要重写方法,所以目标对象不能为final类。

  • 引入jar包

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.5</version>
</dependency>
  • 代理类:
public class CglibUserServiceProxy implements MethodInterceptor {

    private static final Logger log = Logger.getLogger(String.valueOf(CglibUserServiceProxy.class));

    private Object target;//维护一个目标对象

    public CglibUserServiceProxy(Object target) {
        this.target = target;
    }

    //为目标对象生成代理对象
    public Object getProxyInstance() {
        //工具类
        Enhancer en = new Enhancer();
        //设置父类
        en.setSuperclass(target.getClass());
        //设置回调函数
        en.setCallback(this);
        //创建子类对象代理
        return en.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        log.info("方法前...");
        // 执行目标对象的方法
        method.invoke(target, args);
        log.info("方法后....");
        return null;
    }
}
  • 测试代码
/**
  * CGlib 动态代理
  */
@Test
public void tes3() {
    //目标对象
    UserService userService = new UserServiceImpl();
    //代理对象
    UserService proxy = (UserService) new CglibUserServiceProxy(userService).getProxyInstance();
    //执行代理对象方法
    proxy.methodTest();
}

适配器模式

类图

请添加图片描述

  • 将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

  • 在适配器模式中,我们通过增加一个新的适配器类来解决接口不兼容的问题,使得原本没有任何关系的类可以协同工作。

角色

Target(目标抽象类)

定义所需要的接口,可以是抽象类或接口也可以是具体类。

AdapterClass(适配器类)

适配器继承被适配者类,实现Target,在接口的实现方法中调用超类的方法。

MatchesClass(适配者类)

适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。

类适配器模式

在这里插入图片描述

  • 被适配者类(MatchesClass)
public class ClassAdapter {

    public void testMethodOne(){
        System.out.println("被适配的方法!");
    }
}
  • 适配器类(AdapterClass)
public class Adapter extends ClassAdapter implements TargetInterface  {
    
    /**
     * @Author LiDong
     * @Description //TODO 重写接口中的方法,调用超类的方法
     * @Date 21:24 2020/12/5
     * @Param [] 
     * @return void
     **/
    @Override
    public void testMethod() {
        System.out.println("调用Adapter的testMethod()!");
        super.testMethodOne();
    }
}
  • 目标抽象类
public interface TargetInterface {

    void testMethod();
}
  • 测试类
public static void main(String[] args) {
    TargetInterface targetInterface = new Adapter();
    targetInterface.testMethod();
}

对象适配器模式

在这里插入图片描述
对象适配器与类适配器不同之处在于,类适配器通过继承来完成适配,对象适配器则是通过调用对象的属性完成。

public class Adapter  implements TargetInterface {

    private ClassAdapter classAdapter = new ClassAdapter();

    /**
     * @Author LiDong
     * @Description //TODO 重写接口中的方法,对象调用类的方法
     * @Date 21:24 2020/12/5
     * @Param [] 
     * @return void
     **/
    @Override
    public void testMethod() {
        System.out.println("调用Adapter的testMethod()!");
        classAdapter.testMethodOne();
    }
}
主要优点
  • 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无需修改原有结构。

  • 增加了类的透明性和复用性。

  • 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器


实例

  • 播放器接口
@FunctionalInterface
public interface MediaPlayer {

    /**
     * 播放歌曲
     *
     * @param audioType 歌曲类型
     */
    void play(String audioType);

}

  • 播放器实现类
@Slf4j
public class AudioPlayer implements MediaPlayer {

    @Override
    public void play(String audioType) {
        //播放 mp3 音乐文件的内置支持
        if ("mp3".equalsIgnoreCase(audioType)) {
            log.info("Playing mp3 file. ");
        }
        //mediaAdapter 提供了播放其他文件格式的支持
        else if ("vlc".equalsIgnoreCase(audioType) || "mp4".equalsIgnoreCase(audioType)) {
            MediaAdapter mediaAdapter = new MediaAdapter(audioType);
            mediaAdapter.play(audioType);
        } else {
            log.info("Invalid media. {} format not supported", audioType);
        }
    }
}

  • 高级播放器接口
public interface AdvancedMediaPlayer {

    /**
     * 播放 vlc
     */
    void playVlc();

    /**
     * 播放 mp4
     */
    void playMp4();

}
  • 高级播放器接口实现类
public class Mp4Player implements AdvancedMediaPlayer{

    public static final Logger logger = LoggerFactory.getLogger(Mp4Player.class);

    @Override
    public void playVlc() {
        logger.info("......");
    }

    @Override
    public void playMp4() {
        logger.info("Mp4Player 播放mp4...");
    }
}

public class VlcPlayer implements AdvancedMediaPlayer {

    public static final Logger logger = LoggerFactory.getLogger(VlcPlayer.class);

    @Override
    public void playVlc() {
        logger.info("VlcPlayer 播放vlc...");
    }

    @Override
    public void playMp4() {
        logger.info("......");
    }
}
  • 适配器类
public class MediaAdapter implements MediaPlayer {

    /**
     * 维护一个 advancedMediaPlayer
     */
    private AdvancedMediaPlayer advancedMediaPlayer;

    MediaAdapter(String audioType) {
        if ("vlc".equalsIgnoreCase(audioType)) {
            advancedMediaPlayer = new VlcPlayer();
        } else if ("mp4".equalsIgnoreCase(audioType)) {
            advancedMediaPlayer = new Mp4Player();
        }
    }
    @Override
    public void play(String audioType) {
        if ("vlc".equalsIgnoreCase(audioType)) {
            advancedMediaPlayer.playVlc();
        } else if ("mp4".equalsIgnoreCase(audioType)) {
            advancedMediaPlayer.playMp4();
        }
    }
}
  • 测试代码
@Test
public void test() {
    AudioPlayer audioPlayer = new AudioPlayer();
    audioPlayer.play("mp3");
    audioPlayer.play("mp4");
    audioPlayer.play("vlc");
    audioPlayer.play("avi");
}

建造者模式

类图

请添加图片描述

  • 建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
  • 一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

定义

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

特点

  • 建造者独立,易扩展。 便于控制细节风险。产品必须有共同点,范围有限制。如内部变化复杂,会有很多的建造类。

实例代码

  • 创建一个表示食物条目和食物包装的接口。
public interface Item {

    String name();

    Packing packing();

    float price();

}
public interface Packing {

    /**
     * 打包
     *
     * @return void
     */
    String pack();
}
  • 创建实现 Packing 接口的实体类。
public class Wrapper implements Packing {

    @Override
    public String pack() {
        return "Wrapper";
    }
}
public class Bottle implements Packing {

    @Override
    public String pack() {
        return "Bottle";
    }
}
  • 创建实现 Item 接口的抽象类,该类提供了默认的功能。
public abstract class Burger implements Item {

    @Override
    public Packing packing() {
        return new Wrapper();
    }

    @Override
    public abstract float price();
}
public abstract class ColdDrink implements Item {

    @Override
    public Packing packing() {
        return new Bottle();
    }

    @Override
    public abstract float price();

}
  • 创建扩展了 BurgerColdDrink 的实体类。
public class Coke extends ColdDrink {

    @Override
    public float price() {
        return 30.0f;
    }

    @Override
    public String name() {
        return "Coke";
    }
}
public class VegBurger extends Burger {

    public static final float PRICE = 25.0f;

    @Override
    public float price() {
        return PRICE;
    }

    @Override
    public String name() {
        return "Veg Burger";
    }

}
public class ChickenBurger extends Burger {

    public static final float PRICE = 50.5f;

    @Override
    public float price() {
        return PRICE;
    }

    @Override
    public String name() {
        return "Chicken Burger";
    }
}
public class Pepsi extends ColdDrink {

    @Override
    public float price() {
        return 35.0f;
    }

    @Override
    public String name() {
        return "Pepsi";
    }
}
  • 创建一个 Meal 类,带有上面定义的 Item 对象。
@Slf4j
public class Meal {

    private final List<Item> items = new ArrayList<>();

    public void addItem(Item item){
        items.add(item);
    }

    public float getCost(){
        float cost = 0.0f;
        for (Item item : items) {
            cost += item.price();
        }
        return cost;
    }

    public void showItems(){
        for (Item item : items) {
            log.info("Item : {}", item.name());
            log.info(", Packing : {}", item.packing().pack());
            log.info(", Price : {}", item.price());
        }
    }
}
  • 创建一个 MealBuilder 类,实际的 builder 类负责创建 Meal 对象。
public class MealBuilder {

    public Meal prepareVegMeal() {
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Coke());
        return meal;
    }

    public Meal prepareNonVegMeal() {
        Meal meal = new Meal();
        meal.addItem(new ChickenBurger());
        meal.addItem(new Pepsi());
        return meal;
    }
}

  • 测试代码
@Slf4j
public class AppTest {

    public static final String TOTAL_COST = "Total Cost: {}";

    @Test
    public void test() {
        MealBuilder mealBuilder = new MealBuilder();

        Meal vegMeal = mealBuilder.prepareVegMeal();
        log.info("Veg Meal");
        vegMeal.showItems();
        float cost = vegMeal.getCost();
        log.info(TOTAL_COST, cost);

        Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
        log.info("Non-Veg Meal");
        nonVegMeal.showItems();
        float cost1 = nonVegMeal.getCost();
        log.info(TOTAL_COST, cost1);
    }

}

桥接模式

简单理解

  • 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

类图

请添加图片描述

实例代码

  • 画图接口
public interface DrawApi {

    /**
     * 画圆
     */
    void drawCircle();

}
  • 接口实现类
@Slf4j
public class GreenCircle implements DrawApi {

    @Override
    public void drawCircle() {
        log.info("我画了一个绿色的圆圈");
    }
}
@Slf4j
public class RedCircle implements DrawApi{

    @Override
    public void drawCircle() {
      log.info("我画了一个红色的圆圈");
    }
}
  • 抽象类:维护一个接口对象,提供抽象方法
public abstract class Shape {

    protected DrawApi drawApi;

    public Shape(DrawApi drawApi) {
        this.drawApi = drawApi;
    }

    protected abstract  void draw();
}
  • 抽象类子类
@Slf4j
public class Circle extends Shape{

    public Circle(DrawApi drawApi) {
        super(drawApi);
    }

    @Override
    protected void draw() {
        drawApi.drawCircle();
    }
}

过滤器模式

类图

请添加图片描述

定义

  • 过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。

实例

  • 定义Person对象
@SuppressWarnings("all")
public class Person {

    private String name;
    private String gender;
    /**
     * 婚姻状况
     */
    private String martialStatus;
}
  • 定义标准接口
public interface Criteria {

    List<Person> meetCriteria(List<Person> persons);
}
  • 接口的实现:对象过滤的实现
public class CriteriaMale implements Criteria {

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
        List<Person> malePersons = new ArrayList<>();
        for (Person person : persons) {
            if ("MALE".equalsIgnoreCase(person.getGender())) {
                malePersons.add(person);
            }
        }
        return malePersons;
    }
}
public class AndCriteria implements Criteria {

    private final Criteria criteria;
    private final Criteria otherCriteria;

    public AndCriteria(Criteria criteria, Criteria otherCriteria) {
        this.criteria = criteria;
        this.otherCriteria = otherCriteria;
    }

    @Override
    public List<Person> meetCriteria(List<Person> persons) {
        List<Person> firstCriteriaPersons = criteria.meetCriteria(persons);
        return otherCriteria.meetCriteria(firstCriteriaPersons);
    }
}
  • 测试代码
@Slf4j
public class AppTest {
    
    public static final String SINGLE = "Single";
    public static final String MARRIED = "Married";
    public static final String FEMALE = "Female";

    @Test
    public void test() {
        List<Person> persons = new ArrayList<>();

        persons.add(new Person("Robert", "Male", SINGLE));
        persons.add(new Person("John", "Male", MARRIED));
        persons.add(new Person("Laura", FEMALE, MARRIED));
        persons.add(new Person("Diana", FEMALE, SINGLE));
        persons.add(new Person("Mike", "Male", SINGLE));
        persons.add(new Person("Bobby", "Male", SINGLE));

        Criteria male = new CriteriaMale();
        Criteria female = new CriteriaFemale();
        Criteria single = new CriteriaSingle();
        Criteria singleMale = new AndCriteria(single, male);
        Criteria singleOrFemale = new OrCriteria(single, female);

        log.info("Males: ");
        printPersons(male.meetCriteria(persons));

        log.info("Females: ");
        printPersons(female.meetCriteria(persons));

        log.info("Single Males: ");
        printPersons(singleMale.meetCriteria(persons));

        log.info("Single Or Females: ");
        printPersons(singleOrFemale.meetCriteria(persons));
    }

    public static void printPersons(List<Person> persons) {
        for (Person person : persons) {
            log.info("Person : [ Name : {}, Gender : {}, Marital Status : {} ]", person.getName(), person.getGender(), person.getMartialStatus());
        }
    }

}


组合模式

类图

请添加图片描述

定义

  • 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

实例代码

  • 员工类
public class Employee {

    private String name;
    private String dept;
    private int salary;
    private List<Employee> subordinates;

    //构造函数
    public Employee(String name, String dept, int sal) {
        this.name = name;
        this.dept = dept;
        salary = sal;
        subordinates = new ArrayList<>();
    }

    public void add(Employee e) {
        subordinates.add(e);
    }

    public void remove(Employee e) {
        subordinates.remove(e);
    }

    public List<Employee> getSubordinates() {
        return subordinates;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", dept='" + dept + '\'' +
                ", salary=" + salary +
                ", subordinates=" + subordinates +
                '}';
    }
}

装饰器模式

类图

请添加图片描述

定义

  • 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

  • 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

  • 我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。

特点

  • 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
  • 多层装饰比较复杂。

实现代码

  • 定义画图形的接口
public interface Shape {

    /**
     * 画图
     */
    void draw();
}

  • 接口实现类
@Slf4j
public class Circle implements Shape {

    @Override
    public void draw() {
        log.info("画了一个圆!");
    }
}
@Slf4j
public class Rectangle implements Shape {

    @Override
    public void draw() {
        log.info("画了一个矩形!");
    }
}
  • 定义装饰器
public class ShapeDecorator implements Shape {

    protected Shape decoratorShape;

    public ShapeDecorator(final Shape shape) {
        this.decoratorShape = shape;
    }

    @Override
    public void draw() {
        decoratorShape.draw();
    }
}

  • 装饰器扩展类
@Slf4j
public class RedShapeDecorator extends ShapeDecorator {

    public RedShapeDecorator(Shape shape) {
        super(shape);
    }

    @Override
    public void draw() {
        decoratorShape.draw();
        setRedBorder(decoratorShape);
    }

    private void setRedBorder(Shape decoratedShape) {
        log.info("Border Color: Red");
    }
}
  • 测试代码
@Test
public void test() {
    Shape circle = new Circle();
    ShapeDecorator redCircle = new RedShapeDecorator(new Circle());
    ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());

    circle.draw();
    redCircle.draw();
    redRectangle.draw();
}

外观模式

类图

请添加图片描述

定义

  • 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。

  • 这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。

特点

  • 减少系统相互依赖。 提高灵活性。提高了安全性。

  • 不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。

实现代码

  • 创建一个接口
public interface Shape {

    void draw();
}
  • 接口实现类
@Slf4j
public class Circle implements Shape{

    @Override
    public void draw() {
        log.info("画出一个圆!");
    }
}
@Slf4j
public class Rectangle implements Shape{

    @Override
    public void draw() {
        log.info("画出一个矩形!");
    }
}
  • 外观类
public class ShapeMaker {

    private Shape circle;
    private Shape rectangle;

    public ShapeMaker() {
        circle = new Circle();
        rectangle = new Rectangle();
    }

    public void drawCircle() {
        circle.draw();
    }

    public void drawRectangle() {
        rectangle.draw();
    }

}
  • 测试代码
public class AppTest {

    @Test
    public void test() {
        ShapeMaker shapeMaker = new ShapeMaker();

        shapeMaker.drawCircle();
        shapeMaker.drawRectangle();
    }
}


享元模式

类图

请添加图片描述

定义

  • 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。

实现代码

  • 创建一个接口
public interface Shape {

    void draw();
}
  • 接口实现类
@Slf4j
public class Circle implements Shape {

    private String color;
    private int x;
    private int y;
    private int radius;

    public Circle(String color) {
        this.color = color;
    }

    @Override
    public void draw() {
        log.info(toString());
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void setRadius(int radius) {
        this.radius = radius;
    }
}
  • 创建一个工厂,生成基于给定信息的实体类的对象。
@Slf4j
public class ShapeFactory {

    private static final HashMap<String, Circle> circleMap = new HashMap<>();

    public static Circle getCircle(String color) {
        Circle circle = circleMap.get(color);

        if (Objects.isNull(circle)) {
            circle = new Circle(color);
            circleMap.put(color, circle);
            log.info("创建一个 {} 颜色的Circle:", color);
        }
        return circle;
    }
}
  • 测试代码
public class AppTest {

    private static final String[] colors =
            {"Red", "Green", "Blue", "White", "Black"};

    @Test
    public void test() {
        for (int i = 0; i < 20; ++i) {
            Circle circle = ShapeFactory.getCircle(getRandomColor());
            circle.setX(getRandomX());
            circle.setY(getRandomY());
            circle.setRadius(100);
            circle.draw();
        }
    }

    private static String getRandomColor() {
        return colors[(int) (Math.random() * colors.length)];
    }

    private static int getRandomX() {
        return (int) (Math.random() * 100);
    }

    private static int getRandomY() {
        return (int) (Math.random() * 100);
    }
}

责任链模式

类图

请添加图片描述

定义

  • 责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
  • 在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

特点

  • 降低了系统耦合度。新的命令可以很容易添加到系统中去。

  • 使用命令模式可能会导致某些系统有过多的具体命令类。

实现代码

  • 创建抽象的记录器类。
public abstract class AbstractLogger {

    public static int INFO = 1;
    public static int DEBUG = 2;
    public static int ERROR = 3;

    protected int level;

    /**
     * 责任链中的下一个元素
     */
    protected AbstractLogger nextLogger;

    public void setNextLogger(AbstractLogger nextLogger) {
        this.nextLogger = nextLogger;
    }

    public void logMessage(int level, String message) {
        if (this.level <= level) {
            write(message);
        }
        if (nextLogger != null) {
            nextLogger.logMessage(level, message);
        }
    }

    /**
     * @param message 输出日志
     */
    abstract protected void write(String message);
}
  • 创建扩展了该记录器类的实体类。
@Slf4j
public class ErrorLogger extends AbstractLogger {

    public ErrorLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        log.info("Error Console::Logger: {}", message);
    }
}
@Slf4j
public class FileLogger extends AbstractLogger {

    public FileLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        log.info("File::Logger: {}", message);
    }
}
@Slf4j
public class ConsoleLogger extends AbstractLogger {

    public ConsoleLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        log.info("Standard Console::Logger: {}", message);
    }
}
  • 创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。
public class AppTest {


    private AbstractLogger getChainOfLogs() {
        AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
        AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
        AbstractLogger consoleLogger = new ErrorLogger(AbstractLogger.INFO);
        errorLogger.setNextLogger(fileLogger);
        fileLogger.setNextLogger(consoleLogger);
        return errorLogger;
    }


    @Test
    public void test() {
        AbstractLogger loggerChain = getChainOfLogs();
        loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");
        loggerChain.logMessage(AbstractLogger.DEBUG, "This is a debug level information.");
        loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information.");
    }

}

命令模式

类图

请添加图片描述

定义

  • 命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

实现代码

  • 创建一个命令接口。
public interface Order {

    /**
     * 执行命令
     */
    void execute();

}
  • 命令接口实现类
public class BuyStock implements Order {

    private Stock abcStock;

    public BuyStock(Stock abcStock) {
        this.abcStock = abcStock;
    }

    @Override
    public void execute() {
        abcStock.buy();
    }
}
public class SellStock implements Order {

    private Stock abcStock;

    public SellStock(Stock abcStock) {
        this.abcStock = abcStock;
    }

    @Override
    public void execute() {
        abcStock.sell();
    }
}
  • 创建命令调用类
public class Broker {

    private List<Order> orderList = new ArrayList<>();

    public void takeOrder(Order order) {
        orderList.add(order);
    }

    public void placeOrders() {
        for (Order order : orderList) {
            order.execute();
        }
        orderList.clear();
    }
}
  • 测试类
public class AppTest {

    @Test
    public void test() {
        Stock abcStock = new Stock();

        BuyStock buyStockOrder = new BuyStock(abcStock);
        SellStock sellStockOrder = new SellStock(abcStock);

        Broker broker = new Broker();
        broker.takeOrder(buyStockOrder);
        broker.takeOrder(sellStockOrder);

        broker.placeOrders();
    }
}

解释器模式

类图

请添加图片描述

定义

  • 释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

特点

  • 可扩展性比较好,灵活。 增加了新的解释表达式的方式。 易于实现简单文法。

  • 可利用场景比较少。 对于复杂的文法比较难维护。 解释器模式会引起类膨胀。 解释器模式采用递归调用方法。

实现代码

  • 创建一个表达式接口。
public interface Expression {


    /**
     * 解释
     * @return
     */
    boolean interpret(String context);

}
  • 创建实现了上述接口的实体类。
public class TerminalExpression implements Expression {

    private String data;

    public TerminalExpression(String data) {
        this.data = data;
    }

    @Override
    public boolean interpret(String context) {
        if (context.contains(data)) {
            return true;
        }
        return false;
    }
}
public class AndExpression implements Expression {

    private Expression expression1 = null;
    private Expression expression2 = null;

    public AndExpression(Expression expression1, Expression expression2) {
        this.expression1 = expression1;
        this.expression2 = expression2;
    }

    @Override
    public boolean interpret(String context) {
        return expression1.interpret(context) && expression2.interpret(context);
    }
}
public class OrExpression implements Expression {

    private Expression expression1 = null;
    private Expression expression2 = null;

    public OrExpression(Expression expression1, Expression expression2) {
        this.expression1 = expression1;
        this.expression2 = expression2;
    }

    @Override
    public boolean interpret(String context) {
        return expression1.interpret(context) || expression2.interpret(context);
    }
}
  • InterpreterPatternDemo 使用 Expression 类来创建规则,并解析它们。
@Slf4j
public class AppTest {

    private Expression getMaleExpression() {
        Expression expression = new TerminalExpression("张三");
        Expression expression1 = new TerminalExpression("李四");
        return new OrExpression(expression, expression1);
    }

    private Expression getMarrieWomanExpression() {
        Expression expression = new TerminalExpression("张青");
        Expression expression1 = new TerminalExpression("李玉");
        return new AndExpression(expression, expression1);
    }

    @Test
    public void test() {
        Expression isMale = getMaleExpression();
        Expression isMarriedWoman = getMarrieWomanExpression();
        log.info("张三是男性吗? {} ", isMale.interpret("张三"));
        log.info("张青已婚吗? {} ", isMarriedWoman.interpret("张青"));
        log.info("张青和李玉已婚吗? {} ", isMarriedWoman.interpret("张青 李玉"));
    }
}

迭代器模式

类图

请添加图片描述

定义

  • 迭代器模式(Iterator Pattern)是 Java.Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。迭代器模式属于行为型模式。

实现代码

  • 迭代器接口
public interface Iterator {

    boolean hasNext();
    Object next();
}
public interface Container {

    Iterator getIterator();

}
  • 创建实现了 Container 接口的实体类。该类有实现了 Iterator 接口的内部类 NameIterator
public class Persons implements Container {

    public String[] names = {"张三", "李四", "王五"};

    @Override
    public Iterator getIterator() {
        return new NameIterator();
    }

    private class NameIterator implements Iterator {

        int index;

        NameIterator() {
        }

        @Override
        public boolean hasNext() {
            return index < names.length;
        }

        @Override
        public Object next() {
            if (hasNext()) {
                String s = names[index];
                index++;
                return s;
            }
            return null;
        }
    }
}
  • 测试代码
@Slf4j
public class AppTest {

    @Test
    public void test() {
        Persons persons = new Persons();
        for (Iterator iterator = persons.getIterator(); iterator.hasNext(); ) {
            Object next = iterator.next();
            log.info((String) next);
        }
    }

}

中介者模式

类图

请添加图片描述

定义

  • 中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。

实现代码

  • 创建中介类。
@Slf4j
public class ChatRoom {

    public static void showMessage(User user, String message) {
        log.info(new Date().toString()+user.toString()+": " +message);
    }
}
  • 创建 user 类。
public class User {

    private String name;

    public User(final String name) {
        this.name = name;
    }

    public void sendMessage(String message){
        ChatRoom.showMessage(this,message);
    }

    public String getName() {
        return this.name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • 使用 User 对象来显示他们之间的通信。
public class AppTest {

    @Test
    public void test() {
        User robert = new User("Robert");
        User john = new User("John");

        robert.sendMessage("Hi! John!");
        john.sendMessage("Hello! Robert!");
    }
}

备忘录模式

类图

请添加图片描述

定义

  • 备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。

实现代码

  • 创建 Memento 类。
public class Memento {

    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

}
  • 创建 Originator 类。
public class Originator {


    private String state;

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public Memento saveStateToMemento() {
        return new Memento(state);
    }

    public void getStateFromMemento(Memento Memento) {
        state = Memento.getState();
    }

}
  • 创建 CareTaker 类。
public class CareTaker {

    private List<Memento> mementoList = new ArrayList<Memento>();

    public void add(Memento state) {
        mementoList.add(state);
    }

    public Memento get(int index) {
        return mementoList.get(index);
    }
}
  • 使用 CareTakerOriginator 对象。
@Slf4j
public class AppTest {

    @Test
    public void test() {
        Originator originator = new Originator();
        CareTaker careTaker = new CareTaker();
        originator.setState("State #1");
        originator.setState("State #2");
        careTaker.add(originator.saveStateToMemento());
        originator.setState("State #3");
        careTaker.add(originator.saveStateToMemento());
        originator.setState("State #4");

        log.info("Current State: " + originator.getState());
        originator.getStateFromMemento(careTaker.get(0));
        log.info("First saved State: " + originator.getState());
        originator.getStateFromMemento(careTaker.get(1));
        log.info("Second saved State: " + originator.getState());
    }
}

状态模式

类图

请添加图片描述

定义

  • 在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。
  • 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。

实现代码

  • 创建环境类
public class Context {

    private State state;

    /**
     * 初始化
     */
    public Context() {
        this.state = new ConcreteStateA();
    }

    //对请求做处理
    public void handle() {
        state.Handle(this);
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }
}
  • 抽象状态类
public abstract class State {

    public abstract void Handle(Context context);

}
  • 具体状态类
@Slf4j
public class ConcreteStateA extends State{

    @Override
    public void Handle(Context context) {
        log.info("当前状态是 A");
        context.setState(new ConcreteStateB());
    }
}
@Slf4j
public class ConcreteStateB extends State {

    @Override
    public void Handle(Context context) {
        log.info("当前状态是 B");
        context.setState(new ConcreteStateA());
    }
}
  • 测试代码
public class AppTest {

    @Test
    public void test() {
        Context context = new Context();
        context.handle();
        context.handle();
        context.handle();
        context.handle();
    }
}

访问者模式

类图

请添加图片描述

定义

  • 将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。

实现代码

  • 抽象访问者
public interface Visitor {

    void visit(ConcreteElementA element);

    void visit(ConcreteElementB element);

}
  • 具体访问者
@Slf4j
public class ConcreteVisitorA implements Visitor{

    @Override
    public void visit(ConcreteElementA element) {
        log.info("具体访问者A访问-->" + element.operationA());

    }

    @Override
    public void visit(ConcreteElementB element) {
        log.info("具体访问者A访问-->" + element.operationB());

    }
}
@Slf4j
public class ConcreteVisitorB implements Visitor {

    @Override
    public void visit(ConcreteElementA element) {
        log.info("具体访问者B访问-->" + element.operationA());

    }

    @Override
    public void visit(ConcreteElementB element) {
        log.info("具体访问者B访问-->" + element.operationB());

    }
}
  • 抽象元素类
public interface Element {

    void accept(Visitor visitor);
}
  • 具体元素类
@Slf4j
public class ConcreteElementA implements Element {


    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

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

    }
}
public class ConcreteElementB implements Element {


    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }


    public String operationB() {
        return "具体元素B的操作。";
    }
}
  • 对象结构角色
public 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);
    }

}
  • 测试代码
public class AppTest {


    @Test
    public void test() {
        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);
    }
}

完整代码地址 :https://gitee.com/Marlon_Brando/JavaTest/tree/master/src/main/java/designpatterns

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

全栈程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值