zoukankan      html  css  js  c++  java
  • 设计模式学习总结(Java版)

    设计模式学习总结

    设计模式只是一种指导思想

    共23种设计模式 ,尽量精简,方便复习,编程语言是Java

    单例模式

    概述:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个唯一的实例。

    要点:构造方法是private、有当前类的静态成员变量,用static修饰、实例只能在内部实例化

    作用:确保一个类只有一个实例存在,方便控制对象,节省资源

    举例:序列号生成器,Web页面的计数器,创建消耗大的对象,spring IOC容器,Runtime类,Proxy类

    实现:饿汉式、懒汉式、枚举类。。。。。 注意并发/多线程的情况

    简单工厂模式

    概述:又称静态方法工厂模式,它属于类创建型模式。可根据参数的不同返回不同类的实例。就专门定义一个类来负责创建其他类实例的。被创建的实例通常都具有共同的父类。

    要点:它知道每个产品,它决定哪个产品应当被实例化,而无需知道创建细节。一般使用静态方法(就不能在子类中对其进行扩展)。

    作用:解耦 解耦 解耦,将实例化对象的代码提取出来,放到一个类中管理维护。

    举例:DateFormat类,Calendar类,Logger类,JDBC中Connection对象的获取;

    实现:

    public class SimpleCarFactory {
        public static Car getCar(String type) {
            if (type.equalsIgnoreCase("BMW")) {
                // ....
                return new BMWCard();
            } else if (type.equalsIgnoreCase("Audi")) {
                // ....
                return new AudiCard();
            } else throw new IllegalArgumentException("No such brand!");
        }
    }
    

    工厂模式

    概述:定义一个用于创建对象的接口(抽象),让子类(具体)决定实例化哪个类,工厂方法使一个类的实例化延迟到子类。在工厂模式中新增一个产品,不改原有的工厂类,而是新增一个工厂(别问,问就是开闭原则,扩展优于修改。符合单一职责原则,每个具体工厂类只负责创建对应的产品)

    要点:工厂类是抽象的,它定义工厂应该有哪些方法,然后有很多实现类 比如工厂A,工厂B。一个工厂只能创建一种具体产品

    举例:Collection接口中Iterator的生成,具体工厂如LinkedList,ArrayList 抽象产品如Iterator,具体产品就是ListItr,Itr

    实现:

    interface AbstractCarFactory {
        Car createCar();
    }
    
    class BWMCarFactory implements  AbstractCarFactory{
        @Override
        public Car createCar() {
            return new BWMCar();
        }
    }
    
    class AudiCarFactory implements AbstractCarFactory{
        @Override
        public Car createCar() {
            return new AudiCar();
        }
    }
    

    扩展:设计模式的依赖抽象原则

    • 创建对象实例时,不要直接 new 类, 而是把这个new 类的动作放在一个工厂的方法中,并返回。有的书上说,变量不要直接持有具体类的引用。
    • 不要让类继承具体类,而是继承抽象类或者是实现interface(接口)
    • 不要覆盖基类中已经实现的方法。

    抽象工厂模式

    概述:工厂模式下只能创建一大类的产品, 抽象工厂使得工厂不单单生成那具体的某一大类,还可以生产其他大类产品。它打破工厂与具体产品的一对一关系。是工厂模式的一种扩展。 它能创建一系列相关或相互依赖的对象, 而无需指定其具体类。

    要点:添加新产品要修改抽象工厂和具体工厂的代码,也不是声明为abstract的简单工厂

    举例:Spring的BeanFactory类,Java.sql包,Collection接口,涉及到产品系列

    装饰器模式

    概述:动态地给一个对象添加一些额外的功能。就增加功能来说,装饰模式比生成子类更加灵活。是继承关系的一个替代方案。在不影响其他对象的情况下, 以动态、 透明的方式给单个对象添加职责。

    要点:动态地为对象添加功能。不改变原类文件。抽象装饰器与具体被装饰对象实现同一个接口。抽象装饰器持有被装饰器接口对象,以便请求传递。

    举例:机器人功能扩展。给人穿件衣服。java.util.Collections#checkedXXX()、synchronized­XXX()。Java的IO流,比如InputStream有各种FileInputStream,FilterInputStream等等(具体可以查看类图)。javax.servlet.http.HttpServletRequestWrapper 和 Http­Servlet­Response­Wrapper

    /**
     * 装饰器模式之机器人功能升级案例
     */
    public class DecoratorPattern {
        public static void main(String[] args) {
            new RobotDecorator(new FirstRobot()).doMoreThing();
        }
    }
    
    interface Robot {
        void doSomething();
    }
    
    /**
     * 第一代机器人
     */
    class FirstRobot implements Robot {
    
        @Override
        public void doSomething() {
            System.out.println("唱歌");
            System.out.println("对话");
        }
    }
    
    /**
     * 机器人装饰器
     * 定义为抽象类后,可以定义其子类去实现更多装饰器(更灵活)
     */
    class RobotDecorator implements Robot {
        private Robot robot;
    
        public RobotDecorator(Robot robot) {
            this.robot = robot;
        }
    
        @Override
        public void doSomething() {
            this.robot.doSomething();
        }
    
        public void doMoreThing() {
            this.robot.doSomething();
            System.out.println("跳舞、拖地");
        }
    }
    

    适配器模式

    概述:将一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法工作在一起的两个类能够在一起工作。

    要点:Adapter and Adaptee ,关联 or 继承。不改变原来的接口,只提供转换的作用。

    举例:翻译者、InputStreamReader、Spring MVC

    public class AdapterPattern {
        public static void main(String[] args) {
            System.out.println(new SpeakAdapter(new Speaker()).translate());
        }
    }
    class Speaker {
        public String speak() {
            return "aba,aba";
        }
    }
    interface Translate {
        String translate();
    }
    class SpeakAdapter implements Translate {
        private Speaker speaker;
        public SpeakAdapter(Speaker speaker) {
            this.speaker = speaker;
        }
        @Override
        public String translate() {
            String result = speaker.speak();
            result = result.replace(',', ',');
            // 适配过程,处理。。。
            return result;
        }
    }
    

    观察者模式

    概述:定义对象间的一种一对多的依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。例:通知者(欠债人)和被通知者(债主子)的依赖关系(欠债的人能还钱了再去通知债主子,而不用债主天天询问),在设计模式中被成为观察者模式也成为发布订阅模式。

    要点:

    1. 多个订阅者称为观察者:Observer多个观察者观察的对象被称为目标:Subject,Subject维持多个Observer

    2. 要避免之间发生依赖 。

    3. 观察者和被观察者,是松耦合的关系,发布者和订阅者,则完全不存在耦合

    4. 观察者模式有两种重要的策略:

    • Push - 当一个事件发生后将通知所有观察者,并把所有的新数据传给他们 function:notify()

    • Pull - 当一个事件发生后将通知所有观察者,每个观察者将拉取自己需要的数据 function:update(xx)

    1. 观察者模式,多用于单个应用内部、发布订阅模式,则更多的是一种跨应用的模式,比如我们常用的消息中间件

    举例:Vue数据的双向绑定子组件与父组件通信、所有浏览器事件的绑定、

    public class ObservePattern {
        public static void main(String[] args) {
            借款人张三 借款人张三对象 = new 借款人张三();
            借款人张三对象.借钱(new 贷款人A());  借款人张三对象.借钱(new 贷款人B());
            借款人张三对象.通知借款方();  // 状态改变后进行通知:有钱了
        }
    }
    
    interface Debit {
        void 借钱(Credit credit);
        void 通知借款方();
    }
    
    class 借款人张三 implements Debit {
        private List<Credit> allCredit = new ArrayList<Credit>();
        public void 借钱(Credit credit) {
            allCredit.add(credit);
        }
        public void 通知借款方() {
            allCredit.forEach(Credit::takeMoney);
        }
    }
    
    interface Credit {
        void takeMoney();
    }
    
    class 贷款人A implements Credit {
        public void takeMoney() {
            System.out.println("A要钱");
        }
    }
    class 贷款人B implements Credit {
        public void takeMoney() {
            System.out.println("B要钱");
        }
    }
    

    外观模式

    概述: 它通过先现有的系统添加一个新的接口,去隐藏掉系统的复杂性。

    要求一个子系统的外部与内部的通信必须通过一个统一的对象进行。

    外观模式提供一个高层次的接口,使得子系统更易使用。

    要点:子系统修改,外观类也要修改

    举例:

    状态模式:

    概述:允许一个对象在其内部状态改变时改变你它的行为,对象看起来似乎 修改了它的类。其别名为状态对象,状态模式是一种对象行为型模式。(我因)

    要点:封装转换规则,并枚举可能的状态

    举例:

    public class StatePattern {
        public static void main(String[] args) {
            Someone yuan = new Someone();
            yuan.changeState(new HappyState());
            yuan.doSomething();
            yuan.changeState(new SadState());
            yuan.doSomething();
        }
    }
    
    interface State {
        void doWork();
    }
    
    class HappyState implements State {
        public void doWork() { System.out.println("开心的工作"); }
    }
    
    class SadState implements State {
        public void doWork() { System.out.println("难过的工作"); }
    }
    
    class Someone {
        private State state;
        void changeState(State s) { this.state = s; }
        void doSomething() { this.state.doWork(); }
    }
    

    策略模式

    概述:定义一组算法,将每个算法都封装起来,并且使得他们之间可以相互转换。策略模式让算法独立于使用它的客户而变化,也成为政策模式。(我想)

    要点:关注行为,客户端指定

    举例:自助洗衣机根据不同策略(标准,大物,脱水)选择不同洗衣算法、

    代理模式

    概述:为其他对象提供一种代理以控制对这个对象的访问。 (中间层)

    要点:必须要通过代理类来访问目标对象。代理类包含一个指向服务对象的引用成员变量。

    举例:AOP,上谷歌

    责任链模式

    概述:责任链模式是一种处理请求的模式,他让多个处理器都有机会处理该请求,直到其中某个处理成功为止。责任链模式把多个处理器串成链,然后让请求在链上传递。

    要点:处理类要有个方法指向下一个处理类

    举例:过滤器

    public class ChainRespPattern {
        public static void main(String[] args) {
            Handler l1 = new Leader();
            Handler l2 = new Boss();
            l1.setNextHandler(l2);
            l1.process(10);
            l1.process(12);
        }
    }
    
    abstract class Handler {
        protected Handler nextHandler;
        public void setNextHandler(Handler nextHandler) {
            this.nextHandler = nextHandler;
        }
        public abstract void process(Integer info);
    }
    class Leader extends Handler {
        public void process(Integer info) {
            if (info < 11)
                System.out.println("Leader处理");
            else nextHandler.process(info);
        }
    }
    class Boss extends Handler {
        public void process(Integer info) {
            System.out.println("Boss处理");
        }
    }
    

    模板方法模式

    概述:定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤

    要点:要有个调用未实现步骤的模板方法。封装不变的部分,扩展可变的部分.行为由父类控制,具体由子类实现

    实现:

    public class TemplateMethodPattern {
        public static void main(String[] args) {
            Cooking cooking=new CookingFood();
            cooking.cook();
        }
    }
    
    abstract class Cooking {
        protected abstract void step1();
        protected abstract void step2();
        public void cook(){
            System.out.println("做饭开始");
            step1();
            step2();
            System.out.println("做饭结束");
        }
    }
    class CookingFood extends Cooking{
        @Override
        protected void step1() {
            System.out.println("放西红柿");
        }
        @Override
        protected void step2() {
            System.out.println("少盐少味精");
        }
    }
    

    享元模式

    概述:运用共享技术有效地支持大量系类度的对象。享:共享同一个元素。

    要点:有一个FlyweightFactory,也称池容器

    实现:百度网盘MD5相同的文件只保存一份、池技术!!!、共享单车

    import java.util.HashSet;
    import java.util.Set;
    
    public class FlyweightPattern {
        public static void main(String[] args) {
            BikeFlyweightFactory.getInstance().getBike().ride("11");
        }
    }
    
    abstract class BikeFlyweight {
        // 内部状态 0未使用 1在使用
        protected Integer state = 0;
        abstract void ride(String username);
        abstract void back();
        public Integer getState() {return state;}
    }
    
    class MoBikeFlyWeight extends BikeFlyweight {
        private String bikeId;
    
        public MoBikeFlyWeight(String bikeId) {
            this.bikeId = bikeId;
        }
        @Override
        void ride(String username) {
            state = 1;
            System.out.println(username + " 骑行 " + bikeId + " 号自行车出行");
        }
        @Override
        void back() {
            state = 0;
        }
    }
    
    class BikeFlyweightFactory {
        private static BikeFlyweightFactory instance = new BikeFlyweightFactory();
        private Set<BikeFlyweight> pool = new HashSet<>();
    
        public BikeFlyweightFactory() {
            for (int i = 0; i < 2; i++) {
                pool.add(new MoBikeFlyWeight(i + "号"));
            }
        }
        public BikeFlyweight getBike() {
            for (BikeFlyweight bike : pool) {
                if (bike.getState() == 0)
                    return bike;
            }
            return null;
        }
        public static BikeFlyweightFactory getInstance() {
            return instance;
        }
    }
    

    命令模式

    概述:简单来说就是充当中间层。命令模式是一种行为设计模式,它可将请求转换为一个包含与请求相关的所有信息的独立对象。该转换让你能根据不同的请求将方法参数化、延迟请求执行或将其放入队列中,且能实现可撤销操作。

    要点:将一组行为抽象为对象,这个对象和其他对象一样可以被存储传递,从而实现行为请求者与行为实现者之间的松耦合。

    未详细看

    实例:撤消,重做

    建造者模式

    概述:代码是模板性的。通过生成器可以避免将所有的构造步骤全部放到构造函数里,使得可以分步骤生成对象。

    要点:用主管类(生成器)来创建步骤的执行顺序。生成器是目标类里的静态类。简单对象就可以不用。

    实例:new House.Builder().setDoor().setWall()....build();,也可以用Lombok的@Builder 生成静态生成器类

    原型模式

    概述:原型模式是解决复制对象的问题的。原型模式将复制的过程称为克隆。原型模式将克隆过程委派给被克隆的对象。

    要点:原型模式为支持克隆的对象提供一个通用的接口.clone()

    备忘录模式

    概述:备忘录模式是一种行为设计模式,允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。它建议我们将对象内部状态的副本存储到备忘录对象中。

    要点:只有创建备忘录的对象可以访问备忘录的内容。当然也可以提供元数据信息给其他对象。

    实例:编辑器的撤回功能

    迭代器模式

    概述:迭代器模式是一种行为设计模式,让你能在不暴露集合底层表现形式的情况下遍历集合中的所有元素。

    要点:将集合的遍历行为抽取为单独的迭代器对象

    实例:java中集合的iterator

    组合模式

    概述:结构型模式,可以使用它将对象组合成树状结构,并且能够像使用独立对象一样使用他们。

    要点:树形结构中主要包含两类元素leafComposite,叶子完成实际工作,容器也要完成工作,不过工作是交给它下级进行处理。

    实例:人口普查、递归

    桥接模式

    概述:将继承关系转换成关联关系,降低类与类之间的耦合,减少了代码量的编写,提高系统灵活性。将抽象和实现解耦,使得两者可以独立变化。

    要点:一个维度关联另一个维度。要多花心思设计

    实例:

    public class BridgePattern {
        public static void main(String[] args) {
            new XueLi(new OnlineSaleChannel(), "雪梨").doWork();
        }
    }
    // 饮料基本类
    abstract class BaseDrink {
        private SaleChannel saleChannel;
        private String name;
    
        public BaseDrink(SaleChannel saleChannel, String name) {
            this.saleChannel = saleChannel;
            this.name = name;
        }
    
        public void doWork(){
            System.out.println("is drink:"+name);
            this.saleChannel.sale();
        }
    }
    // 冰糖雪梨
    class XueLi extends BaseDrink{
        public XueLi(SaleChannel saleChannel, String name) {
            super(saleChannel, name);
        }
    }
    // 销售渠道 另一个维度
    interface SaleChannel {
         void sale();
    }
    class OnlineSaleChannel implements SaleChannel {
        @Override
        public void sale() {
            System.out.println("线上销售");
        }
    }
    

    中介者模式

    概述:中介者模式是一种行为设计模式,能让你减少对象之间混乱无序的依赖关系。该模式会限制对象之间的直接交换,迫使它们通过一个中介者对象进行合作。

    要点:将系统的网状结构变成以中介者为核心的星状结构,中介者负责中转和协调。

    实例:租房&中介,婚介所&媒人、

    访问者模式

    概述: 访问者模式用于封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作

    要点:定义访问者类。原有的要预留对访问者类的支持(+accpet(Vistor v); ),让访问者类可以访问他的内在数据。v.doForXXX(this)


    分类

    • 创建型模式提供创建对象的机制, 增加已有代码的灵活性和可复用性。
    • 结构型模式介绍如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效。
    • 行为模式负责对象间的高效沟通和职责委派。
    创建型模式 结构型模式 行为模式
    工厂方法模式 适配器模式 模板方法模式
    抽象工厂模式 桥接模式 访问者模式 Visitor
    生成器模式 组合模式 迭代器模式
    原型模式 装饰模式 中介者模式
    外观模式 备忘录模式
    享元模式 观察者模式
    代理模式 责任链模式
    策略模式
    状态模式
    命令模式

    参考

  • 相关阅读:
    1046 Shortest Distance (20 分)(模拟)
    1004. Counting Leaves (30)PAT甲级真题(bfs,dfs,树的遍历,层序遍历)
    1041 Be Unique (20 分)(hash散列)
    1036 Boys vs Girls (25 分)(查找元素)
    1035 Password (20 分)(字符串处理)
    1044 Shopping in Mars (25 分)(二分查找)
    onenote使用小Tip总结^_^(不断更新中...)
    1048 Find Coins (25 分)(hash)
    三个故事
    领导者的举止
  • 原文地址:https://www.cnblogs.com/somegenki/p/13993747.html
Copyright © 2011-2022 走看看