乐趣区

关于设计模式:一文总结设计模式

前言

  • 看了很多寓教于学写设计模式的,看的有点头疼,注意力全都在故事上了,满脑子都是鸭子,餐厅之类,还有一堆和设计模式不相干的话,翻书都翻的挺累的。
  • 这里我整顿了下 23 种设计模式,没什么多余的话,代码演示,简略粗犷,借鉴的中央都附上了参考链接(做个优良的搬运工),没附上的是本人总结的。
  • 借鉴的例子代码,根本都做了一些精简,如果相干例子写的有什么不精确,麻烦在评论外面指出来,最好附上代码,我会尽快修改文章中的相干实例
  • 23 种设计模式,一文出现,不便大家和本人查问,也不便本人随时批改,请配合文章旁边的纲要食用。

总述

7 种面向对象设计准则

设计准则名称 定 义
繁多职责准则(Single Responsibility Principle, SRP) 一个类只负责一个性能畛域中的相应职责
开闭准则(Open-Closed Principle, OCP) 软件实体应答扩大凋谢,而对批改敞开
里氏代换准则(Liskov Substitution Principle, LSP) 所有援用基类对象的中央可能通明地应用其子类的对象
迪米特法令(Law of Demeter, LoD) 一个软件实体该当尽可能少地与其余实体产生相互作用
接口隔离准则(Interface Segregation Principle, ISP) 应用多个专门的接口,而不应用繁多的总接口
依赖倒转准则(Dependence Inversion Principle, DIP) 形象不应该依赖于细节,细节应该依赖于形象
合成复用准则(Composite Reuse Principle, CRP) 尽量应用对象组合,而不是继承来达到复用的目标
  • 设计模式可分为创立型 (Creational),结构型(Structural) 和行为型 (Behavioral) 三种
    • 创立型模式次要用于形容如何创建对象(5 种)
    • 结构型模式次要用于形容如何实现类或对象的组合(7 种)
    • 行为型模式次要用于形容类或对象怎么交互以及怎么调配职责(11 种)
  • 图解

准则简述

1. 繁多职责准则

定义:一个类只有一个引起它变动的起因。

了解:对性能进行分类,代码进行解耦,一个类只管一件事

举例:就比方一个网络申请框架大体分为:申请类,缓存类,配置类,不能把这 3 个混在一起,必须分为 3 个类去实现不同的性能。

2. 开闭准则

定义:一个实体(类、函数、模块等)应该对外扩大凋谢,对内批改敞开

了解:每次发生变化时,要通过新增代码来加强现有类型的行为,而不是批改原有代码。

举例:就比方在软件的生命周期内,因为产品迭代,软件降级保护等起因,须要对原有代码进行批改时,可能会给原有代码引入谬误,也可能使得咱们对整个性能不得不进行重构,并且须要对原有代码进行从新测试,这样的话,对开发周期影响很大,所以开闭准则刚好解决这个问题。

3. 里氏替换准则

定义:继承必须确保超类所领有的性质在子类中依然成立。

了解:在继承类时,除了扩大一些新的性能之外,尽量不要删除或者批改对父类办法的援用,也尽量不要重载父类的办法。

举例:你看啊,就比方 Object 有个办法,叫 equals,如果不恪守里氏代替准则,它的子类重载了 equals 这个办法,并且返回了个 null,这个子类的下一个继承者也会返回 null,那么,在不同开发人员开发时,可能思考不到这个问题,那么就可能导致程序解体。

4. 迪米特法令

定义:一个模块或对象应尽量少的与其余实体之间产生相互作用,使得零碎功能模块绝对独立,这样当一个模块批改时,影响的模块就会越少,扩大起来更加容易。

了解:一个对象应该对其余对象有起码的理解;一个类应该对本人须要耦合或调用的类晓得得起码,类的外部如何实现、如何简单都与调用者或者依赖者没关系,调用者或者依赖者只须要晓得他须要的办法即可,其余的一律不关怀。类与类之间的关系越亲密,耦合度越大,当一个类产生扭转时,对另一个类的影响也越大。

举例:个别在应用框架的时候,框架的开发者会抽出一个类供内部调用,而这个次要的类像是一个中介一样去调用框架外面的其余类,恰好框架外面其余类个别都是不可拜访(调用)的,这个框架就恪守了迪米特准则,其余开发人员只关怀调用的办法,并不需要关怀性能具体如何实现。

5. 接口隔离准则

定义:应用多个专门性能的接口,而不是应用繁多的总接口

了解:在定义接口办法时应该合理化,尽量谋求简略最小,防止接口臃肿

举例:在理论开发中,往往为了节省时间,可能会将多个性能的办法抽成一个接口,其实这设计理念不正确的,这样会使接口处于臃肿的状态,这时就须要正当的拆分接口中的办法,另外抽取成一个独立的接口,防止原有的接口臃肿导致代码了解艰难。

6. 依赖倒置准则

定义:细节应该依赖于形象,而形象不应该依赖于细节

了解:高层模块不依赖低层次模块的细节,不依赖具体的类,而是依赖于接口

举例:比如说咱们写一个网络框架,为了满足不同开发者的需要,即能应用高效的 OkHttp 框架,也能够应用原生的 API。那么是如何进行切换的呢,这个时候须要面向接口编程思维了,把一些网络申请的办法封装成一个接口,而后别离创立 OkHttp 和原生 API 的接口实现类,当然也能够扩大其余网络框架的利用。

7. 合成复用准则

定义:尽量应用对象组合,而不是继承来达到复用的目标。

了解:它要求在软件复用时,要尽量先应用组合或者聚合等关联关系来实现,其次才思考应用继承关系来实现。

举例:相当于咱们开发软件,一个模块的结构,就像搭积木一样,通过组合的模式,实现整体的构建;当初申明式 UI 框架,对于这种思维比拟贯彻。

参考

  • https://blog.csdn.net/lovelio…
  • https://juejin.im/post/5d8861…

创立型模式

单例模式

饿汉模式

public class Singleton {
    // 只会实例化一次
    private static Singleton instance = new Singleton();       
 
    // 公有构造方法,避免被实例化
    private Singleton() {}
 
    public static Singleton getInstance() {return instance;}
}
  • 在未应用该类的时候,也会实例化对象,会造成资源节约,除非在肯定会用到某种类的场景,否在不倡议应用。

懒汉模式

public class Singleton {
    // 持有公有动态实例,避免被援用;赋值为 null,目标是实现提早加载;volatile 润饰是禁止重排
    private volatile static Singleton instance = null;
 
    // 公有构造方法,避免被实例化
    private Singleton() {}
 
    public static Singleton getInstance() {if (instance == null) {synchronized (instance) {if (instance == null) {instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  • 应用 volatile 润饰,可禁止重排,在多线程场景也能保障失常运行;只会在应用的时候,才会去实例化对象,个别场景都能够应用。

动态外部类模式

public class Singleton {
    // 公有构造方法,避免被实例化
    private Singleton() {}
 
    // 获取实例
    public static Singleton getInstance() {return Inner.instance;}
 
    // 应用一个外部类来保护单例,只有在该类被加载的时候,才会实例化对象
    private static class Inner {private static Singleton instance = new Singleton();
    }
}
  • 饿汉模式升级版,解决了资源节约问题,同时也能保障线程平安;只有在内部类被加载的时候,才会去实例化对象;绝对于懒汉模式,动态外部类的形式防止了排队进同步代码块做 null 的判断,性能优于懒汉模式,举荐应用。

枚举模式

public enum Singleton {
    // 创立一个枚举对象,该对象天生为单例
    INSTANCE;
    public Singleton getInstance(){return INSTANCE;}
}
  • 举荐:effective java 中最佳的单例实现模式就是枚举模式,JVM 来帮咱们保障线程平安和繁多实例,在反射和序列化的场景中,仍能保障繁多实例。

参考

  • https://blog.csdn.net/zhanger…
  • https://www.cnblogs.com/happy…

工厂模式

简略工厂模式

  • 以手机为例来阐明
  • 定义一个接口,开机的时候,手机界面上,会显示该手机零碎
public interface Phone {
    // 施行开机操作的时候, 返回手机零碎
    String startUp();}
  • 实现一个 Android 手机类,实现 Phone 接口,返回“Android”手机零碎
public class AndroidPhone implements Phone {
    @Override
    public String startUp() {return "Android";}
}
  • 实现一个 IOS 手机类
public class IOSPhone implements Phone {
    @Override
    public String startUp() {return "IOS";}
}
  • 创立手机工厂治理类
public class PhoneFactory {
    private static Phone mPhone;

    // 依据零碎关键字获取相应手机对象
    public static Phone createPhone(String system) {switch (system) {
            case "Android":
                mPhone = new AndroidPhone();
                break;
            case "IOS":
                mPhone = new IOSPhone();
                break;
        }
        return mPhone;
    }
}
  • 应用
public void test() {Phone android = PhoneFactory.createPhone("Android");
    Phone ios = PhoneFactory.createPhone("IOS");

    System.out.print(android.startUp() + "\n");
    System.out.print(ios.startUp() + "\n");
}
  • 结果显示:Android IOS

工厂模式

  • 工厂模式区别与简略工厂模式的是,工厂模式不是用一个对立的工厂类来治理所有对象,而是每一个对象都有不同的工厂绝对应。
  • 持续以手机为例阐明,须要针对 Android 和 IOS 手机这俩个实现类,去构建不同的工厂,这边用接口去标准不同的工厂类
  • 手机工厂接口
public interface PhoneFactory {
    // 获取相干手机实例
    Phone getPhone();}
  • 创立 Android 手机工厂
public class AndroidPhoneFactory implements PhoneFactory {
    @Override
    public Phone getPhone() {return new AndroidPhone();
    }
}
  • 创立 IOS 手机工厂
public class IOSPhoneFactory implements PhoneFactory {
    @Override
    public Phone getPhone() {return new IOSPhone();
    }
}
  • 应用
public void test() {PhoneFactory androidMiFactory = new AndroidPhoneFactory();
    PhoneFactory iosFactory = new IOSPhoneFactory();

    System.out.print(androidFactory.getPhone().startUp() + "\n");
    System.out.print(iosFactory.getPhone().startUp() + "\n");
}
  • 结果显示:Android IOS

形象工厂模式

  • 形象模式是对工厂模式的进一步优化,工厂类不单单只能创立一个对象,而是能创立一组对象。
  • 在这里,大家可能存在一个纳闷,简略工厂不也是创立一组对象吗?是的,在这点上,俩者是十分十分类似的,区别在于:简略工厂模式是内部传值进去,以获取不同对象;形象工厂模式间接通过办法获取对象,不须要传值。
  • 持续以手机为例阐明,咱们用俩种形式来看看,两头工厂类来创立一组对象

1、第一种形式

  • 定义一个接口,这个接口外面是获取一系列的手机零碎的实例
public interface PhoneSystem {
    // 获取 Android 手机实例
    Phone getAndroid();
    
    // 获取 IOS 手机实例
    Phone getIOS();}
  • 实现形象工厂的这个接口
public class PhoneFactory implements PhoneSystem {
    @Override
    public Phone getAndroid() {return new AndroidPhone();
    }

    @Override
    public Phone getIOS() {return new IOSPhone();
    }
}
  • 应用
public void test() {PhoneSystem phoneSystem = new PhoneFactory();

    Phone android = phoneSystem.getXiaoMi();
    Phone ios = phoneSystem.getHuaWei();

    System.out.print(android.startUp() + "\n");
    System.out.print(ios.startUp() + "\n");
}
  • 结果显示:Android IOS

2、第二种形式

  • 在这里思考下,形象工厂模式,是在工厂类外面创立一组对象,与外层交互,不是通过关键字去返回相应对象,而是通过某个共性办法去返回“符合条件的实例”。
  • 这里假如一个场景:咱们定义的手机对象,其中的开机性能,只在对应的手机上才会起作用(Android 手机想开机,只能应用 Android 手机类中的开机办法,IOS 也是如此),在这里,假如此款手机是 Android 手机。
  • 此处,咱们不定义接口,间接创立形象工厂类。
public class PhoneFactory {
    private static Phone instance;
    // 模仿个数据
    private String SYSTEM = "IOS";

    public static Phone getInstance() {if("Android".equals(SYSTEM))
        {return new AndroidPhone();
        }
        if("IOS".equals(SYSTEM))
        {return new IOSPhone();
        }
        return null;
    }
}
  • 应用
public static void test() {Phone phone = PhoneFactory.getInstance();
    if (phone == null) 
        return;
    System.out.print(phone.startUp() + "\n");
}
  • 结果显示:IOS

建造者模式

阐明

  1. 在 Computer 中创立一个动态外部类 Builder,而后将 Computer 中的参数都复制到 Builder 类中。
  2. 在 Computer 中创立一个 private 的构造函数,参数为 Builder 类型
  3. 在 Builder 中创立一个 public 的构造函数,参数为 Computer 中必填的那些参数,cpu 和 ram。
  4. 在 Builder 中创立设置函数,对 Computer 中那些可选参数进行赋值,返回值为 Builder 类型的实例
  5. 在 Builder 中创立一个 build()办法,在其中构建 Computer 的实例并返回

实现

public class Computer {
    private final String cpu;// 必须
    private final String ram;// 必须
    private final int usbCount;// 可选
    private final String keyboard;// 可选
    private final String display;// 可选

    private Computer(Builder builder){
        this.cpu=builder.cpu;
        this.ram=builder.ram;
        this.usbCount=builder.usbCount;
        this.keyboard=builder.keyboard;
        this.display=builder.display;
    }
    
    public static class Builder{
        private String cpu;// 必须
        private String ram;// 必须
        private int usbCount;// 可选
        private String keyboard;// 可选
        private String display;// 可选

        public Builder(String cup,String ram){
            this.cpu=cup;
            this.ram=ram;
        }

        public Builder setUsbCount(int usbCount) {
            this.usbCount = usbCount;
            return this;
        }
        public Builder setKeyboard(String keyboard) {
            this.keyboard = keyboard;
            return this;
        }
        public Builder setDisplay(String display) {
            this.display = display;
            return this;
        }        
        public Computer build(){return new Computer(this);
        }
    }
}

应用

Computer computer = new Computer.Builder("因特尔","三星")
    .setDisplay("三星 24 寸")
    .setKeyboard("罗技")
    .setUsbCount(2)
    .build();

参考

  • https://zhuanlan.zhihu.com/p/…

原型模式

定义

原型模式(Prototype Pattern):应用原型实例指定创建对象的品种,并且通过拷贝这些原型创立新的对象。原型模式是一种对象创立型模式。

实现

public class Prototype implements Cloneable, Serializable {
    private static final long serialVersionUID = 1L;
    private String string;
    private SerializableObject obj;
 
    // 浅复制
    public Object clone() throws CloneNotSupportedException {Prototype proto = (Prototype) super.clone();
        return proto;
    }
 
    // 深复制
    public Object deepClone() throws IOException, ClassNotFoundException {
        // 写入以后对象的二进制流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
 
        // 读出二进制流产生的新对象 
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();}
 
    public String getString() {return string;}
 
    public void setString(String string) {this.string = string;}
 
    public SerializableObject getObj() {return obj;}
 
    public void setObj(SerializableObject obj) {this.obj = obj;}
}
 
class SerializableObject implements Serializable {private static final long serialVersionUID = 1L;}

参考

  • https://blog.csdn.net/zhanger…

结构型模式

适配器模式

类适配

有一个已存在的将被适配的类

public class Adaptee {public void adapteeRequest() {System.out.println("被适配者的办法");
    }
}

定义一个指标接口

public interface Target {void request();
}

怎么才能够在指标接口中的 request() 调用 Adaptee 的 adapteeRequest() 办法呢?

通过一个适配器类,实现 Target 接口,同时继承了 Adaptee 类,而后在实现的 request() 办法中调用父类的 adapteeRequest() 即可实现

public class Adapter extends Adaptee implements Target{
    @Override
    public void request() {System.out.println("concreteTarget 指标办法");
        super.adapteeRequest();}
}

测试一下

public class Test {public static void main(String[] args) {Target adapterTarget = new Adapter();
        adapterTarget.request();}
}

输入

concreteTarget 指标办法
被适配者的办法

对象适配

电源适配器:定义输入交流电接口,输入 220V 交流电类

public interface AC {int outputAC();
}

public class AC220 implements AC {
    public final int output = 220;

    @Override
    public int outputAC() {return output;}
}

适配器接口,outputDC5V() 办法则用于将输出的电压变换为 5V 后输入

public interface DC5Adapter {int outputDC5V(AC ac);
}

实现电源适配器

public class PowerAdapter implements DC5Adapter {
    public static final int voltage = 220; 
    
    @Override
    public int outputDC5V(AC ac) {int adapterInput = ac.outputAC();
        // 变压器...
        int adapterOutput = adapterInput / 44;
        System.out.println("应用 PowerAdapter 变压适配器,输出 AC:" + adapterInput + "V" 
                           + ",输入 DC:" + adapterOutput + "V");
        return adapterOutput;
    }
}

应用

public class Test {private List<DC5Adapter> adapters = new LinkedList<DC5Adapter>();

    public static void main(String[] args) {AC ac = new AC220(); // 实例化 220v 对象
        DC5Adapter adapter = new PowerAdapter(); // 实例化适配器
        adapter.outputDC5V(ac); 
    }
}

输入

应用 PowerAdapter 变压适配器,输出 AC:220V,输入 DC:5V

接口适配

在理论开发中,常常会遇到接口中定义了太多的办法,以致于有时咱们在一些实现类中并不是都须要

public interface Sourceable {public void method1();
    public void method2();}

抽象类 Wrapper:

public abstract class Wrapper implements Sourceable{public void method1(){}
    public void method2(){}
}

可抉择的去实现,咱们想要的办法

public class SourceSub extends Wrapper {
    @Override
    public void method1(){System.out.println("实现办法一");
    }
}

参考

  • https://juejin.im/post/5ba289…
  • https://blog.csdn.net/zhanger…

装璜模式

定义

  • 装璜器模式(Decorator Pattern)容许向一个现有的对象增加新的性能,同时又不扭转其构造。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

实现

  • 创立一个接口
public interface Shape {void draw();
}
  • 创立俩个实现类
public class Rectangle implements Shape {
    @Override
    public void draw() {System.out.println("Shape: Rectangle");
    }
}
public class Circle implements Shape {
    @Override
    public void draw() {System.out.println("Shape: Circle");
    }
}
  • 创立实现了 Shape 接口的形象装璜类
public abstract class ShapeDecorator implements Shape {
    protected Shape decoratedShape;

    public ShapeDecorator(Shape decoratedShape){this.decoratedShape = decoratedShape;}

    @Override
    public void draw(){decoratedShape.draw();
        System.out.println("Border Color: Red");
    }  
}
    • 测试
public class Test {public static void main(String[] args) {Shape circle = new Circle();
        ShapeDecorator circleShape = new ShapeDecorator(new Circle());
        ShapeDecorator rectangleShape = new ShapeDecorator(new Rectangle());
        System.out.println("Circle with normal border");
        circle.draw();

        System.out.println("\nCircle of red border");
        circleShape.draw();

        System.out.println("\nRectangle of red border");
        rectangleShape.draw();}
}
  • 后果
Circle with normal border
Shape: Circle

Circle of red border
Shape: Circle
Border Color: Red

Rectangle of red border
Shape: Rectangle
Border Color: Red

参考

  • https://www.runoob.com/design…

代理模式

定义

  • 在代理模式(Proxy Pattern)中,一个类代表另一个类的性能。这种类型的设计模式属于结构型模式;在代理模式中,咱们创立具备现有对象的对象,以便向外界提供性能接口。
  • 其实每个模式名称就表明了该模式的作用,代理模式就是多一个代理类进去,替原对象进行一些操作,比方咱们在租房子的时候回去找中介,为什么呢?因为你对该地区屋宇的信息把握的不够全面,心愿找一个更相熟的人去帮你做,此处的代理就是这个意思。再如咱们有的时候打官司,咱们须要请律师,因为律师在法律方面有特长,能够替咱们进行操作,表白咱们的想法。

实现

  • 创立一个接口
public interface Shape {void draw();
}
  • 实现
public class Circle implements Shape {
    @Override
    public void draw() {System.out.println("Shape: Circle");
    }
}
  • 创立一个代理类
public class ProxyShape implements Shape {
     private Circle circle;
    
    @Override
    public void draw() {if(circle == null){circle = new Circle();
        }
        circle.draw();}
}
  • 测试
public class Test {public static void main(String[] args) {Shape shapeProxy = new ProxyShape();
        shape.draw();}
}
  • 后果
Shape: Circle

参考

  • https://blog.csdn.net/zhanger…

外观模式

定义

  • 外观模式(Facade Pattern)暗藏零碎的复杂性,并向客户端提供了一个客户端能够拜访零碎的接口。这种类型的设计模式属于结构型模式,它向现有的零碎增加一个接口,来暗藏零碎的复杂性
  • 这种模式波及到一个繁多的类,该类提供了客户端申请的简化办法和对现有零碎类办法的委托调用
  • 外观模式就是将他们的关系放在一个 Facade 类中,升高了类类之间的耦合度

实现

  • 实现类
public class CPU {public void startup(){System.out.println("cpu startup!");
    }

    public void shutdown(){System.out.println("cpu shutdown!");
    }
}
public class Memory {public void startup(){System.out.println("memory startup!");
    }
    
    public void shutdown(){System.out.println("memory shutdown!");
    }
}
public class Disk {public void startup(){System.out.println("disk startup!");
    }
    
    public void shutdown(){System.out.println("disk shutdown!");
    }
}
  • Facade 类
public class Computer {
    private CPU cpu;
    private Memory memory;
    private Disk disk;

    public Computer(){cpu = new CPU();
        memory = new Memory();
        disk = new Disk();}

    public void startup(){cpu.startup();
        memory.startup();
        disk.startup();}

    public void shutdown(){cpu.shutdown();
        memory.shutdown();
        disk.shutdown();}
}
  • 测试
public class Test {public static void main(String[] args) {Computer computer = new Computer();
        computer.startup();
        computer.shutdown();}
}
  • 后果
cpu startup!
memory startup!
disk startup!
    
cpu shutdown!
memory shutdown!
disk shutdown!

参考

  • https://blog.csdn.net/zhanger…

桥接模式

定义

  • 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者能够独立变动。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接构造,来实现二者的解耦。
  • 这种模式波及到一个作为桥接的接口,使得实体类的性能独立于接口实现类。这两种类型的类可被结构化扭转而互不影响。
  • 桥接模式就是把事物和其具体实现离开,使他们能够各自独立的变动。桥接的用意是:将抽象化与实现化解耦,使得二者能够独立变动,像咱们罕用的 JDBC 桥 DriverManager 一样,JDBC 进行连贯数据库的时候,在各个数据库之间进行切换,根本不须要动太多的代码,甚至丝毫不必动,起因就是 JDBC 提供对立接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。

实现

  • 创立桥接实现接口
public interface DrawAPI {public void drawCircle();
}
  • 创立实现了 DrawAPI 接口的实体桥接实现类
public class RedCircle implements DrawAPI {
   @Override
   public void drawCircle(int radius, int x, int y) {System.out.println("Drawing Circle, color: red);
   }
}
public class GreenCircle implements DrawAPI {
   @Override
   public void drawCircle(int radius, int x, int y) {System.out.println("Drawing Circle, color: green);
   }
}
  • 应用 DrawAPI 接口创立抽象类 Shape。
public abstract class Shape {
    protected DrawAPI drawAPI;
    
    protected Shape(DrawAPI drawAPI){this.drawAPI = drawAPI;}
    
    public abstract void draw();}
  • 现了 Shape 接口的实体类
public class Circle extends Shape {public Circle(DrawAPI drawAPI) {super(drawAPI);
    }

    public void draw() {drawAPI.drawCircle();
    }
}
  • 测试
public class BridgePatternDemo {public static void main(String[] args) {Shape redCircle = new Circle(new RedCircle());
      Shape greenCircle = new Circle(new GreenCircle());
 
      redCircle.draw();
      greenCircle.draw();}
}
  • 后果
Drawing Circle, color: red
Drawing Circle, color: green

参考

  • https://blog.csdn.net/zhanger…
  • https://www.runoob.com/design…

组合模式

定义

  • 组合模式(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;
        this.salary = sal;
        subordinates = new ArrayList<Employee>();}

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

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

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

    public String toString(){
        return ("Employee :[ Name :"+ name 
                +", dept :"+ dept + ", salary :"
                + salary+"]");
    }   
}
  • 测试,俄罗斯套娃
public class Test {public static void main(String[] args) {Employee CEO = new Employee("John","CEO", 30000);

        Employee headSales = new Employee("Robert","Head Sales", 20000);
        Employee salesExecutive1 = new Employee("Richard","Sales", 10000);

        CEO.add(headSales);
        headSales.add(salesExecutive1);

        // 打印该组织的所有员工
        System.out.println(CEO); 
        for (Employee headEmployee : CEO.getSubordinates()) {System.out.println(headEmployee);
            for (Employee employee : headEmployee.getSubordinates()) {System.out.println(employee);
            }
        }        
    }
}
  • 后果
Employee :[Name : John, dept : CEO, salary :30000]
Employee :[Name : Robert, dept : Head Sales, salary :20000]
Employee :[Name : Richard, dept : Sales, salary :10000]

参考

  • https://www.runoob.com/design…

享元模式

定义

  • 享元模式(Flyweight Pattern)次要用于缩小创建对象的数量,以缩小内存占用和进步性能。这种类型的设计模式属于结构型模式,它提供了缩小对象数量从而改善利用所需的对象构造的形式。
  • 享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创立新对象。

典型享元模式

  • 典型享元类(享元:Flyweight,w 不是大写)
class Flyweight {
    // 外部状态 innerState 作为成员变量,同一个享元对象其外部状态是统一的
    private String innerState;
    public Flyweight(String innerState) {this.innerState = innerState;}
    // 内部状态 outerState 在应用时由内部设置,不保留在享元对象中,即便是同一个对象
    public void operation(String outerState) {//......}
}
  • 典型享元工厂类
class FlyweightFactory {
    // 定义一个 HashMap 用于存储享元对象,实现享元池
    private HashMap flyweights = newHashMap();
    
    public Flyweight getFlyweight(String key){
        // 如果对象存在,则间接从享元池获取
        if(flyWeights.containsKey(key)){return (Flyweight) flyweights.get(key);
        } else {
            // 如果对象不存在,先创立一个新的对象增加到享元池中,而后返回
            Flyweight fw = newConcreteFlyweight();
            flyweights.put(key,fw);
            return fw;
        }
    }
}

通用写法

  • 解决某些场景频繁生成实例问题;应用泛型,节俭写判断逻辑
/**
* 经典享元模式办法
* 场景:解决某些场景频繁生成实例问题;应用泛型,节俭写判断逻辑
* 应用:String s = classicFlyweight(String.class);
*/
private Map<String, Object> flyweightMap;
private <T> T classicFlyweight(Class<T> clazz) {
    T t;

    if (flyweightMap == null)
        flyweightMap = new HashMap<>();
    String key = clazz.getName();
    if (flyweightMap.get(key) != null) {t = (T) flyweightMap.get(key);
    }else {
        try {t = clazz.newInstance();
            flyweightMap.put(key, t);
        } catch (Exception e) {t = null;}
    }

    return t;
}

连接池的实现

  • 数据库连接池
  • 通过连接池的治理,实现了数据库连贯的共享,不须要每一次都从新创立连贯,节俭了数据库从新创立的开销,晋升了零碎的性能!
public class ConnectionPool {
    private Vector<Connection> pool;
    
    // 私有属性
    private String url = "jdbc:mysql://localhost:3306/test";
    private String username = "root";
    private String password = "root";
    private String driverClassName = "com.mysql.jdbc.Driver";
 
    private int poolSize = 100;
    private static ConnectionPool instance = null;
    Connection conn = null;
 
    // 构造方法,做一些初始化工作 
    private ConnectionPool() {pool = new Vector<Connection>(poolSize);
        for (int i = 0; i < poolSize; i++) {
            try {Class.forName(driverClassName);
                conn = DriverManager.getConnection(url, username, password);
                pool.add(conn);
            } catch (ClassNotFoundException e) {e.printStackTrace();
            } catch (SQLException e) {e.printStackTrace();
            }
        }
    }
 
    // 返回连贯到连接池
    public synchronized void release() {pool.add(conn);
    }
 
    // 返回连接池中的一个数据库连贯
    public synchronized Connection getConnection() {if (pool.size() > 0) {Connection conn = pool.get(0);
            pool.remove(conn);
            return conn;
        } else {return null;}
    }
}

参考

  • https://juejin.im/post/5ba9ff…
  • https://blog.csdn.net/zhanger…

行为型模式

思考

策略模式和状态模式

相同点

  • 两者通过将行为和状态拆分成一系列小的组件,由条件和状态进行性能更替,这样合乎开闭准则,便于扩大。此外均可作为 if else 或者分支的替换计划;反对的最大行为和状态均无限;

不同点

  • 策略模式中,类的性能是依据以后条件被动更改;
  • 状态模式中,类的性能是被动由以后状态更改;
  • 策略模式中每个行为或算法之间没有关联;
  • 状态模式中的状态之间有关联,并且状态自身管制着状态转移;

解释器模式

定义

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

实现

  • 创立一个表达式接口。
public interface Expression {public 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 OrExpression implements Expression {
    private Expression expr1 = null;
    private Expression expr2 = null;

    public OrExpression(Expression expr1, Expression expr2) { 
        this.expr1 = expr1;
        this.expr2 = expr2;
    }

    @Override
    public boolean interpret(String context) {return expr1.interpret(context) || expr2.interpret(context);
    }
}
public class AndExpression implements Expression {
    private Expression expr1 = null;
    private Expression expr2 = null;

    public AndExpression(Expression expr1, Expression expr2) { 
        this.expr1 = expr1;
        this.expr2 = expr2;
    }

    @Override
    public boolean interpret(String context) {return expr1.interpret(context) && expr2.interpret(context);
    }
}
  • Test 应用 Expression 类来创立规定,并解析它们。
public class Test {
    // 规定:Robert 和 John 是男性
    public static Expression getMaleExpression(){Expression robert = new TerminalExpression("Robert");
        Expression john = new TerminalExpression("John");
        return new OrExpression(robert, john);    
    }

    // 规定:Julie 是一个已婚的女性
    public static Expression getMarriedWomanExpression(){Expression julie = new TerminalExpression("Julie");
        Expression married = new TerminalExpression("Married");
        return new AndExpression(julie, married);    
    }

    public static void main(String[] args) {Expression isMale = getMaleExpression();
        Expression isMarriedWoman = getMarriedWomanExpression();

        System.out.println("John is male?" + isMale.interpret("John"));
        System.out.println("Julie is a married women?" 
                           + isMarriedWoman.interpret("Married Julie"));
    }
}
  • 后果
John is male? true
Julie is a married women? true

参考

  • https://www.runoob.com/design…

状态模式

定义

  • 在状态模式(State Pattern)中,类的行为是基于它的状态扭转的;咱们创立示意各种状态的对象和一个行为随着状态对象扭转而扭转的 context 对象。

实现

  • 创立一个接口。
public interface State {public void doAction(Context context);
}
  • 俩个状态实现类.
public class StartState implements State {public void doAction(Context context) {System.out.println("Player is in start state");
        context.setState(this); 
    }

    public String toString(){return "Start State";}
}
public class StopState implements State {public void doAction(Context context) {System.out.println("Player is in stop state");
        context.setState(this); 
    }

    public String toString(){return "Stop State";}
}
  • 创立 Context 类。
public class Context {
    private State state;

    public Context(){state = null;}

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

    public State getState(){return state;}
}
  • 测试
public class StatePatternDemo {public static void main(String[] args) {Context context = new Context();

        StartState startState = new StartState();
        startState.doAction(context);

        System.out.println(context.getState().toString());

        StopState stopState = new StopState();
        stopState.doAction(context);

        System.out.println(context.getState().toString());
    }
}
  • 后果
Player is in start state
Start State
Player is in stop state
Stop State

参考

  • https://www.runoob.com/design…

策略模式

定义

  • 在策略模式(Strategy Pattern)中,一个类的行为或其算法能够在运行时更改。这种类型的设计模式属于行为型模式。
  • 在策略模式中,咱们创立示意各种策略的对象和一个行为随着策略对象扭转而扭转的 context 对象。策略对象扭转 context 对象的执行算法。
  • 策略模式定义了一系列算法,并将每个算法封装起来,使他们能够互相替换,且算法的变动不会影响到应用算法的客户.

实现

  • 策略接口,定义策略执行接口
public interface Strategy {int calculate(int a, int b);
}
  • 具体策略类,实现策略接口,提供具体算法
// 加法算法
public class AddStrategy implements Strategy{
    @Override
    public int calculate(int a, int b) {return a + b;}
}
// 减法算法
public class SubtractStrategy implements Strategy{
    @Override
    public int calculate(int a, int b) {return a - b;}
}
  • Context 类,持有具体策略类的实例,负责调用具体算法
public class Context {
    private Strategy strategy;

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

    // 动静替换算法(策略)
    public void replaceStrategy(Strategy strategy) {this.strategy = strategy;}

    public int calculate(int a, int b) {return strategy.calculate(a, b);
    }
}
  • 测试
public class Test{public static void main(String[] args) {Strategy addStrategy = new AddStrategy();
        Context context = new Context(addStrategy);
        // 输入 3
        System.out.println(context.calculate(1, 2));

        Strategy subStrategy = new SubtractStrategy();
        // 动静替换算法(策略)
        context.replaceStrategy(subStrategy);
        // 输入 -1
        System.out.println(context.calculate(1, 2));
    }
}
  • 测试 main 办法中,咱们先应用 ” 加法策略 (算法)” 创立一个 context,而后调用 calculate(1,2) 办法失去后果 3。而后动静替换策略为 ” 减法策略 (算法)”,再次调用 calculate(1,2) 失去后果 -1。

参考

  • https://www.jianshu.com/p/d0c…

观察者模式

定义

  • 当对象间存在一对多关系时,则应用观察者模式(Observer Pattern)。比方,当一个对象被批改时,则会主动告诉依赖它的对象。

实现

  • 形象观察者接口(Observer)
    • 为所有的具体观察者定义一个接口,在失去主题告诉时更新本人。
public interface Observer {
    // 更新内容
    public void update(String msg);
}
  • 形象主题接口(Subject)
    • 它把所有观察者对象的援用保留到一个汇集里,每个主题都能够有任何数量的观察者。形象主题提供一个接口,能够减少和删除观察者对象,以及告诉所有观察者。
public interface Subject {
    // 增加观察者
    void attach(Observer observer);
    // 删除观察者
    void detach(Observer observer);
    // 告诉更新
    void notify(String msg);
}
  • 观察者接口实现类
    • 实现形象观察者角色所要求的更新接口,以便使自身的状态与主题状态保持一致。
public class TestObserver implements Observer{
    private String info;

    public TestObserver(String info){this.info = info;}

    @Override
    public void update(String msg) {System.out.println(info + "----" + msg);
    }
}
  • 主题接口实现类
    • 将无关状态存入具体观察者对象;当具体主题外部状态放生扭转时,告诉所有注册过的观察者。
public class TestSubject implements Subject{private List<Observer> mList = new ArrayList();
    
    @Override
    public void attach(Observer observer) {mList.add(observer);
    }
    
    @Override
    public void detach(Observer observer) {mList.remove(observer);
    }
    
    @Override
    public void notify(String msg) {for (Observer observer : mList) {observer.update(msg);
        }
    }
}
  • 测试
public class TestMain {public static void main(String[] args) {Subject subject = new TestSubject();

        Observer observerA = new TestObserver("A:");
        Observer observerB = new TestObserver("B:");
        subject.attach(observerA);
        subject.attach(observerB);
        subject.notify("告诉 One");
        subject.detach(observerA);
        subject.notify("告诉 Two");
    }
}
  • 日志打印

中介者模式

定义

  • 中介者模式(Mediator Pattern)是用来升高多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常解决不同类之间的通信,并反对松耦合,使代码易于保护。

实现

  • 创立中介类
public class ChatRoom {public static void showMessage(User user, String message){System.out.println(new Date().toString()
                           + "[" + user.getName() +"] :" + message);
    }
}
  • 创立 user 类。
public class User {
    private String name;

    public String getName() {return name;}

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

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

    public void sendMessage(String message){ChatRoom.showMessage(this,message);
    }
}
  • 测试
public class Test {public static void main(String[] args) {User robert = new User("Robert");
      User john = new User("John");
 
      robert.sendMessage("Hi! John!");
      john.sendMessage("Hello! Robert!");
   }
}
  • 后果
Thu Jan 31 16:05:46 IST 2013 [Robert] : Hi! John!
Thu Jan 31 16:05:46 IST 2013 [John] : Hello! Robert!

参考

  • https://www.runoob.com/design…

备忘录模式

定义

  • 备忘录模式(Memento Pattern)保留一个对象的某个状态,以便在适当的时候复原对象。

实现

  • Original 类是原始类,外面有须要保留的属性 value 及创立一个备忘录类,用来保留 value 值。Memento 类是备忘录类,Storage 类是存储备忘录的类,持有 Memento 类的实例
public class Original {
    private String value;

    public String getValue() {return value;}

    public void setValue(String value) {this.value = value;}

    public Original(String value) {this.value = value;}

    public Memento createMemento(){return new Memento(value);
    }

    public void restoreMemento(Memento memento){this.value = memento.getValue();
    }
}
public class Memento {
    private String value;
 
    public Memento(String value) {this.value = value;}

    public String getValue() {return value;}
 
    public void setValue(String value) {this.value = value;}
}
public class Storage {
    private Memento memento;
    
    public Storage(Memento memento) {this.memento = memento;}
 
    public Memento getMemento() {return memento;}
 
    public void setMemento(Memento memento) {this.memento = memento;}
}
  • 测试
public class Test {public static void main(String[] args) {
        // 创立原始类
        Original origi = new Original("egg");
        // 创立备忘录
        Storage storage = new Storage(origi.createMemento());

        // 批改原始类的状态
        System.out.println("初始化状态为:" + origi.getValue());
        origi.setValue("niu");
        System.out.println("批改后的状态为:" + origi.getValue());

        // 回复原始类的状态
        origi.restoreMemento(storage.getMemento());
        System.out.println("复原后的状态为:" + origi.getValue());
    }
}
  • 后果
初始化状态为:egg
批改后的状态为:niu
复原后的状态为:egg

参考

  • https://blog.csdn.net/zhanger…

命令模式

定义

  • 命令模式(Command Pattern)是一种数据驱动的设计模式。申请以命令的模式包裹在对象中,并传给调用对象。调用对象寻找能够解决该命令的适合的对象,并把该命令传给相应的对象,该对象执行命令。

实现

  • 创立一个命令接口。
public interface Order {void execute();
}
  • 创立一个申请类。
public class Stock {
   private String name = "ABC";
   private int quantity = 10;
 
   public void buy(){
      System.out.println("Stock [ Name:"+name+", 
         Quantity: "+ quantity +" ] bought");
   }
}
  • 创立实现了 Order 接口的实体类。
public class BuyStock implements Order {
    private Stock abcStock;

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

    public void execute() {abcStock.buy();
    }
}
  • 创立命令调用类。
public class Broker {private List<Order> orderList = new ArrayList<Order>(); 

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

    public void placeOrders(){for (Order order : orderList) {order.execute();
        }
        orderList.clear();}
}
  • 测试
public class CommandPatternDemo {public static void main(String[] args) {Stock abcStock = new Stock();

        BuyStock buyStockOrder = new BuyStock(abcStock);
        Broker broker = new Broker();
        broker.takeOrder(buyStockOrder);

        broker.placeOrders();}
}
  • 后果
Stock [Name: ABC, Quantity: 10] bought

参考

  • https://www.runoob.com/design…

责任链模式

定义

  • 责任链模式(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);
        }
    }

    abstract protected void write(String message);
}
  • 创立扩大了该记录器类的实体类
public class ConsoleLogger extends AbstractLogger {public ConsoleLogger(int level){this.level = level;}

    @Override
    protected void write(String message) {System.out.println("Standard Console::Logger:" + message);
    }
}

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

    @Override
    protected void write(String message) {System.out.println("Error Console::Logger:" + message);
    }
}

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

    @Override
    protected void write(String message) {System.out.println("File::Logger:" + message);
    }
}
  • 测试
public class Test {private static AbstractLogger getChainOfLoggers(){AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
        AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
        AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);

        errorLogger.setNextLogger(fileLogger);
        fileLogger.setNextLogger(consoleLogger);
        return errorLogger;  
    }

    public static void main(String[] args) {AbstractLogger loggerChain = getChainOfLoggers();

        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.");
    }
}
  • 后果
Standard Console::Logger: This is an information.
File::Logger: This is a debug level information.
Standard Console::Logger: This is a debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.

参考

  • https://www.runoob.com/design…

访问者模式

定义

  • 在访问者模式(Visitor Pattern)中,咱们应用了一个访问者类,它扭转了元素类的执行算法。通过这种形式,元素的执行算法能够随着访问者扭转而扭转。这种类型的设计模式属于行为型模式。依据模式,元素对象已承受访问者对象,这样访问者对象就能够解决元素对象上的操作。

实现

  • Visitor 类,寄存要拜访的对象
public interface Visitor {public void visit(Subject sub);
}
public class MyVisitor implements Visitor {
    @Override
    public void visit(Subject sub) {System.out.println("visit the subject:"+sub.getSubject());
    }
}
  • Subject 类,accept 办法,承受将要拜访它的对象,getSubject()获取将要被拜访的属性
public interface Visitor {public void visit(Subject sub);
}
public class MyVisitor implements Visitor {
    @Override
    public void visit(Subject sub) {System.out.println("visit the subject:"+sub.getSubject());
    }
}
  • Subject 类,accept 办法,承受将要拜访它的对象,getSubject()获取将要被拜访的属性
public interface Subject {public void accept(Visitor visitor);
    public String getSubject();}
public class MySubject implements Subject {
    @Override
    public void accept(Visitor visitor) {visitor.visit(this);
    }

    @Override
    public String getSubject() {return "love";}
}
  • 测试
public class Test {public static void main(String[] args) {Visitor visitor = new MyVisitor();
        Subject sub = new MySubject();
        sub.accept(visitor);    
    }
}
  • 后果:visit the subject:love

参考

  • https://blog.csdn.net/zhanger…

迭代器模式

定义

  • 迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中十分罕用的设计模式。这种模式用于程序拜访汇合对象的元素,不须要晓得汇合对象的底层示意。

实现

  • 创立接口
public interface Iterator {public boolean hasNext();
    public Object next();}
public interface Container {public Iterator getIterator();
}
  • 创立实现了 Container 接口的实体类。该类有实现了 Iterator 接口的外部类 NameIterator。
public class NameRepository implements Container {public String names[] = {"Robert" , "John" ,"Julie" , "Lora"};

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

    private class NameIterator implements Iterator {

        int index;

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

        @Override
        public Object next() {if(this.hasNext()){return names[index++];
            }
            return null;
        }     
    }
}
  • 测试
public class Test {public static void main(String[] args) {NameRepository namesRepository = new NameRepository();
        for(Iterator iter = namesRepository.getIterator(); iter.hasNext();){String name = (String)iter.next();
            System.out.println("Name :" + name);
        }  
    }
}
  • 后果
Name : Robert
Name : John
Name : Julie
Name : Lora

参考

  • https://www.runoob.com/design…

模板模式

定义

  • 在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的办法的形式 / 模板。它的子类能够按须要重写办法实现,但调用将以抽象类中定义的形式进行。

实现

  • 创立一个抽象类
public abstract class Game {abstract void initialize();
    abstract void startPlay();
    abstract void endPlay();

    // 模板
    public final void play(){
        // 初始化游戏
        initialize();
        // 开始游戏
        startPlay();
        // 完结游戏
        endPlay();}
}
  • 实现类
public class Football extends Game {
    @Override
    void endPlay() {System.out.println("Football Game Finished!");
    }

    @Override
    void initialize() {System.out.println("Football Game Initialized! Start playing.");
    }

    @Override
    void startPlay() {System.out.println("Football Game Started. Enjoy the game!");
    }
}
  • 测试
public class Test {public static void main(String[] args) {Game game = new Football();
        game.play();}
}
  • 后果
Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!

参考

  • https://www.runoob.com/design…

最初

  • 文章源码:一文总结设计模式

    • 提供良好的搬运格局,请附上援用出处
退出移动版