面向对象的设计模式

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 }
View Code

 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 }
View Code

主要资料来源:《设计模式之禅》、《大话设计模式》、网络

posted @ 2020-03-22 21:19  Tanglong  阅读(170)  评论(0)    收藏  举报