参考https://blog.csdn.net/jiyang_1/article/details/50110931

参考https://blog.csdn.net/dean_hu/article/details/71195133

练习参考https://blog.csdn.net/Wu_Ming0821/article/details/51838078,靠谱

设计模式介绍:

  • 创建型:简单工厂模式(并不是23种设计模式之一)、工厂方法、抽象工厂模式、单例模式、生成器模式和原型模式
  • 结构型:适配器模式adapter、桥接模式bridge、组合器模式component、装饰器模式decorator、门面模式、亨元模式flyweight和代理模式proxy
  • 行为型:命令模式command、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式state、策略模式、模板模式和访问者模式

常用的几种设计模式介绍

1、单例模式

如果一个类始终只能创建一个实例,则这个类被称为单例类,这种模式就被称为单例模式。一般建议单例模式的方法命名为:getInstance(),这个方法的返回类型肯定是单例类的类型了。getInstance方法可以有参数,这些参数可能是创建类实例所需要的参数,当然,大多数情况下是不需要的。实现单例模式的简单例子:

  1.  
    public class Singleton {
  2.  
    public static void main(String[] args)
  3.  
    {
  4.  
    //创建Singleton对象不能通过构造器,只能通过getInstance方法
  5.  
    Singleton s1 = Singleton.getInstance();
  6.  
    Singleton s2 = Singleton.getInstance();
  7.  
    //将输出true
  8.  
    System.out.println(s1 == s2);
  9.  
    }
  10.  
    //使用一个变量来缓存曾经创建的实例
  11.  
    private static Singleton instance;
  12.  
    //将构造器使用private修饰,隐藏该构造器
  13.  
    private Singleton(){
  14.  
    System.out.println("Singleton被构造!");
  15.  
    }
  16.  
    //提供一个静态方法,用于返回Singleton实例
  17.  
    //该方法可以加入自定义的控制,保证只产生一个Singleton对象
  18.  
    public static Singleton getInstance()
  19.  
    {
  20.  
    //如果instance为null,表明还不曾创建Singleton对象
  21.  
    //如果instance不为null,则表明已经创建了Singleton对象,将不会执行该方法
  22.  
    if (instance == null)
  23.  
    {
  24.  
    //创建一个Singleton对象,并将其缓存起来
  25.  
    instance = new Singleton();
  26.  
    }
  27.  
    return instance;
  28.  
    }
  29.  
    }

2、工厂模式

简单工厂模式的核心思想就是:有一个专门的类来负责创建实例的过程。 具体来说,把产品看着是一系列的类的集合,这些类是由某个抽象类或者接口派生出来的一个对象树。而工厂类用来产生一个合适的对象来满足客户的要求。如果简单工厂模式所涉及到的具体产品之间没有共同的逻辑,那么我们就可以使用接口来扮演抽象产品的角色;如果具体产品之间有功能的逻辑或,我们就必须把这些共同的东西提取出来,放在一个抽象类中,然后让具体产品继承抽象类。为实现更好复用的目的,共同的东西总是应该抽象出来的。

  1.  
    /*
  2.  
    * 产品的抽象接口
  3.  
    */
  4.  
    public interface Food {
  5.  
    /*
  6.  
    * 获得相应的食物
  7.  
    */
  8.  
    public void get();
  9.  
    }
  1.  
    /*
  2.  
    * 麦香鸡对抽象产品接口的实现
  3.  
    */
  4.  
    public class McChicken implements Food{
  5.  
    /*
  6.  
    * 获取一份麦香鸡
  7.  
    */
  8.  
    public void get(){
  9.  
    System.out.println("我要一份麦香鸡");
  10.  
    }
  11.  
    }
  1.  
    public class FoodFactory {
  2.  
     
  3.  
    public static Food getFood(String type) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
  4.  
    if(type.equalsIgnoreCase("mcchicken")) {
  5.  
    return McChicken.class.newInstance();
  6.  
     
  7.  
    } else if(type.equalsIgnoreCase("chips")) {
  8.  
    return Chips.class.newInstance();
  9.  
    } else {
  10.  
    System.out.println("哎呀!找不到相应的实例化类啦!");
  11.  
    return null;
  12.  
    }
  13.  
     
  14.  
     
  15.  
    }
  16.  
    }
  1.  
    /*
  2.  
    * 测试客户端
  3.  
    */
  4.  
    public class SimpleFactoryTest {
  5.  
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
  6.  
     
  7.  
    //实例化各种食物
  8.  
    Food mcChicken = FoodFactory.getFood("McChicken");
  9.  
    Food chips = FoodFactory.getFood("Chips");
  10.  
    Food eggs = FoodFactory.getFood("Eggs");
  11.  
     
  12.  
    //获取食物
  13.  
    if(mcChicken!=null){
  14.  
    mcChicken.get();
  15.  
    }
  16.  
    if(chips!=null){
  17.  
    chips.get();
  18.  
    }
  19.  
    if(eggs!=null){
  20.  
    eggs.get();
  21.  
    }
  22.  
     
  23.  
     
  24.  
    }
  25.  
    }

输出的结果如下:

哎呀!找不到相应的实例化类啦!

我要一份麦香鸡

我要一份薯条

3、代理模式

代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象时,客户端实际上不关心是否准确得到该对象,它只要一个能提供该功能的对象即可,此时我们就可返回该对象的代理(Proxy)。

代理就是一个Java对象代表另一个Java对象来采取行动。如:

  1.  
    public class ImageProxy implements Image
  2.  
    {
  3.  
    //组合一个image实例,作为被代理的对象
  4.  
    private Image image;
  5.  
    //使用抽象实体来初始化代理对象
  6.  
    public ImageProxy(Image image)
  7.  
    {
  8.  
    this.image = image;
  9.  
    }
  10.  
    /**
  11.  
    * 重写Image接口的show()方法
  12.  
    * 该方法用于控制对被代理对象的访问,
  13.  
    * 并根据需要负责创建和删除被代理对象
  14.  
    */
  15.  
    public void show()
  16.  
    {
  17.  
    //只有当真正需要调用image的show方法时才创建被代理对象
  18.  
    if (image == null)
  19.  
    {
  20.  
    image = new BigImage();
  21.  
    }
  22.  
    image.show();
  23.  
    }
  24.  
    }

调用时,先不创建:

Image image = new ImageProxy(null);

 

Hibernate默认启用延迟加载,当系统加载A实体时,A实体关联的B实体并未被加载出来,A实体所关联的B实体全部是代理对象——只有等到A实体真正需要访问B实体时,系统才会去数据库里抓取B实体所对应的记录。

借助于Java提供的Proxy和InvocationHandler,可以实现在运行时生成动态代理的功能,而动态代理对象就可以作为目标对象使用,而且增强了目标对象的功能。如:

  1.  
    public interface Panther
  2.  
    {
  3.  
    //info方法声明
  4.  
    public void info();
  5.  
    //run方法声明
  6.  
    public void run();
  7.  
    }
  1.  
    public class GunPanther implements Panther
  2.  
    {
  3.  
    //info方法实现,仅仅打印一个字符串
  4.  
    public void info()
  5.  
    {
  6.  
    System.out.println("我是一只猎豹!");
  7.  
    }
  8.  
    //run方法实现,仅仅打印一个字符串
  9.  
    public void run()
  10.  
    {
  11.  
    System.out.println("我奔跑迅速");
  12.  
    }
  13.  
    }
  1.  
    public class MyProxyFactory
  2.  
    {
  3.  
    //为指定target生成动态代理对象
  4.  
    public static Object getProxy(Object target)
  5.  
    throws Exception
  6.  
    {
  7.  
    //创建一个MyInvokationHandler对象
  8.  
    MyInvokationHandler handler =
  9.  
    new MyInvokationHandler();
  10.  
    //为MyInvokationHandler设置target对象
  11.  
    handler.setTarget(target);
  12.  
    //创建、并返回一个动态代理
  13.  
    return Proxy.newProxyInstance(target.getClass().getClassLoader()
  14.  
    , target.getClass().getInterfaces(), handler);
  15.  
    }
  16.  
    }
  1.  
    public class MyInvokationHandler implements InvocationHandler
  2.  
    {
  3.  
    //需要被代理的对象
  4.  
    private Object target;
  5.  
    public void setTarget(Object target)
  6.  
    {
  7.  
    this.target = target;
  8.  
    }
  9.  
    //执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法
  10.  
    public Object invoke(Object proxy, Method method, Object[] args)
  11.  
    throws Exception
  12.  
    {
  13.  
    TxUtil tx = new TxUtil();
  14.  
    //执行TxUtil对象中的beginTx。
  15.  
    tx.beginTx();
  16.  
    //以target作为主调来执行method方法
  17.  
    Object result = method.invoke(target , args);
  18.  
    //执行TxUtil对象中的endTx。
  19.  
    tx.endTx();
  20.  
    return result;
  21.  
    }
  22.  
    }
  1.  
    public class TxUtil
  2.  
    {
  3.  
    //第一个拦截器方法:模拟事务开始
  4.  
    public void beginTx()
  5.  
    {
  6.  
    System.out.println("=====模拟开始事务=====");
  7.  
    }
  8.  
    //第二个拦截器方法:模拟事务结束
  9.  
    public void endTx()
  10.  
    {
  11.  
    System.out.println("=====模拟结束事务=====");
  12.  
    }
  13.  
    }

测试:

  1.  
    public static void main(String[] args)
  2.  
    throws Exception
  3.  
    {
  4.  
    //创建一个原始的GunDog对象,作为target
  5.  
    Panther target = new GunPanther();
  6.  
    //以指定的target来创建动态代理
  7.  
    Panther panther = (Panther)MyProxyFactory.getProxy(target);
  8.  
    //调用代理对象的info()和run()方法
  9.  
    panther.info();
  10.  
    panther.run();
  11.  
    }

4、观测者模式

观察者模式结构中包括四种角色:

  一、主题:主题是一个接口,该接口规定了具体主题需要实现的方法,比如添加、删除观察者以及通知观察者更新数据的方法。

  二、观察者:观察者也是一个接口,该接口规定了具体观察者用来更新数据的方法。

  三、具体主题:具体主题是一个实现主题接口的类,该类包含了会经常发生变化的数据。而且还有一个集合,该集合存放的是观察者的引用。

  四:具体观察者:具体观察者是实现了观察者接口的一个类。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,让自己成为它的观察者,或者让这个具体主题将自己从具体主题的集合中删除,使自己不在时它的观察者。

观察者模式定义了对象间的一对多依赖关系,让一个或多个观察者对象观察一个主题对象。当主题对象的状态发生变化时,系统能通知所有的依赖于此对象的观察者对象,从而使得观察者对象能够自动更新。

在观察者模式中,被观察的对象常常也被称为目标或主题(Subject),依赖的对象被称为观察者(Observer)。

Observer,观察者接口:

观察者:观察者也是一个接口,该接口规定了具体观察者用来更新数据的方法

  1.  
    public interface Observer {
  2.  
    void update(Observable o, Object arg);
  3.  
    }

Observable,目标或主题:

主题:主题是一个接口,该接口规定了具体主题需要实现的方法,比如添加、删除观察者以及通知观察者更新数据的方法

  1.  
    import java.util.ArrayList;
  2.  
    import java.util.List;
  3.  
    import java.util.Iterator;
  4.  
     
  5.  
    public abstract class Observable {
  6.  
    // 用一个List来保存该对象上所有绑定的事件监听器
  7.  
    List<Observer> observers = new ArrayList<Observer>();
  8.  
     
  9.  
    // 定义一个方法,用于从该主题上注册观察者
  10.  
    public void registObserver(Observer o) {
  11.  
    observers.add(o);
  12.  
    }
  13.  
     
  14.  
    // 定义一个方法,用于从该主题中删除观察者
  15.  
    public void removeObserver(Observer o) {
  16.  
    observers.add(o);
  17.  
    }
  18.  
     
  19.  
    // 通知该主题上注册的所有观察者
  20.  
    public void notifyObservers(Object value) {
  21.  
    // 遍历注册到该被观察者上的所有观察者
  22.  
    for (Iterator it = observers.iterator(); it.hasNext();) {
  23.  
    Observer o = (Observer) it.next();
  24.  
    // 显式每个观察者的update方法
  25.  
    o.update(this, value);
  26.  
    }
  27.  
    }
  28.  
    }

Product被观察类:

具体主题:具体主题是一个实现主题接口的类,该类包含了会经常发生变化的数据。而且还有一个集合,该集合存放的是观察者的引用。

  1.  
    public class Product extends Observable {
  2.  
    // 定义两个属性
  3.  
    private String name;
  4.  
    private double price;
  5.  
     
  6.  
    // 无参数的构造器
  7.  
    public Product() {
  8.  
    }
  9.  
     
  10.  
    public Product(String name, double price) {
  11.  
    this.name = name;
  12.  
    this.price = price;
  13.  
    }
  14.  
     
  15.  
    public String getName() {
  16.  
    return name;
  17.  
    }
  18.  
     
  19.  
    // 当程序调用name的setter方法来修改Product的name属性时
  20.  
    // 程序自然触发该对象上注册的所有观察者
  21.  
    public void setName(String name) {
  22.  
    this.name = name;
  23.  
    notifyObservers(name);
  24.  
    }
  25.  
     
  26.  
    public double getPrice() {
  27.  
    return price;
  28.  
    }
  29.  
     
  30.  
    // 当程序调用price的setter方法来修改Product的price属性时
  31.  
    // 程序自然触发该对象上注册的所有观察者
  32.  
    public void setPrice(double price) {
  33.  
    this.price = price;
  34.  
    notifyObservers(price);
  35.  
    }
  36.  
    }

具体观察者:具体观察者是实现了观察者接口的一个类。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,让自己成为它的观察者,或者让这个具体主题将自己从具体主题的集合中删除,使自己不在时它的观察者。

NameObserver名称观察者:

  1.  
    import javax.swing.JFrame;
  2.  
    import javax.swing.JLabel;
  3.  
     
  4.  
    public class NameObserver implements Observer {
  5.  
    // 实现观察者必须实现的update方法
  6.  
    public void update(Observable o, Object arg) {
  7.  
    if (arg instanceof String) {
  8.  
    // 产品名称改变值在name中
  9.  
    String name = (String) arg;
  10.  
    // 启动一个JFrame窗口来显示被观察对象的状态改变
  11.  
    JFrame f = new JFrame("观察者");
  12.  
    JLabel l = new JLabel("名称改变为:" + name);
  13.  
    f.add(l);
  14.  
    f.pack();
  15.  
    f.setVisible(true);
  16.  
    System.out.println("名称观察者:" + o + "物品名称已经改变为: " + name);
  17.  
    }
  18.  
    }
  19.  
    }

PriceObserver价格观察者:

  1.  
    public class PriceObserver implements Observer {
  2.  
    // 实现观察者必须实现的update方法
  3.  
    public void update(Observable o, Object arg) {
  4.  
    if (arg instanceof Double) {
  5.  
    System.out.println("价格观察者:" + o + "物品价格已经改变为: " + arg);
  6.  
    }
  7.  
    }
  8.  
    }

测试:

  1.  
    public class Test {
  2.  
    public static void main(String[] args) {
  3.  
    // 创建一个被观察者对象
  4.  
    Product p = new Product("电视机", 176);
  5.  
    // 创建两个观察者对象
  6.  
    NameObserver no = new NameObserver();
  7.  
    PriceObserver po = new PriceObserver();
  8.  
    // 向被观察对象上注册两个观察者对象
  9.  
    p.registObserver(no);
  10.  
    p.registObserver(po);
  11.  
    // 程序调用setter方法来改变Product的name和price属性
  12.  
    p.setName("书桌");
  13.  
    p.setPrice(345f);
  14.  
    }
  15.  
    }

其中Java工具类提供了被观察者抽象基类:java.util.Observable。观察者接口:java.util.Observer。

java中几种常用的设计模式的更多相关文章

  1. 聊聊Java中几种常用的设计模式

    1.单例模式(有的书上说叫单态模式其实都一样) 该模式主要目的是使内存中保持1个对象.看下面的例子: package org.sp.singleton; //方法一 public class Sing ...

  2. Java中几种常用数据类型之间转换的方法

    Java中几种常用的数据类型之间转换方法: 1. short-->int 转换 exp: short shortvar=0; int intvar=0; shortvar= (short) in ...

  3. java 中几种常用数据结构

    Java中有几种常用的数据结构,主要分为Collection和map两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类. 一.几个常用类的区别 1.A ...

  4. Java 中几种常用设计模式

    Java 中一般认为有23种设计模式,当然暂时不需要所有的都会,但是其中常见的几种设计模式应该去掌握. 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模 ...

  5. java中4种常用线程池

    一.线程池 线程池:说白了,就是一种线程使用模式.线程过多会带来调度开销,进而影响整体性能.而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务,这避免了在处理短时间任务时创建与销毁线程的代价 ...

  6. JAVA中几种常用的RPC框架介绍

    原文:https://blog.csdn.net/zhaowen25/article/details/45443951

  7. Java中几种日志方案

    .本文记录Java中几种常用的日志解决方案 0x01 Log4j .这应该是一个比较老牌的日志方案了,配置也比较简单,步骤如下 1)添加对应依赖,比如 Gradle 中 dependencies { ...

  8. Java基础-Java中23种设计模式之常用的设计模式

    Java基础-Java中23种设计模式之常用的设计模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.设计模式分类 设计模式是针对特定场景给出的专家级的解决方案.总的来说设 ...

  9. Java中23种经典设计模式详解

    Java中23种设计模式目录1. 设计模式 31.1 创建型模式 41.1.1 工厂方法 41.1.2 抽象工厂 61.1.3 建造者模式 101.1.4 单态模式 131.1.5 原型模式 151. ...

随机推荐

  1. Cannot create PoolableConnectionFactory (Communications link failure The last packet sent successfu

    SQL: Cannot create JDBC driver of class '' for connect URL 使用数据库数据源的web 项目,发布后,访问数据库500报错: 浏览器端: 控制台 ...

  2. python接口测试-将运行结果写入Excel表格

    公司工作是促进学习的第一生产力!! 一个get请求的接口,我想清楚的在Excel中看到所有的数据! 带着学过H5,php觉得所有代码都很简单的自信,在公司开发的[鼓励]下开始了一上午的斗争 一个小时. ...

  3. 安装并激活pycharm

    进入 pycharm官网 https://www.jetbrains.com/pycharm/ 或直接百度pycharm进入官网 点击download now 下载专业版: 点击保存文件: 双击 py ...

  4. app内嵌vue h5,安卓和ios拦截H5点击事件

    安卓和ios拦截h5点击事件,这个函数事件必须是暴漏在window下的 安卓和ios拦截普通h5函数: <div onclick = "show(),window.android.sh ...

  5. laravel-阿里大于

    安装扩展 # 安装curl模块apt-get install curl # 安装php5-curl扩展apt-get install php5-curl # 安装laravel阿里大鱼服务compos ...

  6. 最新版的Chrome如何设置网页编码

    在最新的V55版本中已经没有了编码选项,没有了这个可能会导致一些特殊编码网页出现乱码问题.那么如何找回这个Chrome的编码功能?可以通过下载chrome扩展:Set Character Encodi ...

  7. 随笔:关于Class.getSimpleName()

    最近学习过程中,遇到了Class.getSimpleName()这个方法,就搜索了一些资料: API定义: Class.getName():以String的形式,返回Class对象的"实体& ...

  8. Python基础:五、Python程序的编写方式

    python程序有两种编写方式: 1. 进入cmd控制台(linux终端),输入python进入编辑模式,这时候我们可以直接编写python程序 2. 也可以在.py文件中编写python代码,通过p ...

  9. 5. Web vulnerability scanners (网页漏洞扫描器 20个)

    5. Web vulnerability scanners (网页漏洞扫描器 20个) Burp Suite是攻击Web应用程序的集成平台. 它包含各种工具,它们之间有许多接口,旨在方便和加快攻击应用 ...

  10. [双系统linux] ----双系统切换导致系统时间错误

    安装了linux双系统以后,发现每次双系统切换以后系统时间总会错误. 原因:Linux和win7(win10)双系统时间错误问题 时间相差8小时 MAC/linux 将系统硬件时间看待为UTC, 即U ...