23种经典设计模式

Posted by ACRusher on July 23, 2016

设计模式简介

设计模式共有23种

  • 关于构建类的 5种
    • 工厂设计模式 Factory
    • 抽象工厂设计模式 Abstract Factory
    • 单例模式 Singleton
    • 构建者模式 Builder
    • 原型模式 Prototype
  • 关于类结构的 7种
    • 适配器模式 Adaptor
    • 装饰器模式 Decorator
    • 代理模式 Proxy
    • 外观模式 Facade
    • 桥接模式 Bridge
    • 组合模式 Composite
    • 享元模式 Cache
  • 关于类行为的 11种
    • 策略模式 Strategy
    • 模板方法模式 Template
    • 观察者模式 Observer
    • 迭代子模式 Iterator
    • 责任链模式 Chain
    • 命令模式 Command
    • 备忘录模式 Memo
    • 状态模式 State
    • 访问者模式 Visitor
    • 中介者模式 Mediator
    • 解释器模式 Interpreter

设计模式的六大原则

  • 开闭原则

    对扩展开放,对修改关闭

  • 里氏替换原则

    所有使用父类的地方,一定可以用子类替换

  • 依赖倒转原则

    要依赖接口和抽象编程,而不是依赖具体类

  • 接口隔离原则

    尽量使用不同的接口,不要在一个接口中定义过多功能

  • 迪米特原则或者最少知道原则

    一个类要尽可能少的与其他类发生联系

  • 合成复用原则

    尽量使用聚合,避免使用继承

设计模式代码示例

下面是构造类型的5个设计模式


1.工厂设计模式

适用于批量生产拥有共同功能不同规格的产品。

public class FactoryDesignPattern {

    public static interface MessageSender{
        void send(String message);
    }

    public static class MailMessageSender implements MessageSender{

        public void send(String message) {
            System.out.println(" sending mail . content: "+message);
        }
    }

    public static class SmsMessageSender implements MessageSender{

        public void send(String message) {
            System.out.println(" sending mobile message . content: "+message);
        }
    }

    public static class MessageSenderFactory{
        public static MessageSender createMailMessageSender(){
            return new MailMessageSender();
        }
        public static MessageSender createSmsMessageSender(){
            return new SmsMessageSender();
        }
    }

    public static void main(String[] args) {
        MessageSender mailSender = MessageSenderFactory.createMailMessageSender();
        mailSender.send("mail");
        mailSender=MessageSenderFactory.createSmsMessageSender();
        mailSender.send("sms");
    }
}

2.抽象工厂模式

对于工厂模式,随着功能的迭代,需要不停的修改工厂类,甚至会出现需要不同版本的工厂类。此时对工厂类加一层抽象,来满足依赖倒转原则,便演化出了抽象工厂模式。

public class AbstractFactoryDesignPattern {
    public static interface MessageSender{
        void send(String message);
    }

    public static class MailMessageSender implements MessageSender {
        private String version;

        public MailMessageSender(String version) {
            this.version = version;
        }

        public void send(String message) {
            System.out.println((version==null?"":version)+" sending mail . content: "+message);
        }
    }

    public static class SmsMessageSender implements MessageSender {
        private String version;

        public SmsMessageSender(String version) {
            this.version = version;
        }

        public void send(String message) {
            System.out.println((version==null?"":version)+" sending mobile message . content: "+message);
        }
    }

    public static abstract class MessageSenderFactory{
        public abstract   MessageSender createMailMessageSender();
        public abstract MessageSender createSmsMessageSender();
    }

    public static class MessageSenderFactoryV1 extends MessageSenderFactory{

        public MessageSender createMailMessageSender() {
            return new MailMessageSender("V1");
        }

        public MessageSender createSmsMessageSender() {
            return new SmsMessageSender("V1");
        }
    }

    public static class MessageSenderFactoryV2 extends MessageSenderFactory{

        public MessageSender createMailMessageSender() {
            return new MailMessageSender("V2");
        }

        public MessageSender createSmsMessageSender() {
            return new SmsMessageSender("V2");
        }
    }

    public static void main(String[] args) {
        MessageSenderFactory messageSenderFactory=new MessageSenderFactoryV1();
        MessageSender messageSender=messageSenderFactory.createMailMessageSender();
        messageSender.send("mail");
        messageSender=messageSenderFactory.createSmsMessageSender();
        messageSender.send("sms");
    }
}

### 3.单例模式

有些核心类,在web容器种只能创建一次,此时需要单例模式。单例模式的实现有很多种,主流的是double check加锁 和 static属性实现。

public class SingletonDesignPattern {

    public static class SingletonBeanA{
        //禁止外部创建
        private SingletonBeanA(){}
        private static SingletonBeanA singletonBeanA;

        public static SingletonBeanA getInstance(){
            if(singletonBeanA==null){
                synchronized (SingletonBeanA.class){
                    if(singletonBeanA==null){
                        SingletonBeanA tmp=new SingletonBeanA();
                        //创建后的bean 一定不要直接赋值给 singletonBeanA
                        // necessary check , make sure bean is ok
                        singletonBeanA=tmp;
                    }
                }
            }
            return singletonBeanA;
        }
        //序列化时保证单例
        public Object readResolve(){
            return getInstance();
        }
    }
    
    public static class SingletonBeanB{
        private SingletonBeanB(){};
        //jvm 保证只初始化一次
        private static SingletonBeanB singletonBeanB=new SingletonBeanB();
        public static SingletonBeanB getInstance(){
            return singletonBeanB;
        }
        //序列化时保证单例
        public Object readResolve(){
            return getInstance();
        }
    }
    
    //通过enum 保证单例机制
    public static enum SingletonBeanC{
        instance;
        SingletonBeanC() {
        }
    }
}

4.建造者模式

工厂模式关注的是批量生产对象,而建造者关注的是构建一个复杂的聚合对象。

public class BuilderDesignPattern {
    // 一个复杂的难以理解的类
    public static class ComplexBean{
        String name;
        Long concurrent;
        int sleep;
        ThreadHolder threadHolder;

        public static class ThreadHolder{
            Thread thread;
            int tid;
        }
    }
    //一个容易使用的 提供简易配置方法的构造者
    public static class ComplexBeanBuilder{
        private String name;
        private Long concurrent;
        public ComplexBeanBuilder name(String name){
            this.name=name;
            return this;
        }
        public ComplexBeanBuilder concurrent(Long concurrent){
            this.concurrent=concurrent;
            return this;
        }
        //复杂的构建逻辑
        public ComplexBean build(){
            ComplexBean complexBean=new ComplexBean();
            complexBean.name=name;
            complexBean.concurrent=concurrent;
            complexBean.sleep=10;
            ComplexBean.ThreadHolder threadHolder=new ComplexBean.ThreadHolder();
            threadHolder.thread= Thread.currentThread();
            complexBean.threadHolder=threadHolder;
            return complexBean;
        }
    }

    public static void main(String[] args) {
        ComplexBean complexBean=new ComplexBeanBuilder().
                name("name").concurrent(10L).build();
        System.out.println(complexBean.name);
    }
}

5.原型模式

原型模式在生产环境用的比较少,说白了就是将已有的对象作为原型复制一个新对象,实现方法有浅复制和深复制两种,分别可以通过clone和反序列化实现。

public class PrototypeDesignPattern {

    public static class Holder implements Serializable{
        private static final long serialVersionUID = 1L;
        String name="holder";
    }

    public static class PrototypeBean implements Cloneable,Serializable{
        private static final long serialVersionUID = 1L;
        String name;
        Holder holder;

        //浅复制
        public PrototypeBean copy() throws CloneNotSupportedException {
            return (PrototypeBean)super.clone();
        }
        //深复制
        public PrototypeBean deepCopy() throws IOException, ClassNotFoundException {
            ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream=new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(this);

            ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            ObjectInputStream objectInputStream=new ObjectInputStream(byteArrayInputStream);
            return (PrototypeBean)objectInputStream.readObject();
        }
    }

    public static void main(String[] args) throws Exception {
        PrototypeBean prototypeBean=new PrototypeBean();
        prototypeBean.name="good name";
        Holder holder=new Holder();
        prototypeBean.holder=holder;

        PrototypeBean copy=prototypeBean.copy();
        PrototypeBean deepCopy=prototypeBean.deepCopy();

        assert copy.holder==holder;
        assert deepCopy.holder!=null && deepCopy.holder!=holder;
    }
}

下面是7种结构类型设计模式


6.适配器模式

顾名思义,适配器模式是用来将已有的类或者接口中的方法 组合转化成更加方便使用的方法, 适配器也可以提供默认实现方便子类继承使用。说白了,就是现实生活中的转换头。

public class AdaptorDesignPattern {

    public static interface Phone{
        boolean sendMessage(String message);
        boolean call(String phoneNumber);
        // represent the phone function that we don't even care
        void functionA();
        void functionB();
        void functionC();
    }

    public static abstract class PhoneAdaptor implements Phone{
        public void functionA() {
            //default implement
        }

        public void functionB() {
            //default implement
        }

        public void functionC() {
            //default implement
        }
    }

    public static void main(String[] args) {
        Phone phone=new PhoneAdaptor() {
            public boolean sendMessage(String message) {
                System.out.println("sending message : "+message);
                return true;
            }

            public boolean call(String phoneNumber) {
                return true;
            }
        };
        phone.sendMessage("hello world.");
    }
}

7.装饰器模式

主要用于动态的在原有类的基础上添加功能,如添加缓存、增加日志等等。Decorator实现原有类相同的接口,对使用原有类的地方是透明的。

public class DecoratorDesignPattern {

    public static interface IPhone{
        boolean sendMessage(String message);
    }

    public static class Phone implements IPhone{
        public boolean sendMessage(String message){
            System.out.println("sending message : "+message);
            return true;
        }
    }

    public static class PhoneDecorator implements IPhone{
        private DecoratorDesignPattern.Phone phone=new Phone();

        public boolean sendMessage(String message) {
            System.out.println("before send message.");
            phone.sendMessage(message);
            System.out.println("after send message.");
            return true;
        }
    }

    public static void main(String[] args) {
        IPhone phone=new PhoneDecorator();
        phone.sendMessage("message.");
    }
}

8.代理模式

有一些业务操作十分复杂,客户并不关心内部的具体实现,客户可以通过托管给代理来实现对应的功能。代理还可以根据需要,对相应的功能做增强和扩展。 与装饰器的区别:装饰器对客户使用是透明的,主要在原有功能基础上额外添加客户无感知的功能;代理模式下用户必须感知代理,并且依赖代理的实现。

public class ProxyDesignPattern {
    public static class Sing{
        public void sing(){
            System.out.println("i am singing...");
        }
    }

    public static class SingProxy{
        private Sing sing = new Sing();
        public void sing(){
            System.out.println("using proxy ... ");
            sing.sing();
        }
    }

    public static void main(String[] args) {
        //用户感知代理的存在,并依赖代理的实现
        SingProxy singProxy = new SingProxy();
        singProxy.sing();
    }
}

9.外观模式

为了降低业务之间的耦合关系,避免复杂的网状依赖关系,设计一个集中管理的Facade类。 类比于天朝的民主集中制,一切向Facade看齐,变将网状依赖变为更加清晰的星状依赖。

public class FacadeDesignPattern {
    
    public static class BeanA{}
    public static class BeanB{}
    public static class BeanC{}
    
    public static class Facade{
        private static BeanA beanA=new BeanA();
        private static BeanB beanB=new BeanB();
        private static BeanC beanC=new BeanC();

        public static BeanA getBeanA() {
            return beanA;
        }

        public static BeanB getBeanB() {
            return beanB;
        }

        public static BeanC getBeanC() {
            return beanC;
        }
    }

    public static void main(String[] args) {
        BeanA beanA=Facade.getBeanA();
        //do some thing with beanA
    }
}

10.桥接模式

将抽象与实现分离,从而使二者可以独立变化。换句话,就是在抽象与具体实现之间添加一个中间类。通常在适配驱动的场景下,使用桥接模式。

public class BridgeDesignPattern {

    public static interface Driver{
        String run(String key);
    }
    public static class DriverA implements Driver{
        public String run(String key){
            return "driver A : "+key;
        }
    }
    public static class DriverB implements Driver{
        public String run(String key) {
            return "driver B : "+key;
        }
    }
    public static interface DataManager{
        String read(String key);
        //不依赖Driver是否实现 而新增功能
        boolean write(String key,String value);
    }

    public static class DataManagerBridge implements DataManager{

        Driver driver;

        public String read(String key) {
            if(driver!=null) return driver.run(key);
            return null;
        }

        // 虽然driver 暂时不支持写入,可以在桥接器中提供默认实现
        public boolean write(String key, String value) {
            return false;
        }
    }

    public static void main(String[] args) {
        DataManagerBridge dataManagerBridge=new DataManagerBridge();
        //桥接器注入 具体driver实现
        dataManagerBridge.driver=new DriverA();
        System.out.println(dataManagerBridge.read("key"));
        System.out.println(dataManagerBridge.write("key","value"));
    }
}

11.组合模式

主要用来构建一些稍复杂的数据结构,如二叉树、B+树等。

代码示例略,请参考二叉树实现。

12.享元模式

主要用来缓存对象示例,减少新建对象的开销。最典型的应用是数据库连接池、线程池等。

代码示例略,请参考数据库连接池实现。

行为设计模式 11种


13.策略模式

封装一系列的算法,每个算法为一个实现类,实现共同的接口。由外部用户的输入,动态的决定使用哪个算法。 常见用于决策算法,以及个性化或场景化推荐系统。

public class StrategyDesignPattern {

    public static interface Recommend{
        String recommendProduct();
    }

    public static class ManRecommend implements Recommend{

        public String recommendProduct() {
            return "Cars";
        }
    }

    public static class WomanRecommend implements Recommend{

        public String recommendProduct() {
            return "Flowers";
        }
    }

    public static class RecommendManager{
        public String recommend(Map<String,String> params){
            Recommend recommend=null;
            if(params.containsKey("man")) recommend=new ManRecommend();
            else recommend=new WomanRecommend();
            return recommend.recommendProduct();
        }
    }

    public static void main(String[] args) {
        Map<String,String> map=new HashMap<String, String>();
        System.out.println(new RecommendManager().recommend(map));
    }

}

14.模板模式

由抽象类定义一些列的抽象方法或实现方法,子类只需实现必要的抽象方法。多用于业务流程的抽象,极大提高代码复用性。

代码示例略。

15.观察者模式

类似于发布订阅的Server主动推送模型。观察者将自己注册到发布者中,当有观察者关心的时间发生时,发布者会回调观察者。

代码示例略。

16.迭代子模式

提供集合遍历的统一接口,参考jdk中集合类的实现。

17.责任链模式

将一系列的处理实体类串联起来,按顺序依次调用,直到有实体类决定终止向后调用并处理请求。典型的例子是web应用的FilterChain。

18.命令模式

主要目的是将调用者和实现者解耦,调用者只需关注发号Command,实现者实现具体逻辑,Command中需要注入实现者。

19.备忘录模式

将对象某时刻的状态整个保存下来,在适当的时候可以恢复。

20.状态模式

当对象的状态改变时,对外表现出明显不同的行为。类比qq状态改变,qq好友就可能无法发出振动。

21.访问者模式

适合数据结构很稳定,但算法经常改变的情况。客户可以定义多个Visitor, Subject被访问者只需要accept访问者,并提供通用的数据访问。

22.中介者模式

目的是解耦类之间的调用,通过统一的Mediator来协调调用。典型的生活例子是租房,租房者和房东都去找中介者,中介来协调合同签订。 每个相关的类只需要持有中介者的引用,中介者持有所有相关类的引用。

23.解释器模式

主要用于解释器的实现。


Creative Commons License
This work is licensed under a CC A-S 4.0 International License.