可看c语言中文网介绍
C语言中文网 Java设计模式
单例模式
懒汉式
/**
* 懒汉式,单例模式
* 不足:
* 在多线程环境中存在多个对象,线程不安全
*/
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton(){
}
public static LazySingleton getInstance(){
if (instance==null){
instance = new LazySingleton();
}
return instance;
}
}
饿汉式
/**
* 饿汉式,单例模式,线程安全
* 不足:
* 类加载时就创建对象,该类不管是否使用都存在一个对象
* 创建对象无法传递参数
*/
public class HungrySingleton {
private static HungrySingleton instance;
/**
* 静态代码块在类加载期间初始化,只执行一次
*/
static {
try {
instance = new HungrySingleton();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 防止通过反射创建对象
*/
private HungrySingleton() throws Exception {
if (instance!=null){
throw new Exception("该类只能有一个实例");
}
}
public static HungrySingleton getInstance(){
return instance;
}
}
双重校验
/**
* 双重校验:单例模式,线程安全
* 不足:
* 在第一次创建对象时需要同步
*/
public class DCLSingleton {
private volatile static DCLSingleton instance;
private DCLSingleton(){
}
public static DCLSingleton getInstance(){
if (instance == null){
synchronized (DCLSingleton.class){
if (instance == null){
instance = new DCLSingleton();
}
}
}
return instance;
}
}
静态内部类
/**
* 静态内部类,单例模式,线程安全,解决饿汉式中无论如何都存在一个对象的问题
*/
public class StaticInnerSingleton {
private StaticInnerSingleton(){
}
public static StaticInnerSingleton getInstance(){
return InnerClass.instance;
}
/**
* 静态内部类
*/
private static class InnerClass{
private static final StaticInnerSingleton instance = new StaticInnerSingleton();
}
}
枚举
/**
* 枚举,单例模式,线程安全,防止反射,序列化,克隆
*/
public enum EnumSingleton {
INSTANCE;
}
单例模式测试类
public static void main(String[] args) {
//懒汉式
/*
Singleton singleton = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
System.out.println(singleton == singleton2);
*/
/*
for (int i =0;i<10;i++){
new Thread(new Runnable() {
@Override
public void run() {
for (int j=0;j<10;j++){
System.out.println(LazySingleton.getInstance());
}
}
}).start();
}
*/
//饿汉式
/*
for (int i =0;i<10;i++){
new Thread(new Runnable() {
@Override
public void run() {
for (int j=0;j<10;j++){
System.out.println(HungrySingleton.getInstance());
}
}
}).start();
}
*/
//双重校验
/*
for (int i =0;i<10;i++){
new Thread(new Runnable() {
@Override
public void run() {
for (int j=0;j<10;j++){
System.out.println(DCLSingleton.getInstance());
}
}
}).start();
}
*/
//静态内部类
/*
for (int i =0;i<10;i++){
new Thread(new Runnable() {
@Override
public void run() {
for (int j=0;j<10;j++){
System.out.println(StaticInnerSingleton.getInstance());
}
}
}).start();
}
*/
//枚举
for (int i =0;i<10;i++){
new Thread(new Runnable() {
@Override
public void run() {
for (int j=0;j<10;j++){
System.out.println(EnumSingleton.INSTANCE);
}
}
}).start();
}
}
反射测试类
用来证明简单单例模式无法做到线程安全(枚举可以做到)
在例子饿汉式中,对构造方法进行添加语句,做判断对象,抛出异常操作,做到反射无法创建新的对象,达到线程安全
public static void main(String[] args) throws Exception {
HungrySingleton instance = HungrySingleton.getInstance();
Class<HungrySingleton> cls = HungrySingleton.class;
//获取类中的所有构造方法
Constructor<HungrySingleton> constructor = cls.getDeclaredConstructor();
//设置私有构造方法可访问
constructor.setAccessible(true);
//使用反射实例化对象
HungrySingleton instance2 = constructor.newInstance();
System.out.println(instance2);
System.out.println(instance == instance2);
}
工厂模式
简单工厂
/**
* 电器工厂,简单工厂类
*/
public class ApplianceFactory {
/**
* 生产电器
* @param type
* @return
*/
public static Appliance makeAppliance(String type){
switch (type){
case "电视机":
return new Tv();
case "冰箱":
return new IceBox();
}
return null;
}
}
工厂方法
抽象工厂
代理模式
静态代理
/**
* 抽象主题:房东接口
*/
public interface HouseOwner {
/**
* 出租房屋
*/
public void rent();
/**
* 收租
*/
public void getMoney();
/**
* 具体主题:民房,城中村房东类
* 目标对象
*/
public class VillageHouseOwner implements HouseOwner{
@Override
public void rent() {
System.out.println("有床、独立卫生间、热水器、单间:500/月、押一付一");
}
@Override
public void getMoney() {
System.out.println("收取每月月租、水电费、生活垃圾费");
}
/**
* 代理类,房东代理类
* 代理目标类
*
* 缺点:跟目标对象一样实现了抽象业务的接口,一旦抽象业务接口发送改变也必须跟着改变,可以使用动态代理(反射机制)解决
*/
public class HouseOwnerProxy implements HouseOwner{
/**
* 代理类中定义目标对象类中的属性
*/
private HouseOwner houseOwner;
public HouseOwnerProxy(){
}
public HouseOwnerProxy(HouseOwner houseOwner){
this.houseOwner = houseOwner;
}
@Override
public void rent() {
houseOwner.rent();
getProxyFee();
}
@Override
public void getMoney() {
houseOwner.getMoney();
procedureFee();
}
public void getProxyFee(){
System.out.println("收取半个月的房租费当做中介费,只收取一次");
}
public void procedureFee(){
System.out.println("每月收取固定手续费50元");
}
/**
* 访问
*/
public class Test {
public static void main(String[] args) {
//租客直接找到房东租房,把房租交给房东
VillageHouseOwner villageHouseOwner = new VillageHouseOwner();
villageHouseOwner.rent();
villageHouseOwner.getMoney();
//创建一个代理类对象,构造方法中传入目标对象(被代理的对象)
HouseOwnerProxy proxy = new HouseOwnerProxy(new VillageHouseOwner());
//使用代理类租房子和收取租金
proxy.rent();
proxy.getMoney();
}
}
动态代理
/**
* 抽象主题:房东接口
*/
public interface HouseOwner {
/**
* 出租房屋
*/
public void rent();
/**
* 收租
*/
public void getMoney();
/**
* 房子日常保养维护
*/
public void maintain();
}
/**
* 具体主题:民房,城中村房东类
* 目标对象
*/
public class VillageHouseOwner implements HouseOwner {
@Override
public void rent() {
System.out.println("有床、独立卫生间、热水器、单间:500/月、押一付一");
}
@Override
public void getMoney() {
System.out.println("收取每月月租、水电费、生活垃圾费");
}
@Override
public void maintain() {
System.out.println("房子日常维护,家电日常维修");
}
}
/**
* jdk动态代理类,用来代理目标业务对象,目标对象必须实现接口
*/
public class JDKProxy implements InvocationHandler {
/**
* 要代理的目标对象
*/
private Object targetObject;
public JDKProxy(){
}
public JDKProxy(Object targetObject){
this.targetObject = targetObject;
}
/**
* 传入目标对象,使用反射机制动态创建代理对象
* @param targetObject
* @return
*/
public Object creatProxy(Object targetObject){
this.targetObject = targetObject;
return Proxy.newProxyInstance(
targetObject.getClass().getClassLoader(),//目标对象类加载器
targetObject.getClass().getInterfaces(),//目标对象实现的接口
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//使用反射动态调用目标对象的方法
Object invoke = method.invoke(this.targetObject, args);
if (method.getName().equals("rent")){//判断当前执行的方法是否是rent方法
getProxyFee();
}
if (method.getName().equals("getMoney")){
procedureFee();
}
return invoke;
}
public void getProxyFee(){
System.out.println("收取半个月的房租费当做中介费,只收取一次");
}
public void procedureFee(){
System.out.println("每月收取固定手续费50元");
}
}
public class Test {
public static void main(String[] args) {
JDKProxy proxy = new JDKProxy();
//创建代理对象
HouseOwner proxyHouseOwner = (HouseOwner)proxy.creatProxy(new VillageHouseOwner());
proxyHouseOwner.rent();
proxyHouseOwner.getMoney();
proxyHouseOwner.maintain();
}
}
观察者模式
/**
* 抽象观察者,粉丝接口
*/
public interface Fans {
/**
* 接收消息的方法,接收主题发送过来的消息
* @param msg
*/
public void notify(String msg);
}
/**
* 抽象主题:明星类
*/
public abstract class Star {
/**
* 创建一个集合,存放当前抽象主题所有的观察者粉丝对象
*/
protected List<Fans> list = new ArrayList<>();
/**
* 新增观察者对象,粉丝
* @param fans
*/
public synchronized void addFans(Fans fans){
if (!list.contains(fans)){
list.add(fans);
}
}
/**
* 移除观察者对象,粉丝
* @param fans
*/
public synchronized void removeFans(Fans fans){
if (list.contains(fans)){
list.remove(fans);
}
}
/**
* 通知所有的观察者
*/
public abstract void notifyFans(String msg);
}
/**
* 具体的观察者:电影粉丝
*/
public class MovieFans implements Fans{
private String name;
public MovieFans(){
}
public MovieFans(String name){
this.name = name;
}
@Override
public void notify(String msg) {
System.out.println(name+msg);
}
}
/**
* 具体主题
*/
public class MovieStar extends Star{
@Override
public void notifyFans(String msg) {
if (!list.isEmpty()){
list.forEach(fans ->fans.notify(msg));
}
}
}
/**
* 具体观察者:音乐粉丝
*/
public class MusicFans implements Fans{
@Override
public void notify(String msg) {
System.out.println(msg);
}
}
/**
*具体主题:音乐明星
*/
public class MusicStar extends Star{
@Override
public void notifyFans(String msg) {
if (!list.isEmpty()){
list.forEach(fans -> fans.notify(msg));
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
//创建一个电影明星
MovieStar movieStar = new MovieStar();
//创建两个电影粉丝
MovieFans movieFans1 = new MovieFans("张三");
MovieFans movieFans2 = new MovieFans("李四");
//两粉丝关注明星
movieStar.addFans(movieFans1);
movieStar.addFans(movieFans2);
movieStar.notifyFans("电影即将上映!");
//取消关注
movieStar.removeFans(movieFans1);
movieStar.notifyFans("感谢粉丝支持!");
}
}