zoukankan      html  css  js  c++  java
  • 《大话设计模式》读书笔记(四)

    写在前面

    本文上接《大话设计模式》读书笔记(三),本次主要介绍三种设计模式,外观模式,建造者模式和观察者模式。

    7.外观模式(Facade Pattern)

    解决的问题

    外观模式,正像它的名字。对于一些实现十分复杂,但使用者又没必要知道这些复杂细节的时候,外观模式可以提供一个统一的简单接口。外观模式主要用于将层与层之间分离,提供简单接口等等功能。

    类图结构

    image-20201128155728734

    在图中,Facade是外观类,知道哪些子系统负责处理请求,将客户的请求代理给适当的字系统对象。下面四个子类是子系统类的集合,实现子系统的功能,处理Facade对象指派的任务。子类中没有Facade的任何信息。

    四个子系统的代码:

    public class SubSystemOne{
        public void methodOne(){
            System.out.println("子系统方法一");
        }
    }
    
    public class SubSystemTwo{
        public void methodTwo(){
            System.out.println("子系统方法二");
        }
    }
    public class SubSystemThree{
        public void methodThree(){
            System.out.println("子系统方法三");
        }
    }
    public class SubSystemFour{
        public void methodFour(){
            System.out.println("子系统方法四");
        }
    }
    

    外观类:

    public class Facade{
        SubSystemOne one;
        SubSystemTwo two;
        SubSystemThree three;
        SubSystemFour four;
        
        public Facade(){
            one = new SubSystemOne();
            two = new SubSystemTwo();
            three = new SubSystemThree();
            four = new SubSystemFour();
        }
        
        public void methodA(){
           System.out.println("方法组A()");
           one.methodOne();
           two.methodTwo();
           four.methodFour();
        }
        
        public void methodB(){
            System.out.println("方法组B()");
            two.methodTwo();
            three.methodThree();
        }
    }
    

    好处与坏处

    优点在之前的介绍中都写过了,外观模式可以简化系统的调用,同时符合迪米特法则,降低了应用层和子系统之间的耦合度。也正因如此,外观模式的缺点也就体现在不符合开闭原则。在我们拓展子系统的时候,必然要去修改子系统的代码,这显然违背了开闭原则。

    8.建造者模式(Builder Pattern)

    解决的问题

    建造者模式,将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。多用于在将一个复杂对象的构建与表示分离的情况下。在这种模式下,用户只需指定建造的类型即可得到一个对象,而无需知道具体的构建细节。

    类图结构

    image-20201128161203284

    如图,Builder代表一个建造者类,是一个为创建一个Product对象的各个部件指定的抽象接口。ConcreteBuilder是具体的建造者,实现了Builder接口,构造和装配各个部件。Director类为指挥者类,是构建一个使用Builder接口的对象。Product自然是具体的产品类了,不用多说了。

    Product类:

    public class Product{
        List<String> parts = new ArrayList<String>();
        
        public void add(String part){
            parts.add(part);
        }
        
        public void show(){
            System.out.println("开始创建产品...");
            for(String part:parts){
                System.out.println(part);
            }
        }
    }
    

    Builder类

    public abstract class Builder{
        abstract void buildPartA();
        abstract void buildPartB();
        abstract Product getResult();
    }
    

    ConcreteBuilder类

    public class ConcreteBuilder extends Builder{
        private Product product = new Product();
        
        @Override
        public void buildPartA(){
            product.add("部件X");
        }
        
        @Override
        public void buildPartB(){
            product.add("部件Y");
        }
        
        @Override
        public Product getResult(){
            return product;
        }
    }
    

    Director类:

    public class Director{
        public void construct(Builder builder){
            builder.buildPartA();
            builder.buildPartB();
        }
    }
    

    好处与坏处

    好处为,使用建造者模式可以使得客户端不必知道产品内部组成的细节,具体的建造者类之间是互相独立的,这有助于系统的扩展。但由于建造者模式创建的产品大多都具有类似的特征,因此建造者模式的使用范围很窄。如果产品的内部变化复杂,会需要很多的具体建造者类来实现,会让系统变得十分复杂。

    9.观察者模式(Observer Pattern)

    解决的问题

    观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。让这个主题对象在状态发生变化的时候会自动通知所有观察者对象,使得他们可以自己更新自己。

    类图结构

    image-20201128162831150

    Subject类,它把所有的观察者对象的引用保存在一个聚集里,每个主题可以有任意数量的观察者,抽象主题提供一个可以增加和删除观察者对象的接口。Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。ConcreteObserver类,具体观察者,实现了抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相一致。ConcreteSubject类,具体主题,将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记的观察者发出通知。

    Subject类:

    public abstract class Subject{
        private List<Observer> observers = new List<Observer>();
        
        public void attach(Observer observer){
            observers.add(observer);
        }
        
        public void detach(Observer observer){
            observers.remove(observer);
        }
        
        public void notify(){
            for(Observer o : observers){
                o.update();
            }
        }
    } 
    

    Observer类:

    public abstract class Observer{
        public abstract void update();
    }
    

    ConcreteSubject类:

    public class ConcreteSubject extends Subject{
        private String subjectState;
        
        public String getSubjectState(){
            return subjectState;
        }
        public void setSubjectState(String SubjectState){
            this.subjectState = subjectState;
        }
    }
    

    ConcreteObserver类:

    public class ConcreteObserver extends Observer{
        private String name;
        private String observerState;
        private ConcreteSubject subject;
        
        public ConcreteObserver(ConcreteSubject subject,String name){
            this.subject = subject;
            this.name = name;
        }
        
        @Override
        public void update(){
            observerState = subject.subjectState;
            System.out.println("观察者" + name + "的新状态是" + observerState);
        }
        
        public ConcreteSubject getSubject(){
            return subject;
        }
        
        public void setSubject(ConcreteSubject subject){
            this.subject = subject;
        }
    }
    

    好处与坏处

    观察者模式的效果有以下的优点:

    第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

    第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知,

    观察者模式有下面的缺点:

    第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

    第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。

    第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

    第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

    总结

    总的来说,这次学习了三个设计模式。

  • 相关阅读:
    Oracle 按一行里某个字段里的值分割成多行进行展示
    Property or method "openPageOffice" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by
    SpringBoot 项目启动 Failed to convert value of type 'java.lang.String' to required type 'cn.com.goldenwater.dcproj.dao.TacPageOfficePblmListDao';
    Maven 设置阿里镜像
    JS 日期格式化,留作参考
    JS 过滤数组里对象的某个属性
    原生JS实现简单富文本编辑器2
    Chrome控制台使用详解
    android权限(permission)大全
    不借助第三方网站四步实现手机网站转安卓APP
  • 原文地址:https://www.cnblogs.com/wushenjiang/p/14053088.html
Copyright © 2011-2022 走看看