博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java 中几种常用设计模式
阅读量:4857 次
发布时间:2019-06-11

本文共 15392 字,大约阅读时间需要 51 分钟。

Java 中一般认为有23种设计模式,当然暂时不需要所有的都会,但是其中常见的几种设计模式应该去掌握。

总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

1. 单例模式

所谓的单例设计指的是一个类只允许产生一个实例化对象

最好理解的一种设计模式,分为懒汉式饿汉式

1.饿汉式

  ——构造方法私有化,外部无法产生新的实例化对象,只能通过static方法取得实例化对象

class Singleton {    /**     * 在类的内部可以访问私有结构,所以可以在类的内部产生实例化对象     */    private static Singleton instance = new Singleton();    /**     * private 声明构造     */    private Singleton() {    }    /**     * 返回对象实例     */    public static Singleton getInstance() {        return instance;    }    public void print() {        System.out.println("Hello Singleton...");    }}

 

 

2.懒汉式

  ——当第一次去使用Singleton对象的时候才会为其产生实例化对象的操作

class Singleton {    /**     * 声明变量     */    private static volatile Singleton singleton = null;    /**     * 私有构造方法     */    private Singleton() {    }    /**     * 提供对外方法     * @return      */    public static Singleton getInstance() {        // 还未实例化        if (singleton == null) {            synchronized (Singleton.class) {                if (singleton == null) {                    singleton = new Singleton();                }            }        }        return singleton;    }    public void print() {        System.out.println("Hello World");    }}

当多个线程并发执行 getInstance 方法时,懒汉式会存在线程安全问题,所以用到了 synchronized 来实现线程的同步,当一个线程获得锁的时候其他线程就只能在外等待其执行完毕。

而饿汉式则不存在线程安全的问题。

2. 工厂设计模式

工厂模式分为工厂方法模式和抽象工厂模式。

工厂方法模式

工厂方法模式: 1. 工厂方法模式分为三种:普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。 2. 多个工厂方法模式,是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。 3. 静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

1. 普通工厂模式

建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

interface Sender {    void Send();}class MailSender implements Sender {    @Override    public void Send() {        System.out.println("This is mail sender...");    }}class SmsSender implements Sender {    @Override    public void Send() {        System.out.println("This is sms sender...");    }}public class FactoryPattern {    public static void main(String[] args) {        Sender sender = produce("mail");        sender.Send();    }    public static Sender produce(String str) {        if ("mail".equals(str)) {            return new MailSender();        } else if ("sms".equals(str)) {            return new SmsSender();        } else {            System.out.println("输入错误...");            return null;        }    }}

 

 

2. 多个工厂方法模式

该模式是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

interface Sender {    void Send();}class MailSender implements Sender {    @Override    public void Send() {        System.out.println("This is mail sender...");    }}class SmsSender implements Sender {    @Override    public void Send() {        System.out.println("This is sms sender...");    }}class SendFactory {    public Sender produceMail() {        return new MailSender();    }    public Sender produceSms() {        return new SmsSender();    }}public class FactoryPattern {    public static void main(String[] args) {        SendFactory factory = new SendFactory();        Sender sender = factory.produceMail();        sender.Send();    }}

 

 

3. 静态工厂方法模式

将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

interface Sender {    void Send();}class MailSender implements Sender {    @Override    public void Send() {        System.out.println("This is mail sender...");    }}class SmsSender implements Sender {    @Override    public void Send() {        System.out.println("This is sms sender...");    }}class SendFactory {    public static Sender produceMail() {        return new MailSender();    }    public static Sender produceSms() {        return new SmsSender();    }}public class FactoryPattern {    public static void main(String[] args) {        Sender sender = SendFactory.produceMail();        sender.Send();    }}

 

 

抽象工厂模式

工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要扩展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?
那么这就用到了抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

interface Provider {    Sender produce();}interface Sender {    void Send();}class MailSender implements Sender {    public void Send() {        System.out.println("This is mail sender...");    }}class SmsSender implements Sender {    public void Send() {        System.out.println("This is sms sender...");    }}class SendMailFactory implements Provider {    public Sender produce() {        return new MailSender();    }}class SendSmsFactory implements Provider {    public Sender produce() {        return new SmsSender();    }}public class FactoryPattern {    public static void main(String[] args) {        Provider provider = new SendMailFactory();        Sender sender = provider.produce();        sender.Send();    }}

 

 

3. 建造者模式

工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性。

import java.util.ArrayList;import java.util.List;/** * @Author: LiuWang * @Created: 2018/8/6 17:47 */abstract class Builder {    /**     * 第一步:装CPU     */   public abstract void buildCPU();    /**     * 第二步:装主板     */    public abstract void buildMainBoard();    /**     * 第三步:装硬盘     */    public abstract void buildHD();    /**     * 获得组装好的电脑     * @return     */    public abstract Computer getComputer();}/** * 装机人员装机 */class Director {    public void Construct(Builder builder) {        builder.buildCPU();        builder.buildMainBoard();        builder.buildHD();    }}/** * 具体的装机人员 */class ConcreteBuilder extends  Builder {    Computer computer = new Computer();    @Override    public void buildCPU() {        computer.Add("装CPU");    }    @Override    public void buildMainBoard() {        computer.Add("装主板");    }    @Override    public void buildHD() {        computer.Add("装硬盘");    }    @Override    public Computer getComputer() {        return computer;    }}class Computer {    /**     * 电脑组件集合     */    private List
parts = new ArrayList
(); public void Add(String part) { parts.add(part); } public void print() { for (int i = 0; i < parts.size(); i++) { System.out.println("组件:" + parts.get(i) + "装好了..."); } System.out.println("电脑组装完毕..."); }}public class BuilderPattern { public static void main(String[] args) { Director director = new Director(); Builder builder = new ConcreteBuilder(); director.Construct(builder); Computer computer = builder.getComputer(); computer.print(); }}

 

 

4. 适配器设计模式

适配器模式是将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的的类的兼容性问题。

主要分三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

1. 类的适配器模式:

class Source {    public void method1() {        System.out.println("This is original method...");    }}interface Targetable {    /**     * 与原类中的方法相同     */    public void method1();    /**     * 新类的方法     */    public void method2();}class Adapter extends Source implements Targetable {    @Override    public void method2() {        System.out.println("This is the targetable method...");    }}public class AdapterPattern {    public static void main(String[] args) {        Targetable targetable = new Adapter();        targetable.method1();        targetable.method2();    }}

 

2. 对象的适配器模式

基本思路和类的适配器模式相同,只是将Adapter 类作修改,这次不继承Source 类,而是持有Source 类的实例,以达到解决兼容性的问题。

class Source {    public void method1() {        System.out.println("This is original method...");    }}interface Targetable {    /**     * 与原类中的方法相同     */    public void method1();    /**     * 新类的方法     */    public void method2();}class Wrapper implements Targetable {    private Source source;    public Wrapper(Source source) {        super();        this.source = source;    }    @Override    public void method1() {        source.method1();    }    @Override    public void method2() {        System.out.println("This is the targetable method...");    }}public class AdapterPattern {    public static void main(String[] args) {        Source source = new Source();        Targetable targetable = new Wrapper(source);        targetable.method1();        targetable.method2();    }}

 

 

3. 接口的适配器模式

接口的适配器是这样的:有时我们写的一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。

/** * 定义端口接口,提供通信服务 */interface Port {    /**     * 远程SSH端口为22     */    void SSH();    /**     * 网络端口为80     */    void NET();    /**     * Tomcat容器端口为8080     */    void Tomcat();    /**     * MySQL数据库端口为3306     */    void MySQL();}/** * 定义抽象类实现端口接口,但是什么事情都不做 */abstract class Wrapper implements Port {    @Override    public void SSH() {    }    @Override    public void NET() {    }    @Override    public void Tomcat() {    }    @Override    public void MySQL() {    }}/** * 提供聊天服务 * 需要网络功能 */class Chat extends Wrapper {    @Override    public void NET() {        System.out.println("Hello World...");    }}/** * 网站服务器 * 需要Tomcat容器,Mysql数据库,网络服务,远程服务 */class Server extends Wrapper {    @Override    public void SSH() {        System.out.println("Connect success...");    }    @Override    public void NET() {        System.out.println("WWW...");    }    @Override    public void Tomcat() {        System.out.println("Tomcat is running...");    }    @Override    public void MySQL() {        System.out.println("MySQL is running...");    }}public class AdapterPattern {    private static Port chatPort = new Chat();    private static Port serverPort = new Server();    public static void main(String[] args) {        // 聊天服务        chatPort.NET();        // 服务器        serverPort.SSH();        serverPort.NET();        serverPort.Tomcat();        serverPort.MySQL();    }}

 

 

5. 装饰模式

顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。

interface Shape {    void draw();}/** * 实现接口的实体类 */class Rectangle implements Shape {    @Override    public void draw() {        System.out.println("Shape: Rectangle...");    }}class Circle implements Shape {    @Override    public void draw() {        System.out.println("Shape: Circle...");    }}/** * 创建实现了 Shape 接口的抽象装饰类。 */abstract class ShapeDecorator implements Shape {    protected Shape decoratedShape;    public ShapeDecorator(Shape decoratedShape) {        this.decoratedShape = decoratedShape;    }    @Override    public void draw() {        decoratedShape.draw();    }}/** *  创建扩展自 ShapeDecorator 类的实体装饰类。 */class RedShapeDecorator extends ShapeDecorator {    public RedShapeDecorator(Shape decoratedShape) {        super(decoratedShape);    }    @Override    public void draw() {        decoratedShape.draw();        setRedBorder(decoratedShape);    }    private void setRedBorder(Shape decoratedShape) {        System.out.println("Border Color: Red");    }}/** * 使用 RedShapeDecorator 来装饰 Shape 对象。 */public class DecoratorPattern {    public static void main(String[] args) {        Shape circle = new Circle();        Shape redCircle = new RedShapeDecorator(new Circle());        Shape redRectangle = new RedShapeDecorator(new Rectangle());        System.out.println("Circle with normal border");        circle.draw();        System.out.println("\nCircle of red border");        redCircle.draw();        System.out.println("\nRectangle of red border");        redRectangle.draw();    }}

 

 

6. 策略模式

策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数。策略模式的决定权在用户,系统本身提供不同算法的实现,新增或者删除算法,对各种算法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可。

/** * 抽象算法的策略类,定义所有支持的算法的公共接口 */abstract class Strategy {    /**     * 算法方法     */    public abstract void AlgorithmInterface();}/** * 具体算法A */class ConcreteStrategyA extends Strategy {    //算法A实现方法    @Override    public void AlgorithmInterface() {        System.out.println("算法A的实现");    }}/** * 具体算法B */class ConcreteStrategyB extends Strategy {    /**     * 算法B实现方法     */    @Override    public void AlgorithmInterface() {        System.out.println("算法B的实现");    }}/** * 具体算法C */class ConcreteStrategyC extends Strategy {    @Override    public void AlgorithmInterface() {        System.out.println("算法C的实现");    }}/** * 上下文,维护一个对策略类对象的引用 */class Context {    Strategy strategy;    public Context(Strategy strategy) {        this.strategy = strategy;    }    public void contextInterface(){        strategy.AlgorithmInterface();    }}/** * 客户端代码:实现不同的策略 */public class StrategyPattern {    public static void main(String[] args) {        Context context;        context = new Context(new ConcreteStrategyA());        context.contextInterface();        context = new Context(new ConcreteStrategyB());        context.contextInterface();        context = new Context(new ConcreteStrategyC());        context.contextInterface();    }}

 

 

7. 代理模式

代理模式指给一个对象提供一个代理对象,并由代理对象控制对原对象的引用。代理可以分为静态代理和动态代理。

通过代理模式,可以利用代理对象为被代理对象添加额外的功能,以此来拓展被代理对象的功能。可以用于计算某个方法执行时间,在某个方法执行前后记录日志等操作。

1. 静态代理

静态代理需要我们写出代理类和被代理类,而且一个代理类和一个被代理类一一对应。代理类和被代理类需要实现同一个接口,通过聚合使得代理对象中有被代理对象的引用,以此实现代理对象控制被代理对象的目的。

/** * 代理类和被代理类共同实现的接口 */interface IService {    void service();}/** * 被代理类 */class Service implements IService{    @Override    public void service() {        System.out.println("被代理对象执行相关操作");    }}/** * 代理类 */class ProxyService implements IService{    /**     * 持有被代理对象的引用     */    private IService service;    /**     * 默认代理Service类     */    public ProxyService() {        this.service = new Service();    }    /**     * 也可以代理实现相同接口的其他类     * @param service     */    public ProxyService(IService service) {        this.service = service;    }    @Override    public void service() {        System.out.println("开始执行service()方法");        service.service();        System.out.println("service()方法执行完毕");    }}//测试类public class ProxyPattern {    public static void main(String[] args) {        IService service = new Service();        //传入被代理类的对象        ProxyService proxyService = new ProxyService(service);        proxyService.service();    }}

 

 

2. 动态代理

JDK 1.3 之后,Java通过java.lang.reflect包中的三个类Proxy、InvocationHandler、Method来支持动态代理。动态代理常用于有若干个被代理的对象,且为每个被代理对象添加的功能是相同的(例如在每个方法运行前后记录日志)。

动态代理的代理类不需要我们编写,由Java自动产生代理类源代码并进行编译最后生成代理对象。

创建动态代理对象的步骤:
1. 指明一系列的接口来创建一个代理对象
2. 创建一个调用处理器(InvocationHandler)对象
3. 将这个代理指定为某个其他对象的代理对象
4. 在调用处理器的invoke()方法中采取代理,一方面将调用传递给真实对象,另一方面执行各种需要的操作

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 代理类和被代理类共同实现的接口 */interface IService {    void service();}class Service implements IService{    @Override    public void service() {        System.out.println("被代理对象执行相关操作");    }}class ServiceInvocationHandler implements InvocationHandler {    /**     * 被代理的对象     */    private Object srcObject;    public ServiceInvocationHandler(Object srcObject) {        this.srcObject = srcObject;    }    @Override    public Object invoke(Object proxyObj, Method method, Object[] args) throws Throwable {        System.out.println("开始执行"+method.getName()+"方法");        //执行原对象的相关操作,容易忘记        Object returnObj = method.invoke(srcObject,args);        System.out.println(method.getName()+"方法执行完毕");        return returnObj;    }}public class ProxyPattern {    public static void main(String[] args) {        IService service = new Service();        Class
clazz = service.getClass(); IService proxyService = (IService) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new ServiceInvocationHandler(service)); proxyService.service(); }}

 

转载于:https://www.cnblogs.com/Diyo/p/11415588.html

你可能感兴趣的文章
20941输入输出系统
查看>>
使用 Flash 描述复杂的社交网络
查看>>
唐骏十年管理经验谈:管理者要学会让员工感动
查看>>
几道和「黑洞照片」那种海量数据有关的算法问题
查看>>
为什么有禁用Mac系统的Spotlight的需求:
查看>>
paip. 定时 关机 休眠 的总结
查看>>
Oracle core02_数据块
查看>>
检查用户名是否存在jsp——access
查看>>
AmazeUI 保存浏览器数据 永久性
查看>>
使用内存数据库进行单元测试
查看>>
centos7 64位系统jdbc连接oracle报错问题
查看>>
最清晰细致的教程!一步步教你打造Win7+CentOS双系统
查看>>
移动端部分安卓手机(三星,小米)竖拍上传图片预览的时候发生旋转问题
查看>>
Visual Studio 11 Beta 官方下载地址
查看>>
渲染树render tree
查看>>
BZOJ3810: [Coci2015]Stanovi
查看>>
12、Flask实战第12天:子域名
查看>>
关于文字内容溢出用点点点(…)省略号表示
查看>>
(转)人与人
查看>>
字符串搜索
查看>>