面向对象的设计模式
1.单例模式
Ensure a class has only one instance,and provide global point of access to it.
特点:
1.减少资源占用,提高系统性能
2.扩展困难、不易测试
使用场景:
1.要求生成唯一序列号的环境(分表)
2.共享访问点或共享数据
3.创建一个对象消耗资源过多(IO,数据库)
4.存在大量静态常量和静态方法的环境(工具类)
单例模式类型:
1.饿汉模式
2.懒汉模式
3.线程安全
4.enum实现
5.工厂方法实现
6.有上限的多例模式
1 import java.lang.reflect.Constructor;
2 import java.util.ArrayList;
3 import java.util.List;
4 import java.util.Random;
5
6 /** 单例模式 */
7 public class SingleInstanceTest {
8 private static final int LOOP_TIMES = 3;
9 public static void main(String[] args){
10 int cnt;
11 //饿汉模式
12 cnt = LOOP_TIMES;
13 while(cnt-- > 0){
14 HungryMan hungryMan = HungryMan.getInstance();
15 System.out.print( (LOOP_TIMES - cnt) + ":");
16 hungryMan.info();
17 }
18
19 //懒汉模式
20 cnt = LOOP_TIMES;
21 while(cnt-- > 0){
22 LazyMan lazyMan = LazyMan.getInstance();
23 System.out.print( (LOOP_TIMES - cnt) + ":");
24 lazyMan.info();
25 }
26
27 //懒汉线程安全模式
28 cnt = LOOP_TIMES;
29 while(cnt-- > 0){
30 LazyManThreadSafe lazyManThreadSafe = LazyManThreadSafe.getInstance();
31 System.out.print( (LOOP_TIMES - cnt) + ":");
32 lazyManThreadSafe.info();
33 }
34
35 //懒汉枚举模式
36 cnt = LOOP_TIMES;
37 while(cnt-- >0){
38 LazyManEnum lazyManEnum = LazyManEnum.getInstance();
39 System.out.print( (LOOP_TIMES - cnt) + ":");
40 lazyManEnum.info();
41 }
42
43 //恶汉多例模式
44 cnt = LOOP_TIMES;
45 while(cnt-- > 0){
46 HungryManMany hungryManMany = HungryManMany.getInstance();
47 System.out.print( (LOOP_TIMES - cnt) + ":");
48 hungryManMany.info();
49 }
50 //工厂方法实现单例模式
51 cnt = LOOP_TIMES;
52 while(cnt-- > 0){
53 SingletonFactory factory = new SingletonFactory();
54 System.out.print( (LOOP_TIMES - cnt) + ":");
55 factory.info();
56 }
57 }
58 }
59
60 /** 饿汉模式-隐藏构造方法 */
61 class HungryMan{
62 private static final HungryMan hungryMan = new HungryMan();
63
64 /** 私有构造方法-只会执行一次 */
65 private HungryMan(){
66 System.out.println("饿汉模式");
67 }
68
69 /** 返回实例对象 */
70 public static HungryMan getInstance(){
71 return hungryMan;
72 }
73
74 public static void info(){
75 System.out.println(hungryMan.getClass().getName() + ":" + hungryMan.hashCode());
76 }
77 }
78
79 /** 饿汉模式-隐藏构造方法,延迟加载 */
80 class LazyMan{
81 private static LazyMan lazyMan = null;
82
83 /** 私有构造方法-只会执行一次 */
84 private LazyMan(){
85 System.out.println("懒汉模式");
86 }
87
88 /** 返回实例对象,延迟加载 */
89 public static LazyMan getInstance(){
90 if(lazyMan == null){lazyMan = new LazyMan();}
91 return lazyMan;
92 }
93
94 public static void info(){
95 System.out.println(lazyMan.getClass().getName() + ":" + lazyMan.hashCode());
96 }
97 }
98
99 /** 饿汉模式-隐藏构造方法,延迟加载,线程安全
100 * 被volatile修饰的变量
101 * 1. 每次被线程访问时,都强迫从共享内存中重读该变量的值
102 * 2. 当变量发生变化时,强迫线程将变化值回写到共享内存
103 * 3. volatile屏蔽掉了VM中必要的代码优化,效率较低
104 * */
105 class LazyManThreadSafe{
106 private static volatile LazyManThreadSafe lazyManThreadSafe = null;
107
108 /** 私有构造方法-只会执行一次 */
109 private LazyManThreadSafe(){
110 System.out.println("懒汉线程安全模式");
111 }
112
113 /** 返回实例对象,线程安全 */
114 public static LazyManThreadSafe getInstance(){
115 if(lazyManThreadSafe == null){//判断同步
116 synchronized(LazyManThreadSafe.class){
117 if(lazyManThreadSafe == null){//判断实例化对象
118 lazyManThreadSafe = new LazyManThreadSafe();
119 }
120 }
121 }
122 return lazyManThreadSafe;
123 }
124
125 public static void info(){
126 System.out.println(lazyManThreadSafe.getClass().getName() + ":" + lazyManThreadSafe.hashCode());
127 }
128 }
129
130 /**
131 * 懒汉模式枚举实现,并将类声明为抽象类,禁止实例化
132 * 优点:
133 * 1.线程安全
134 * 2.防止反射强行调用构造器
135 * 3.提供了自动序列化机制,防止反序列化的时候创建新的实例
136 */
137 abstract class LazyManEnum {
138 private static LazyManEnum lazyManEnum;
139
140 private LazyManEnum(){
141 System.out.println("懒汉Enum模式");
142 }
143
144 public static LazyManEnum getInstance(){
145 if(lazyManEnum == null){
146 lazyManEnum = Singleton.INSTANCE.getInstance();
147 }
148 return lazyManEnum;
149 }
150
151 public static void info(){
152 System.out.println(lazyManEnum.getClass().getName() + ":" + lazyManEnum.hashCode());
153 }
154
155 /** 类内子类 */
156 protected static class Child extends LazyManEnum{
157 public Child(){
158 System.out.println("Child...");
159 }
160 }
161
162 /** 类内枚举 */
163 private enum Singleton{
164 INSTANCE;
165 private final LazyManEnum singleton;
166
167 /** 构造方法,JVM会保证此方法绝对只调用一次*/
168 Singleton(){
169 singleton = new LazyManEnum.Child();
170 }
171
172 /** 返回实例 */
173 public LazyManEnum getInstance(){
174 return singleton;
175 }
176 }
177 }
178
179 /** 有上限的多例模式-懒汉模式 */
180 class HungryManMany{
181 private static final int MAX_NUM_OF_INSTANCE = 3;
182 private static final List<HungryManMany> hungryManList = new ArrayList<>();
183 private static HungryManMany hungryManMany;
184
185 /** 私有构造方法-只会执行一次 */
186 private HungryManMany(){
187 System.out.println("饿汉多例模式");
188 }
189
190 //静态初始化实例化对象列表
191 static {
192 int cnt = MAX_NUM_OF_INSTANCE;
193 while(cnt-- > 0){
194 hungryManList.add(new HungryManMany());
195 }
196 }
197
198 /** 随即返回一个实例对象 */
199 public static HungryManMany getInstance(){
200 Random random = new Random();
201 hungryManMany = hungryManList.get(random.nextInt(MAX_NUM_OF_INSTANCE));
202 return hungryManMany;
203 }
204
205 public static void info(){
206 System.out.println(hungryManMany.getClass().getName() + ":" + hungryManMany.hashCode());
207 }
208 }
209
210 /** 工厂方法实现单例模式 */
211 /** 单例类 */
212 class Singleton{
213 private Singleton(){};
214 }
215
216 /** 单例工厂 */
217 class SingletonFactory{
218 private static Singleton singleton;
219
220 static{
221 try{
222 Class cls = Class.forName(Singleton.class.getName());
223 //获取无参构造方法
224 Constructor constructor = cls.getDeclaredConstructor();
225 //设置构造方法可访问
226 constructor.setAccessible(true);
227 //生成实例
228 singleton = (Singleton)constructor.newInstance();
229 } catch(Exception e){
230 e.printStackTrace();
231 }
232 }
233
234 public Singleton getSingleton(){
235 return singleton;
236 }
237
238 public static void info(){
239 System.out.println(singleton.getClass().getName() + ":" + singleton.hashCode());
240 }
241 }
2.工厂模式
Define an instance for creating an object,but let subclasses to decide which class to instantiate.
Factory Method lets a class defer instantiation to subclasses.
特点:
1.良好的封装性、透明产品类实现细节
2.降低模块间的耦合度
3.易于扩展
4.应用法则:迪米特法则、依赖倒置原则、里氏替换原则
工厂模式类型:
1.工厂模式
2.简单工厂模式
3.多工厂模式
4.延迟加载(数据库连接)
1 import java.util.HashMap;
2 import java.util.Map;
3
4 /** 工厂模式 */
5 public class FactoryMode {
6 public static void main(String[] args) {
7 //工厂模式
8 System.out.println("工厂模式:");
9 AbstractNoodleFactory noodleFactory = NoodleFactory.getInstance();
10 //番茄鸡蛋面
11 INoodle tomatoNoodle = noodleFactory.createNoodle(TomatoNoodle.class);
12 tomatoNoodle.getMainMaterial();
13 //牛肉面
14 INoodle beefNoodle = noodleFactory.createNoodle(BeefNoodle.class);
15 beefNoodle.getMainMaterial();
16 //炸酱面
17 INoodle sauceNoodle = noodleFactory.createNoodle(SauceNoodle.class);
18 sauceNoodle.getMainMaterial();
19
20 //简单工厂模式
21 System.out.println("简单工厂模式:");
22 //番茄鸡蛋面
23 INoodle tomatoNoodle2 = NoodleSimpleFactory.createNoodle(TomatoNoodle.class);
24 tomatoNoodle2.getMainMaterial();
25 //牛肉面
26 INoodle beefNoodle2 = NoodleSimpleFactory.createNoodle(BeefNoodle.class);
27 beefNoodle2.getMainMaterial();
28 //炸酱面
29 INoodle sauceNoodle2 = NoodleSimpleFactory.createNoodle(SauceNoodle.class);
30 sauceNoodle2.getMainMaterial();
31
32 //多工厂模式
33 System.out.println("多工厂模式:");
34 //番茄鸡蛋面
35 INoodle tomatoNoodle3 = TomatoNoodleFactory.getInstance().createNoodle();
36 tomatoNoodle3.getMainMaterial();
37 //牛肉面
38 INoodle beefNoodle3 = BeefNoodleFactory.getInstance().createNoodle();
39 beefNoodle3.getMainMaterial();
40 //炸酱面
41 INoodle sauceNoodle3 = SauceNoodleFactory.getInstance().createNoodle();
42 sauceNoodle3.getMainMaterial();
43
44 //延迟加载
45 System.out.println("延迟加载");
46 //番茄鸡蛋面
47 INoodle tomatoNoodle4 = NoodleFactoryLazyLoad.createNoodle("tomatoNoodle");
48 tomatoNoodle4.getMainMaterial();
49 //牛肉面
50 INoodle beefNoodle4 = NoodleFactoryLazyLoad.createNoodle("beefNoodle");
51 beefNoodle4.getMainMaterial();
52 //炸酱面
53 INoodle sauceNoodle4 = NoodleFactoryLazyLoad.createNoodle("sauceNoodle");
54 sauceNoodle4.getMainMaterial();
55
56 }
57 }
58
59 /** 面条接口 */
60 interface INoodle{
61 //主要材料
62 void getMainMaterial();
63 }
64
65 /** 番茄鸡蛋面 */
66 class TomatoNoodle implements INoodle{
67 @Override
68 public void getMainMaterial() {
69 System.out.println(this.getClass() + ":Noodle + Tomato + Egg.");
70 }
71 }
72
73 /** 牛肉面 */
74 class BeefNoodle implements INoodle{
75 @Override
76 public void getMainMaterial() {
77 System.out.println(this.getClass() + ":Noodle + Beef.");
78 }
79 }
80
81 /** 炸酱面 */
82 class SauceNoodle implements INoodle{
83 @Override
84 public void getMainMaterial() {
85 System.out.println(this.getClass() + ":Noodle + Sauce.");
86 }
87 }
88
89 /** 抽象工厂 */
90 abstract class AbstractNoodleFactory{
91 public abstract <T extends INoodle> T createNoodle(Class<T> noodle);
92 }
93
94 /** 基本工厂模式 */
95 class NoodleFactory extends AbstractNoodleFactory{
96 private static final NoodleFactory noodleFactory = new NoodleFactory();
97
98 private NoodleFactory(){};
99
100 public static NoodleFactory getInstance(){
101 return noodleFactory;
102 }
103
104 @Override
105 public <T extends INoodle> T createNoodle(Class<T> noodleClass) {
106 INoodle noodle = null;
107 try{
108 noodle = (T)Class.forName(noodleClass.getName()).newInstance();
109 } catch (Exception e){
110 e.printStackTrace();
111 }
112 return (T)noodle;
113 }
114 }
115
116 /** 简单工厂:去掉继承类,创建方法变为static类型 */
117 class NoodleSimpleFactory{
118 private NoodleSimpleFactory(){};
119
120 public static <T extends INoodle> T createNoodle(Class<T> noodleClass) {
121 INoodle noodle = null;
122 try{
123 noodle = (T)Class.forName(noodleClass.getName()).newInstance();
124 } catch (Exception e){
125 e.printStackTrace();
126 }
127 return (T)noodle;
128 }
129 }
130
131 /** 多工厂模式:将原来的工厂分为更细化的工厂 */
132 /** 多工厂抽象类 */
133 abstract class NoodleMultiplyFactory{
134 public abstract INoodle createNoodle();
135 }
136
137 /** 番茄鸡蛋面工厂 */
138 class TomatoNoodleFactory extends NoodleMultiplyFactory{
139 private static final TomatoNoodleFactory noodleFactory = new TomatoNoodleFactory();
140
141 private TomatoNoodleFactory(){};
142
143 public static TomatoNoodleFactory getInstance(){
144 return noodleFactory;
145 }
146
147 @Override
148 public INoodle createNoodle() {
149 return new TomatoNoodle();
150 }
151 }
152
153 /** 牛肉面工厂 */
154 class BeefNoodleFactory extends NoodleMultiplyFactory{
155 private static final BeefNoodleFactory noodleFactory = new BeefNoodleFactory();
156
157 private BeefNoodleFactory(){};
158
159 public static BeefNoodleFactory getInstance(){
160 return noodleFactory;
161 }
162
163 @Override
164 public INoodle createNoodle() {
165 return new BeefNoodle();
166 }
167 }
168
169 /** 炸酱面工厂 */
170 class SauceNoodleFactory extends NoodleMultiplyFactory{
171 private static final SauceNoodleFactory noodleFactory = new SauceNoodleFactory();
172
173 private SauceNoodleFactory(){};
174
175 public static SauceNoodleFactory getInstance(){
176 return noodleFactory;
177 }
178
179 @Override
180 public INoodle createNoodle() {
181 return new SauceNoodle();
182 }
183 }
184
185 /** 延迟加载 */
186 /** 延迟加载工厂类:将产生的对象放进Map内进行缓存,可设置最大产生数量 */
187 class NoodleFactoryLazyLoad{
188 private final static Map<String,INoodle> noodleMap = new HashMap<>();
189
190 public static synchronized INoodle createNoodle(String type){
191 INoodle noodle = null;
192 if(noodleMap.containsKey(type)){
193 noodle = noodleMap.get(type);
194 } else{
195 try{
196 switch (type){
197 case "tomatoNoodle":
198 noodle = new TomatoNoodle();break;
199 case "beefNoodle":
200 noodle = new BeefNoodle();break;
201 case "sauceNoodle":
202 noodle = new SauceNoodle();break;
203 default:throw new Exception("This type is inexistent.");
204 }
205 } catch (Exception e){
206 e.printStackTrace();
207 }
208 }
209 noodleMap.put(type,noodle);
210 return noodle;
211 }
212 }
主要资料来源:《设计模式之禅》、《大话设计模式》、网络


浙公网安备 33010602011771号