常用的Java设计模式(一)

一、单例模式
为什么使用单例模式呢,那就需要理解我们什么时候会使用到单例。
比如有些对象我们只需要一个,例如配置文件、工具类、线程池、缓存、日志等,,,,
这个时候我们就会需要一个单例,而不需要在使用的时候创建了其他的实例。

单例模式分为 饿汉模式 懒汉模式
那么接下来用代码来看看单例模式的实现吧

饿汉模式的单例(线程安全的)

package com.Singleton;

/** * 单例模式 应用场合:有些对象只需要一个就足够了,如古代皇帝 作用: * 保证整个应用程序中某个实例只有一个 类型:饿汉模式 懒汉模式 * * @author ruolan * */
public class Singleton {
    // 饿汉模式 在类加载的时候,就会创建类的唯一的实例
    // 1、构造方法私有化,不允许外部直接创建对象
    private Singleton() {
    }
    // 2、创建类的唯一实例(私有的,不允许外部成员访问)
    private static Singleton instance = new Singleton();

    // 3、提供一个用于获取实例的公开的静态的方法
    // static 在类加载的时候直接加载。
    public static Singleton getInstance() {
        return instance;
    }
}

测试类:

package com.Singleton;

public class Test {

    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        if (s1 == s2) {
            System.out.println("s1和s2是同一个实例");
        } else {
            System.out.println("s1和s2不是同一个实例");
        }
    }
}

输出结果

s1和s2是同一个实例

懒汉模式:

package com.Singleton;

//懒汉模式
//
public class Singleton2 {

    // 1、将构造方法私有化
    private Singleton2() {
    }

    // 2、声明这个类的唯一实例,使用private static修饰
    private static Singleton2 instance;

    // 3、提供一个公开的静态的方法获取实例
    public static Singleton2 getInstance() {
        if (instance == null) {
        //代码改成这样之后,只有在instance还没被初始化的时候才会进入到第3行,然后加上同步锁。
        //等instance一但初始化完成了,就再也走不到第3行了,这样执行getInstance方法也不会再
        //受到同步锁的影响,效率上会有一定的提升。
            synchronized (Singleton2.class) {
                if (instance == null) {
                    instance = new Singleton2();
                }
            }
        }
        return instance;
    }
}

测试类:

package com.Singleton;

public class Test {

    public static void main(String[] args) {

        Singleton2 s3 = Singleton2.getInstance();
        Singleton2 s4 = Singleton2.getInstance();
        if (s3 == s4) {
            System.out.println("s3和s4是同一个实例");
        } else {
            System.out.println("s3和s4不是同一个实例");
        }

    }

}

输出结果:

s3和s4是同一个实例

那么懒汉模式和饿汉模式的区别呢?

区别:饿汉模式在加载类的时候比较慢,运行的时候获取对象的速度快(已经创建了)线程安全
懒汉模式在加载类的时候比较快,运行的时候获取对象的速度慢(还没创建)线程不安全这个时候就要加锁了。

二、工厂模式
1、工厂模式的概念
实例化对象,用工厂方法代替new操作

2、什么情况下使用工厂模式
有一组类似的对象要创建
在编码的时候不能预测要创建那种类的实例
系统需要考虑扩展性,不应该依赖于产品类实例被创建、组合和表达的细节
3、工厂模式的uml图
常用的Java设计模式(一)_第1张图片
下面我们就来利用一个实例来简单的实现一下工厂模式吧

package com.sunny.project;

/** * 发型接口 * @author ruolan * */
public interface HairInterface {
    //实现了发型
    public void draw();
}
package com.sunny.project;

/** * 发型工厂 * * @author ruolan * */
public class HairFactory {

    /** * 根据类型来创建对象 * * @param key * @return */
    public HairInterface getHair(String key) {
        if ("left".equals(key)) {
            return new LeftHair();
        } else if ("right".equals(key)) {
            return new RightHair();
        }
        return null;
    }

    /** * 根据类的名称来生产对象 * @param className * @return */
    public HairInterface getHairByClass(String className){
        try {
            HairInterface hair = (HairInterface) Class.forName(className).newInstance();
            return hair;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

}
package com.sunny.project;

/** * 画一个左偏分发型 * @author ruolan * */
public class LeftHair implements HairInterface {

    @Override
    public void draw() {
        System.out.println("---左偏分发型----");
    }


}
package com.sunny.project;

public class RightHair implements HairInterface{

    @Override
    public void draw() {
        System.out.println("----右偏分发型----");
    }

}

测试类:

package com.sunny.project;

public class SunnyTest {

    public static void main(String[] args) {
        HairFactory factory = new HairFactory();
        HairInterface left = factory.getHair("left");
        if (left != null) {
            left.draw();
        }
    }
}

输出结果:

---左偏分发型----

抽象工厂模式
1、抽象工厂模式uml图

常用的Java设计模式(一)_第2张图片
2、来看下具体的实现吧
先创建一个uml图形中的Factory——>PersonFactory

package com.sunny.project;

public interface PersonFactory {

    //男孩接口
    public Boy getBoy();
    //女孩接口
    public Girl getGirl();

}

这里创建一个uml中ConcreteFactory1的—–> MCFactory

package com.sunny.project;

public class MCFactory implements PersonFactory{

    @Override
    public Boy getBoy() {
        return new MCBoy();
    }

    @Override
    public Girl getGirl() {
        return new MCGirl();
    }

}

这里创建一个uml中ConcreteFactory2的—–> XNFactory

package com.sunny.project;

public class XNFactory implements PersonFactory{

    @Override
    public Boy getBoy() {
        return new XNBoy();
    }

    @Override
    public Girl getGirl() {
        return new XNGirl();
    }

}

这里创建一个uml中AbstractProductA的—–> Boy

package com.sunny.project;

public interface Boy {
    public void drawBoy();
}

这里创建一个uml中AbstractProductB的—–> Girl

package com.sunny.project;

public interface Girl {

    public void drawWoman();

}

这里创建一个uml中ConcreteProducrA1的—–> MCBoy

package com.sunny.project;

public class MCBoy implements Boy {

    @Override
    public void drawBoy() {
        System.out.println("圣诞系列的男孩");
    }

}

这里创建一个uml中ConcreteProducrA1的—–> MCGirl

package com.sunny.project;

public class MCGirl implements Girl {

    @Override
    public void drawWoman() {
        System.out.println("圣诞系列的女孩");
    }

}

这里创建一个uml中ConcreteProducrB的—–> XNGirl

package com.sunny.project;

public class XNGirl implements Girl {

    @Override
    public void drawWoman() {
        System.out.println("新年系列的女孩");
    }

}

这里创建一个uml中ConcreteProducrB的—–> XNBoy

package com.sunny.project;

public class XNBoy implements Boy {

    @Override
    public void drawBoy() {
        System.out.println("新年系列的男孩");
    }

}

测试类:

package com.sunny.project;

public class SunnyTest {

    public static void main(String[] args) {

        PersonFactory factory = new MCFactory();
        Girl girl = factory.getGirl();
        girl.drawWoman();
        Boy boy = factory.getBoy();
        boy.drawBoy();
    }

}

运行结果:

圣诞系列的女孩
圣诞系列的男孩

工厂模式的实现帮助我们:
系统可以在不修改具体工厂角色的情况下引进新的产品
客户端不必关心对象如果创建,明确了职责
更好的理解面向对象的原则,面向接口编程,而不要面向实现编程

工厂方法模式和抽象工厂模式对比:
工厂模式是一种极端情况的抽象工厂模式,而抽象工厂模式可以看成工厂模式的推广
工厂模式用来创建一个产品的等级结构,而抽象工厂模式是用来创建多个产品的等级结构
工厂模式只有一个抽象产品类,而抽象工厂模式有多个抽象产品类

工厂模式使用的哪些场景:
一个系统应当不依赖于产品类实例被创立、组成、和表示的细节,这对于所有形态的工厂模式都是重要的
这个系统的产品有至少一个产品族
同属于一个产品族的产品是设计成在一起使用的,这一约束必须的在系统的设计中体现出来
不同的产品以一种接口的面貌出现,从而使系统不依赖于接口实现的细节

三、观察者模式

下面我们来看下定义吧:
1. 概述

  有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

  1. 解决的问题

      将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。

  2. 模式中的角色

      3.1 抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

      3.2 具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。

      3.3 抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

      3.4 具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
    4.观察者模式结构:
    常用的Java设计模式(一)_第3张图片
    5.准备阶段
    常用的Java设计模式(一)_第4张图片
    6.运行阶段
    常用的Java设计模式(一)_第5张图片
    下面我们就用一个例子来看下吧:

Observer类 ——–> Observer

package WeatherObserverPattern;
/** * 观察者接口,定义一个更新的接口给那些目标发生改变的时候 * 被通知的对象 * @author ruolan * */
public interface Observer {

    //观察者进行更新的接口
    //传入目标对象,方便获取相应的目标对象
    public void update(WeatherSubject subject);
}

ConCreateObserver类 ——–>ConreateObserver

package WeatherObserverPattern;

/** * 具体的观察者对象,实现更新的方法, 使自身的状态和目标的状态保持一致 * * @author ruolan * @param <ConcreteSubject> * */
public class ConreateObserver implements Observer {

    //观察的名字,是谁收到了信息,黄明的女票还是老妈
    private String obserberName;

    //天气的内容的情况,这个消息从目标出获取
    private String weatherContent;
    //提醒的内容:黄明的女票提醒约会,黄明的老妈提醒购物
    private String remindThing;



    public String getObserberName() {
        return obserberName;
    }

    public void setObserberName(String obserberName) {
        this.obserberName = obserberName;
    }

    public String getWeatherContent() {
        return weatherContent;
    }

    public void setWeatherContent(String weatherContent) {
        this.weatherContent = weatherContent;
    }

    public String getRemindThing() {
        return remindThing;
    }

    public void setRemindThing(String remindThing) {
        this.remindThing = remindThing;
    }

    // 观察者状态
    private String weatherState;

    /** * 获取目标类的状态,同步到观察者的状态中 */
    @Override
    public void update(WeatherSubject subject) {
        //获取天气内容
        weatherState = ((WeatherConcreteSubject) subject).getWeatherState();
        System.out.println(obserberName + "收到了" + weatherState + "," + remindThing);
    }

    /** * 所需变量 : 1、观察者的名字 2、天气情况的内容 3、提醒的内容 */

}

Subject类 ——–>WeatherSubject

package WeatherObserverPattern;

import java.util.ArrayList;
import java.util.List;

/** * 目标对象,他知道观察他的观察者额 并提供注册添加和删除观察者的接口 * * @author ruolan */
public class WeatherSubject {

    // 用一个集合来保存注册的观察者对象
    private List<Observer> observers = new ArrayList<>();

    // 把观察者添加集合
    public void attach(Observer observer) {
        observers.add(observer);
    }

    //删除集合中的指定订阅天气的
    public void detach(Observer observer){
        observers.remove(observer);
    }

    //通知所有已经订阅了天气的人,只能子类调用
    protected void notifyObservers(){
        for (Observer observer : observers) {
            observer.update(this);
        }
    }
}

ConcreteSubject类 ——> WeatherConcreteSubject

package WeatherObserverPattern;
/** * 具体的目标对象,负责把有关状态存入到相应的观察者对象中 * @author ruolan * */

public class WeatherConcreteSubject extends WeatherSubject {

    private String weatherState;

    public String getWeatherState() {
        return weatherState;
    }

    public void setWeatherState(String subjectState) {
        this.weatherState = subjectState;
        this.notifyObservers();//状态发生改变就通知观察者
    }


}

Client类

package WeatherObserverPattern;

public class Client {

    public static void main(String[] args) {
        //1、创建一个目标
        WeatherConcreteSubject weather = new WeatherConcreteSubject();

        //2、创建观察者
        ConreateObserver observerGirl = new ConreateObserver();
        observerGirl.setObserberName("黄明的女票");
        observerGirl.setRemindThing("是我们的第一次约会,地点是天桥,不见不散");
        ConreateObserver observerMum = new ConreateObserver();
        observerMum.setObserberName("黄明的妈妈");
        observerMum.setRemindThing("是一个购物的好日子,明天去购物去吧");
        //3、注册观察者
        weather.attach(observerGirl);
        weather.attach(observerMum);
        //4、目标发布天气
        weather.setWeatherState("明天天气晴朗,蓝天白云,气温28度");

    }

}

运行结果:

黄明的女票收到了明天天气晴朗,蓝天白云,气温28度,是我们的第一次约会,地点是天桥,不见不散
黄明的妈妈收到了明天天气晴朗,蓝天白云,气温28度,是一个购物的好日子,明天去购物去吧

在这里感谢一下慕课网的老师哈,今天就到这了,明天继续。。。。。。

你可能感兴趣的:(java设计模式)