diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7b016a8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.compile.nullAnalysis.mode": "automatic" +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..61de0ed --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +测试 \ No newline at end of file diff --git a/demo/src/main/java/com/louzin/java23/adapter/Adapter.java b/demo/src/main/java/com/louzin/java23/adapter/Adapter.java new file mode 100644 index 0000000..06b49e6 --- /dev/null +++ b/demo/src/main/java/com/louzin/java23/adapter/Adapter.java @@ -0,0 +1,10 @@ +package com.louzin.java23.adapter; + +public class Adapter extends Source implements Targetable { + + @Override + public void method2() { + System.out.println("Targetable Method"); + } + +} diff --git a/demo/src/main/java/com/louzin/java23/adapter/AdapterTester.java b/demo/src/main/java/com/louzin/java23/adapter/AdapterTester.java new file mode 100644 index 0000000..7211ccb --- /dev/null +++ b/demo/src/main/java/com/louzin/java23/adapter/AdapterTester.java @@ -0,0 +1,19 @@ +package com.louzin.java23.adapter; + +public class AdapterTester { + public static void main(String[] args) { + // Source source=new Source(); + // Wrapper wrapper=new Wrapper(source); + // // Targetable targetable=new Adapter(); + // // targetable.method1(); + // // targetable.method2(); + // wrapper.method1(); + // wrapper.method2(); + Sourceable source1 = new SourceSub1(); + Sourceable source2 = new SourceSub2(); + source1.method1(); + source1.method2(); + source2.method1(); + source2.method2(); + } +} diff --git a/demo/src/main/java/com/louzin/java23/adapter/Source.java b/demo/src/main/java/com/louzin/java23/adapter/Source.java new file mode 100644 index 0000000..458aca1 --- /dev/null +++ b/demo/src/main/java/com/louzin/java23/adapter/Source.java @@ -0,0 +1,7 @@ +package com.louzin.java23.adapter; + +public class Source { + public void method1() { + System.out.println("Original Method"); + } +} diff --git a/demo/src/main/java/com/louzin/java23/adapter/SourceSub1.java b/demo/src/main/java/com/louzin/java23/adapter/SourceSub1.java new file mode 100644 index 0000000..ed58500 --- /dev/null +++ b/demo/src/main/java/com/louzin/java23/adapter/SourceSub1.java @@ -0,0 +1,7 @@ +package com.louzin.java23.adapter; + +public class SourceSub1 extends Wrapper2{ + public void method1(){ + System.out.println("Method1"); + } +} diff --git a/demo/src/main/java/com/louzin/java23/adapter/SourceSub2.java b/demo/src/main/java/com/louzin/java23/adapter/SourceSub2.java new file mode 100644 index 0000000..d3efeb3 --- /dev/null +++ b/demo/src/main/java/com/louzin/java23/adapter/SourceSub2.java @@ -0,0 +1,7 @@ +package com.louzin.java23.adapter; + +public class SourceSub2 extends Wrapper2{ + public void method2(){ + System.out.println("Method2"); + } +} diff --git a/demo/src/main/java/com/louzin/java23/adapter/Sourceable.java b/demo/src/main/java/com/louzin/java23/adapter/Sourceable.java new file mode 100644 index 0000000..f564d2d --- /dev/null +++ b/demo/src/main/java/com/louzin/java23/adapter/Sourceable.java @@ -0,0 +1,6 @@ +package com.louzin.java23.adapter; + +public interface Sourceable { + public void method1(); + public void method2(); +} diff --git a/demo/src/main/java/com/louzin/java23/adapter/Targetable.java b/demo/src/main/java/com/louzin/java23/adapter/Targetable.java new file mode 100644 index 0000000..66afd2e --- /dev/null +++ b/demo/src/main/java/com/louzin/java23/adapter/Targetable.java @@ -0,0 +1,8 @@ +package com.louzin.java23.adapter; + +public interface Targetable { + //与Source类中的方法相同 + public void method1(); + //新类的方法 + public void method2(); +} diff --git a/demo/src/main/java/com/louzin/java23/adapter/Wrapper.java b/demo/src/main/java/com/louzin/java23/adapter/Wrapper.java new file mode 100644 index 0000000..fba5a71 --- /dev/null +++ b/demo/src/main/java/com/louzin/java23/adapter/Wrapper.java @@ -0,0 +1,21 @@ +package com.louzin.java23.adapter; + +public 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("Targetable Method!"); + } + +} diff --git a/demo/src/main/java/com/louzin/java23/adapter/Wrapper2.java b/demo/src/main/java/com/louzin/java23/adapter/Wrapper2.java new file mode 100644 index 0000000..2034832 --- /dev/null +++ b/demo/src/main/java/com/louzin/java23/adapter/Wrapper2.java @@ -0,0 +1,6 @@ +package com.louzin.java23.adapter; + +public abstract class Wrapper2 implements Sourceable{ + public void method1(){} + public void method2(){} +} diff --git a/demo/src/main/java/com/louzin/java23/builder/Builder.java b/demo/src/main/java/com/louzin/java23/builder/Builder.java new file mode 100644 index 0000000..4a4ea13 --- /dev/null +++ b/demo/src/main/java/com/louzin/java23/builder/Builder.java @@ -0,0 +1,19 @@ +package com.louzin.java23.builder; + +import java.util.ArrayList; +import java.util.List; + +public class Builder { + private List list = new ArrayList(); + public void produceMailSender(int count){ + for(int i=0; i +# 设计模式的分类 +分为三大类: +- 创造型模式(五种) +> 工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式 +- 结构型模式(七种) +> 适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式 +- 行为型模式(十一种) +> 策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式 + +补充:并发型模式,线程池模式 +## 1、工厂方法模式(Factory Method) +工厂方法模式分为三种 +### 1.1普通工厂方法模式 +建立一个工厂类,对实现了同一接口的一些类进行实例的创建: +```java +//共同接口 +public interface Sender { + public void Send(); +} +``` +```java +public class CommonFactoryMailSender implements Sender{ + + @Override + public void Send() { + System.out.println("This is MailSender!"); + } + +} +``` +```java +public class CommonFactorySmsSender implements Sender{ + + @Override + public void Send() { + System.out.println("This is Sms Sender!"); + } + +} +``` +建立工厂类: +```java +public class CommonFactorySendFactory { + public Sender producSender(String type){ + if("mail".equals(type)){ + return new CommonFactoryMailSender(); + }else if("sms".equals(type)){ + return new CommonFactorySmsSender(); + }else{ + System.out.println("类型错误!"); + return null; + } + } +} +``` +进行使用: +```java +public void testName() { + CommonFactorySendFactory factorySendFactory= new CommonFactorySendFactory(); + Sender sender=factorySendFactory.producSender("mail"); + sender.Send(); + }; + } +``` +### 1.2多个工厂方法模式 +对普通工厂方法模式进行改进,提供多个工厂方法模式,分别创建对象 +```java +public class MultipleFactorySendFactory { + public CommonFactoryMailSender produceSenderMail(){ + return new CommonFactoryMailSender(); + } + public CommonFactorySmsSender produceSenderSms(){ + return new CommonFactorySmsSender(); + } +} +``` +测试如下: +```java + public void test2(){ + MultipleFactorySendFactory factorySendFactory=new MultipleFactorySendFactory(); + Sender sender=factorySendFactory.produceSenderMail(); + sender.Send(); + } +``` +### 1.3静态工厂方法模式 +将多个工厂方法模式中的方法设置为静态,不需要创建实例,可以直接调用 +```java +public class StaticFactorySendFactory { + public static CommonFactoryMailSender procduceSenderMail(){ + return new CommonFactoryMailSender(); + } + public static CommonFactorySmsSender procduceSenderSms(){ + return new CommonFactorySmsSender(); + } +} +``` +测试如下: +```java +public void test3() { + Sender sender=StaticFactorySendFactory.procduceSenderSms(); + sender.Send(); +} +``` +### 1.4总结 +工厂方法模式适合大量需要创建,且具有共同的接口时,可以通过工厂方法模式进行创建 +对于以上三种,第一种通过字符串判断来创建对应的对象,第三种相对于第二种不需要实例化工厂类,一般情况下使用静态工厂方法模式 +## 2、抽象工厂模式(Abstract Factory) +工厂方法模式存在的问题是:类的创建依赖工厂类,如果想要扩展程序,就需要对工厂类进行修改,此时违背了闭包原则。从设计的角度,使用抽象工厂模式创建多个类,若需要新增功能直接增加新的工厂即可,同时无需修改之前的代码 +```java +public interface Sender { + public void Send(); +} +``` +继承并实现方法: +```java +//SmsSender +public class SmsSender implements Sender { + + @Override + public void Send() { + System.out.println("SmsSender!"); + } + +} +``` +```java +//MailSender +public class MailSender implements Sender { + + @Override + public void Send() { + System.out.println("MailSender!"); + } + +} +``` +实现共同接口: +```java +public interface Sender { + public void Send(); +} +``` +实现两个工厂类: +```java +public class SendSmsFactory implements Provider{ + + @Override + public Sender produce() { + return new SmsSender(); + } + +} +``` +```java +public class SendMailFactory implements Provider{ + + @Override + public Sender produce(){ + return new MailSender(); + } + +} +``` +测试如下: +```java +public void name() { + Provider provider=new SendMailFactory(); + com.louzin.java23.abstractfactory.Sender sender=provider.produce(); + sender.Send(); +} +``` +### 2.1总结 +若想添加一个新的功能,只需要做一个实现类实现Sender接口,同时创建一个工厂类实现Provider接口,无需改动现成的代码,扩展性较好 +## 3、单例模式(Singleton) +单例对象(Singleton)是一种常见的设计模式。在Java的应用中,能保证在一个JVM中只存在一个该对象的实例,这样的好处是: +- 限制某些繁琐类的建立,这类大型对象的创建是一笔很大的开销 +- 无需重复new,降低了系统内存的使用频率,减轻GC压力 +- 保证程序的核心流程只能创建一个 + +```java +public class SingletonDemo1 { + /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */ + private static SingletonDemo1 instance = null; + + /* 私有构造方法,防止被实例化 */ + private SingletonDemo1() { + } + + /* 静态工程方法,创建实例 */ + public static SingletonDemo1 getInstance() { + if (instance == null) { + instance = new SingletonDemo1(); + } + return instance; + } + + /* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */ + public Object readResolve() { + return instance; + } +} +``` +这个类可以满足单例的基本要求,但是若将其置于多线程环境,将会出现问题,我们会对`getInstance`方法加`synchronized`关键字: +~~~java +public static synchronized SingletonDemo1 getInstance() { + if (instance == null) { + instance = new SingletonDemo1(); + } + return instance; + } +~~~ +但是`synchronized`锁住的是这个对象,每次调用的时候都要加锁,非常影响性能。实际上,只有第一次创建的时候才需加锁,之后就不需要了: +```java +public static SingletonDemo1 getInstance() { + if (instance == null) { + synchronized (instance) { + if (instance == null) { + instance = new SingletonDemo1(); + } + } + } + return instance; +} +``` + +这种方式很好理解,将加锁放在了内部,在调用的时候并不会加锁,只有在创建的时候才会加锁、 +**但是这种情况还是可能会出现问题**: +> 在Java指令中,**创建对象**和**赋值操作**是分开进行的,也就是说`instance = new SingletonDemo1()`是分开进行的,但是`JVM`并不能保证这两个操作的先后顺序,也就可能会出现JVM先为新的`SingletonDemo1`实例分配空间,然后直接赋值给`instance`,在此之后才进行初始化`SingletonDemo1`实例,此时便会出错 + +以下为例: +- A,B两个线程同时调用了这个类 +- A先判断完,进入`synchronized`块执行了`instance = new SingletonDemo1()` +- JVM内部优化机制,先分配了空白内存,并完成赋值,此时还未初始化这个实例 +- B判断`instance`不是`null`后离开了`synchronized`块,并将结果返回给调用方法 +- 调用方法抛出异常 + +解决方式如下: +```java +/* 此处使用一个内部类来维护单例 */ +private static class SingletonDemo1Factory { + private static SingletonDemo1 instance = new Singleton(); +} +/* 获取实例 */ +public static SingletonDemo1 getInstance() { + return SingletonDemo1.instance; +} +``` +单例模式使用内部类来维护单例的实现,`JVM`内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的,当我们第一次调用`getInstance`的时候,`JVM`能帮我们保证只会创建一次,并会把赋值给`instance`的内存初始化完成,以保证正常运行 + +**但是**如果在构造函数中抛出异常,实例将永远不会创建,也会造成出错,我们只能根据实际情况,选择最合适的应用场景 + +补充(分离创建和获取): +```java +public class SingletonTest { + private static SingletonTest instance = null; + //阻止实例化 + private SingletonTest() { + } + //分离创建和获取 + private static synchronized void syncInit() { + if (instance == null) { + instance = new SingletonTest(); + } + } + //获取对象 + public static SingletonTest getInstance() { + if (instance == null) { + syncInit(); + } + return instance; + } + //序列化一致性保证 + public Object readResolve() { + return instance; + } +} +``` +### 3.1影子实例 +采用"影子实例"的方法为单例对象的属性同步更新 +```java +public class SingletonTest { + + private static SingletonTest instance = null; + private Vector properties = null; + + public Vector getProperties() { + return properties; + } + + private SingletonTest() { + } + + private static synchronized void syncInit() { + if (instance == null) { + instance = new SingletonTest(); + } + } + + public static SingletonTest getInstance() { + if (instance == null) { + syncInit(); + } + return instance; + } + + public void updateProperties() { + SingletonTest shadow = new SingletonTest(); + properties = shadow.getProperties(); + } +} +``` 4、建造者模式(Builder) +工厂类模式服务于单个类,而建造者模式将各个类集中起来管理,用来创建复合对象,实际上就是抽象工厂类和`Test`的结合: +`Sender`接口,两个实现类`MailSender`和`SmsSender` \ No newline at end of file