设计模式笔记系列 第三篇

        这篇记录下建造者模式、粉饰器模式、门面模式、观察者模式、代理模式和责任链模式~

1、建造者模式

        (一)、定义

                将一个复杂对象的创建和它的表示分离,使得同样的创建过程可以创建出不同的表示。 通常用于大型复杂对象的创建,并且对于对象的构建有一定的顺序要求。

        (二)、结构

比如我们要创建一个Object对象,我们可以将Object对象的属性按照构建的顺序要求,划分成不同的步骤,封装成一个接口。根据不同的建造顺序,编写不同的实现。然后再写一个Director,来封装对象构建过程,提供一个构建的方法,来输出构建的对象。

        (三)、代码演示
/**
 * @Description: 建造者模式
 */
public interface Builder {
    
    /**
     * @description: 构建第一部分属性接口
     *
     * @param: objectPart1
     * @return: void
     **/
    void buildPart1(String objectPart1);
    
    /**
     * @description: 构建第二部分属性接口
     *
     * @param: objectPart2
     * @return: void
     **/
    void buildPart2(String objectPart2);
    
    /**
     * @description: 构建第三部分属性接口
     *
     * @param: objectPart3
     * @return: void
     **/
    void buildPart3(String objectPart3);

    /**
     * @description: 构建对象
     *
     * @return: BuildObject
     **/
    BuildObject build();
}

/**
 * @Description: 构建对象的实现
 */
public class ObjectBuilder implements Builder {

    private String objectPart1;

    private String objectPart2;

    private String objectPart3;


    @Override
    public void buildPart1(String objectPart1) {
        this.objectPart1 = objectPart1;
    }

    @Override
    public void buildPart2(String objectPart2) {
        this.objectPart2 = objectPart2;
    }

    @Override
    public void buildPart3(String objectPart3) {
        this.objectPart3 = objectPart3;
    }

    @Override
    public BuildObject build() {
        return new BuildObject(this.objectPart1, this.objectPart2, this.objectPart3);
    }
}

/**
 * @Description: 建造者对象
 */
public class BuildObject {

    private String objectPart1;
    private String objectPart2;
    private String objectPart3;

    public BuildObject() {
    }

    public BuildObject(String objectPart1, String objectPart2, String objectPart3) {
        this.objectPart1 = objectPart1;
        this.objectPart2 = objectPart2;
        this.objectPart3 = objectPart3;
    }

    public String getObjectPart1() {
        return objectPart1;
    }

    public void setObjectPart1(String objectPart1) {
        this.objectPart1 = objectPart1;
    }

    public String getObjectPart2() {
        return objectPart2;
    }

    public void setObjectPart2(String objectPart2) {
        this.objectPart2 = objectPart2;
    }

    public String getObjectPart3() {
        return objectPart3;
    }

    public void setObjectPart3(String objectPart3) {
        this.objectPart3 = objectPart3;
    }

    @Override
    public String toString() {
        return "BuildObject{" +
                "objectPart1='" + objectPart1 + '\'' +
                ", objectPart2='" + objectPart2 + '\'' +
                ", objectPart3='" + objectPart3 + '\'' +
                '}';
    }
}

/**
 * @Description: 控制对象的构建
 */
public class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public BuildObject makeObject(String objectPart1, String objectPart2, String objectPart3){
        builder.buildPart1(objectPart1);
        builder.buildPart2(objectPart2);
        builder.buildPart3(objectPart3);
        BuildObject object = builder.build();
        return object;
    }
}

/**
 * @Description: 建造者模式单元测试
 */
public class BuilderTest {

    @Test
    void test(){

        ObjectBuilder objectBuilder = new ObjectBuilder();
        Director director = new Director(objectBuilder);
        BuildObject object = director.makeObject("1", "2", "3");
        System.out.println(object);
    }
}

演示的举证的对象比较简单,这里只是做简单的演示,我们还可以将复杂对象的属性多个划分成一部分一起创建~

2、粉饰器模式

        (一)、定义

                在不改变原有对象的基础上,将功能附加对象上。                

        (二)、结构

如上图,假如现在要在原有的基础上实现一个新的功能,并且不能修改原来的代码,就可以添加一个装饰器Decorator,它持有原来的接口Component(保留原来的功能),同时实现原来的接口,当编写新功能ConcreteDecorator 时,只需要继承装饰器Decorator,便可在原有的功能基础上添加新的功能。

        (三)、代码演示
/**
 * @Description: 装饰者举例:原有功能接口
 */
public interface Component {

    /**
     * @description: 原功能方法
     **/
    void operation();
}

/**
 * @Description: 原有功能实现
 */
public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("煮粥....");
    }
}

/**
 * @Description: 装饰者
 */
public abstract class Decorator implements Component{

    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }
}

/**
 * @Description: TODO
 * @Author: yjduan
 * @CreateTime: 2024-02-05  16:48
 */
public class ConcreteDecorator extends Decorator{


    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        System.out.println("煮粥前添加捣碎的皮蛋、肉丝.");
        component.operation();
    }
}


/**
 * @Description: 装饰者模式单元测试
 */
public class DecoratorTest {

    @Test
    public void test(){
        Component component = new ConcreteDecorator(new ConcreteComponent());
        component.operation();
    }
}

当然,当我们追加功能后,我们还可以利用装饰器继续追加功能~

3、门面模式

        (一)、定义

                为子系统中一组接口提供一个一致的接口,门面模式定义了一个高层接口,使得子系统中的一组接口更加容易使用。                

        (二)、结构

                

门面模式在日常的开发过程会经常使用,也许大家已经使用过多次了。假如在某个系统中有一个工作流,对接了不同的子系统中提供出来的多个方法。我们可以定义一个门面接口,封装这几个子系统中需要用到的方法。把封装后的门面接口,再提供出来使用。这就是门面模式。

        (三)、代码演示

                

/**
 * @Description: 子系统1
 */
public class System1 {

    /**
     * @description: 子系统的方法
     **/
    public void method(){
        System.out.println("子系统1的方法....");
    }
}

/**
 * @Description: 子系统2
 */
public class System2 {

    /**
     * @description: 子系统的方法
     **/
    public void method(){
        System.out.println("子系统2的方法....");
    }
}

/**
 * @Description: 子系统3
 */
public class System3 {

    /**
     * @description: 子系统的方法
     **/
    public void method(){
        System.out.println("子系统3的方法....");
    }
}

/**
 * @Description: 门面模式
 */
public interface Facade {

    /**
     * @description: 门面模式封装的接口
     **/
    void FacadeMethod();
}

/**
 * @Description: 门面模式集成集成实现类
 */
public class ConcreteFacade implements Facade {

    private System1 system1 = new System1();

    private System2 system2 = new System2();

    private System3 system3 = new System3();

    @Override
    public void FacadeMethod() {
        // 子系统1的方法
        system1.method();

        // 子系统2的方法
        system2.method();

        // 子系统3的方法
        system3.method();
    }
}

/**
 * @Description: 门面模式单元测试
 */
public class FacadeTest {

    @Test
    public void test(){
        Facade facade = new ConcreteFacade();
        facade.FacadeMethod();
    }

}

 当我们有多个系统去对接时,只需要根据单元测试一样去使用可以了~


4、观察者模式

        (一)、定义

                 定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者都会收到通知并更新。


        (二)、结构

主题对象Subject 中实现添加、移出、通知观察者得方法,ConcreteSubject 继承主题对象,并持有目标对象状态属性,当状态修改时,同布更新所有观察者。Observer 接口中定义更新观察者得方法,ConcreteObserver 实现观察者接口,在更新方法中回调ConcreteSubject中得getObserverState() 获取目标对象状态。


        (三)、代码演示
/**
 * @Description: 主题对象
 */
public class Subject {
    // 容器,用来保存关注的观察者对象
    private List<Observer> container = new ArrayList<>();

    /**
     * @description: 添加观察者
     *
     * @param: [observer]
     **/
    public void attach(Observer observer){
        container.add(observer);
    }

    /**
     * @description: 移除观察者
     *
     * @param: [observer]
     **/
    public void detach(Observer observer){
        container.remove(observer);
    }

    /**
     * @description: 通知所有的观察者进行更新
     **/
    protected void notifyObservers(){
        for (Observer observer : container) {
            observer.update(this);
        }
    }
}


/**
 * @Description: 目标对象(被监测的对象)
 */
public class ConcreteSubject extends Subject {

    private String observerState;

    public String getObserverState() {
        return observerState;
    }

    /**
     * @description: 修改目标对象状态
     *
     * @param: [observerState]
     * @return: void
     **/
    public void setObserverState(String observerState) {
        this.observerState = observerState;

        // 状态更新时,通知所有观察者
        this.notifyObservers();
    }
}

/**
 * @Description: 观察者接口,
 */
public interface Observer {
    
    /**
     * @description: 更新观察者的接口, 根据目标对象的状态更新
     *
     * @param subject 目标对象
     **/
    void update(Subject subject);
}

/**
 * @Description: 更新观察者实现
 */
public class ConcreteObserver implements Observer {
    @Override
    public void update(Subject subject) {
        // 获取目标对象的状态,更新观察者的状态
        String observerState = ((ConcreteSubject) subject).getObserverState();
        System.out.println("根据目标对象的状态:"+ observerState +",更新所有观察者的状态......");
    }
}

/**
 * @Description: 观察者模式单元测试
 */
public class ObserverTest {

    @Test
    public void test(){
        // 创建两个观察者
        Observer task1 = new ConcreteObserver();
        Observer task2 = new ConcreteObserver();

        // 实例化目标对象
        ConcreteSubject subject = new ConcreteSubject();

        // 目标对象添加观察者
        subject.attach(task1);
        subject.attach(task2);

        // 修改目标对象状态,触发观察者同布更新
        subject.setObserverState("001");
    }
}


5、责任链模式

        (一)、定义

                使多个对象都有机会处理请求,从而避免请求得发送者和接收者之间得耦合关系。将这些对象连成一条链,并沿着这条链传第该请求,直到有一个对象处理它为止。


        (二)、结构

用户提交请求后,交给receiver1、receiver2、receiver3 进行处理,根据各自的职责处理请求。当然如果进入对应的处理环节,如果申请条件不符合,也可以直接拒绝,中断申请。


        (三)、代码演示
/**
 * @Description: 责任链模式
 */
public abstract class Handler {

    /** 持有下一个的责任对象*/
    protected Handler next = null;

    /** 设置下一个处理请求的对象*/
    public void setNext(Handler next) {
        this.next = next;
    }

    /**
     * @description: 处理请求得方法
     *
     * @param: days 请假的天数
     * @return: boolean 请假审批的结果通知
     **/
    public abstract boolean handleRequest(Integer days);
}

/**
 * @Description: 经理处理请求
 */
public class ManagerHandler extends Handler {
    @Override
    public boolean handleRequest(Integer days) {
        // 部门经理只能审批7天内的请假申请
        if(days <= 7) {
            System.out.println("部门经理已同意....");
            return true;
        } else {
            // 当前的申请还未处理, 交给直接上级(下一个请求链)进行处理
            if(this.next != null) {
                return this.next.handleRequest(days);
            }
        }
        return false;
    }
}

/**
 * @Description: 部门负责人处理请求
 */
public class SectionHeadHandler extends Handler {
    @Override
    public boolean handleRequest(Integer days) {
        // 部门负责人能够处理一个月内的请假申请
        if(days <= 30){
            System.out.println("部门负责人已同意....");
            return true;
        } else {
            // 如果还未处理
            if (null != next){
                return this.next.handleRequest(days);
            }
        }
        return false;
    }
}

/**
 * @Description: 总经理处理请求
 */
public class MasterHandler extends Handler {
    @Override
    public boolean handleRequest(Integer days) {
        // 超过一个月的请假申请总经理处理
        if(days > 30){
            System.out.println("总经理已同意.....");
            return true;
        } else {
            if(null!=next){
                return this.next.handleRequest(days);
            }
        }
        return false;
    }
}

/**
 * @Description: 责任链模式单元测试
 */
public class ChinaTest {

    @Test
    public void test(){
        // 申明责任链路
        Handler managerHandler =  new ManagerHandler();
        Handler sectionHeadHandler =  new SectionHeadHandler();
        Handler masterHandler =  new MasterHandler();

        // 设置请求处理的链路
        managerHandler.setNext(sectionHeadHandler);
        sectionHeadHandler.setNext(masterHandler);

        // 场景测试
        Integer days = 15;
        boolean result = managerHandler.handleRequest(days);
        System.out.println("处理结果:"+ result);
    }
}

以上的例子,根据公司请假的流程写了一个简单demo,以供后续参考~


6、代理模式

        (一)、定义

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


        (二)、结构

        Subject 封装访问对象的接口,realSubject 是实际subject 的实现,proxy 是代理对象。当需要访问realSubject 中已存在数据的属性时,可以直接从realSubject 中直接获取,但如果是realSubject 未加载值的属性,则利用代理对象重新加载realSubject 中不存在的数据。


        (三)、代码演示

根据公司组织架构编写一个简单的demo,假如为了节省资源只加载员工表id和员工名称,当需要进一步查询员工信息时,再利用代理加载未加载的属性。

/**
 * @Description: 员工属性Api
 */
public interface EmpApi {

    public Long getId();

    public void setId(Long id);

    public String getJobNumber();

    public void setJobNumber(String jobNumber);

    public String getName();

    public void setName(String name);

    public Integer getSex();

    public void setSex(Integer sex);

    public String getAddr();

    public void setAddr(String addr);
}

/**
 * @Description: 员工属性接口具体的实现(需要被代理的对象)
 */
public class RealEmp implements EmpApi {
    private Long id;
    private String name;
    private String jobNumber;
    private Integer sex;
    private String addr;

    @Override
    public Long getId() {
        return this.id;
    }

    @Override
    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public String getJobNumber() {
        return this.jobNumber;
    }

    @Override
    public void setJobNumber(String jobNumber) {
        this.jobNumber = jobNumber;
    }

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

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

    @Override
    public Integer getSex() {
        return this.sex;
    }

    @Override
    public void setSex(Integer sex) {
        this.sex = sex;
    }

    @Override
    public String getAddr() {
        return this.addr;
    }

    @Override
    public void setAddr(String addr) {
        this.addr = addr;
    }
}


/**
 * @Description: 代理对象,代理具体的员工属性实现
 */
public class EmpProxy implements EmpApi {

    /** 持有被代理的目标对象*/
    private RealEmp realEmp = null;

    /** 标示属性是否需要重新加载*/
    private Boolean reloadFlag = false;

    public EmpProxy(RealEmp realEmp) {
        this.realEmp = realEmp;
    }


    // 已经记载过的属性,从原数据对象上直接返回
    @Override
    public Long getId() {
        return realEmp.getId();
    }

    @Override
    public void setId(Long id) {
        realEmp.setId(id);
    }

    @Override
    public String getName() {
        return realEmp.getName();
    }

    @Override
    public void setName(String name) {
        realEmp.setName(name);
    }


    // 未加载过的对象,重新从数据中加载
    @Override
    public String getJobNumber() {
        // 判断是否需要重新加载
        if(!this.reloadFlag){
            // 数据不存在,重新加载
            reload();
            this.reloadFlag = true;
        }
        return realEmp.getJobNumber();
    }

    @Override
    public void setJobNumber(String jobNumber) {
        realEmp.setJobNumber(jobNumber);
    }

    @Override
    public Integer getSex() {
        // 判断是否需要重新加载
        if(!this.reloadFlag){
            // 数据不存在,重新加载
            reload();
            this.reloadFlag = true;
        }
        return realEmp.getSex();
    }

    @Override
    public void setSex(Integer sex) {
        realEmp.setSex(sex);
    }

    @Override
    public String getAddr() {
        // 判断是否需要重新加载
        if(!this.reloadFlag){
            // 数据不存在,重新加载
            reload();
            this.reloadFlag = true;
        }
        return realEmp.getAddr();
    }

    @Override
    public void setAddr(String addr) {
        realEmp.setAddr(addr);
    }

    private void reload() {
        System.out.println("重新加载不存在的员工数据.....");
        this.realEmp.setJobNumber("001");
        this.realEmp.setSex(0);
        this.realEmp.setAddr("湖北武汉...");
    }
}

/**
 * @Description: 代理模式单元测试
 */
public class EmpPoxyTest {

    @Test
    public void test(){

        // 首先只加载id和name : 部分加载的时候,需要给代理对象赋值,而不是被代理的目标对象
        EmpApi emp = new EmpProxy(new RealEmp());
        emp.setId(1L);
        emp.setName("张三");

        // 访问已加载的数据
        System.out.println(emp.getName());
        
        // 访问开始未加载的数据
        System.out.println(emp.getJobNumber());
    }
}

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值