louzin
2 years ago
25 changed files with 539 additions and 0 deletions
@ -0,0 +1,3 @@ |
|||||||
|
{ |
||||||
|
"java.compile.nullAnalysis.mode": "automatic" |
||||||
|
} |
@ -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"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
package com.louzin.java23.adapter; |
||||||
|
|
||||||
|
public class Source { |
||||||
|
public void method1() { |
||||||
|
System.out.println("Original Method"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
package com.louzin.java23.adapter; |
||||||
|
|
||||||
|
public class SourceSub1 extends Wrapper2{ |
||||||
|
public void method1(){ |
||||||
|
System.out.println("Method1"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
package com.louzin.java23.adapter; |
||||||
|
|
||||||
|
public class SourceSub2 extends Wrapper2{ |
||||||
|
public void method2(){ |
||||||
|
System.out.println("Method2"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
package com.louzin.java23.adapter; |
||||||
|
|
||||||
|
public interface Sourceable { |
||||||
|
public void method1(); |
||||||
|
public void method2(); |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
package com.louzin.java23.adapter; |
||||||
|
|
||||||
|
public interface Targetable { |
||||||
|
//与Source类中的方法相同
|
||||||
|
public void method1(); |
||||||
|
//新类的方法
|
||||||
|
public void method2(); |
||||||
|
} |
@ -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!"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
package com.louzin.java23.adapter; |
||||||
|
|
||||||
|
public abstract class Wrapper2 implements Sourceable{ |
||||||
|
public void method1(){} |
||||||
|
public void method2(){} |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package com.louzin.java23.builder; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class Builder { |
||||||
|
private List<Sender> list = new ArrayList<Sender>(); |
||||||
|
public void produceMailSender(int count){ |
||||||
|
for(int i=0; i<count; i++){ |
||||||
|
list.add(new MailSender()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void produceSmsSender(int count){ |
||||||
|
for(int i=0; i<count; i++){ |
||||||
|
list.add(new SmsSender()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
package com.louzin.java23.builder; |
||||||
|
|
||||||
|
public class BuilderTest { |
||||||
|
public static void main(String[] args) { |
||||||
|
Builder builder = new Builder(); |
||||||
|
builder.produceMailSender(10); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
package com.louzin.java23.builder; |
||||||
|
|
||||||
|
public class MailSender implements Sender{ |
||||||
|
@Override |
||||||
|
public void Send(){ |
||||||
|
System.out.println("MailSender!"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
package com.louzin.java23.builder; |
||||||
|
|
||||||
|
public interface Sender { |
||||||
|
public void Send(); |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
package com.louzin.java23.builder; |
||||||
|
|
||||||
|
public class SmsSender implements Sender{ |
||||||
|
@Override |
||||||
|
public void Send(){ |
||||||
|
System.out.println("SmsSender!"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package com.louzin.java23.decorator; |
||||||
|
|
||||||
|
public class Decorator implements Sourceable{ |
||||||
|
private Sourceable sourceable; |
||||||
|
public Decorator(Sourceable sourceable) { |
||||||
|
super(); |
||||||
|
this.sourceable = sourceable; |
||||||
|
} |
||||||
|
@Override |
||||||
|
public void method() { |
||||||
|
System.out.println("before Decorator"); |
||||||
|
sourceable.method(); |
||||||
|
System.out.println("after Decorator"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
package com.louzin.java23.decorator; |
||||||
|
|
||||||
|
public class DecoratorTest { |
||||||
|
public static void main(String[] args) { |
||||||
|
Sourceable sourceable=new Source(); |
||||||
|
Sourceable objDecorator=new Decorator(sourceable); |
||||||
|
objDecorator.method(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
package com.louzin.java23.decorator; |
||||||
|
|
||||||
|
public class Source implements Sourceable{ |
||||||
|
@Override |
||||||
|
public void method() { |
||||||
|
System.out.println("Original Method"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
package com.louzin.java23.decorator; |
||||||
|
|
||||||
|
public interface Sourceable { |
||||||
|
public void method(); |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package com.louzin.java23.proxy; |
||||||
|
|
||||||
|
public class Proxy implements Sourceable{ |
||||||
|
private Source source; |
||||||
|
public Proxy() { |
||||||
|
super(); |
||||||
|
this.source = new Source(); |
||||||
|
} |
||||||
|
@Override |
||||||
|
public void method() { |
||||||
|
before(); |
||||||
|
source.method(); |
||||||
|
after(); |
||||||
|
} |
||||||
|
private void after(){ |
||||||
|
System.out.println("after"); |
||||||
|
} |
||||||
|
private void before(){ |
||||||
|
System.out.println("before"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
package com.louzin.java23.proxy; |
||||||
|
|
||||||
|
public class ProxyTester { |
||||||
|
public static void main(String[] args) { |
||||||
|
Sourceable sourceable=new Proxy(); |
||||||
|
sourceable.method(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
package com.louzin.java23.proxy; |
||||||
|
|
||||||
|
public class Source implements Sourceable{ |
||||||
|
@Override |
||||||
|
public void method() { |
||||||
|
System.out.println("Original Method"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
package com.louzin.java23.proxy; |
||||||
|
|
||||||
|
public interface Sourceable { |
||||||
|
public void method(); |
||||||
|
} |
@ -0,0 +1,317 @@ |
|||||||
|
[JAVA]23种设计模式:工厂方法模式,抽象工厂模式,单例模式Ⅰ |
||||||
|
|
||||||
|
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。 |
||||||
|
<!-- more --> |
||||||
|
# 设计模式的分类 |
||||||
|
分为三大类: |
||||||
|
- 创造型模式(五种) |
||||||
|
> 工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式 |
||||||
|
- 结构型模式(七种) |
||||||
|
> 适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式 |
||||||
|
- 行为型模式(十一种) |
||||||
|
> 策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式 |
||||||
|
|
||||||
|
补充:并发型模式,线程池模式 |
||||||
|
## 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` |
Loading…
Reference in new issue