设计模式学习笔记--23种设计模式(一)
来源:互联网 发布:linux默认用户名密码 编辑:程序博客网 时间:2024/05/16 19:03
模式一:单例模式
(一) 介绍
定义:确保某一个类只有一个实例,并且自行实例化并向整个系统提供这个实例。
(二) 实践
优点:
- 减少内存开销,特别是一个对象需要频繁的创建和销毁时
- 减少系统的性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久贮存在内存中,这里要注意垃圾回收机制,特别是J2EE.
- 避免对资源的多重利用
- 可以设置全局的访问点,优化和共享资源
缺点:
- 没有接口,扩展很难
- 对测试不利
- 与单一职责有冲突
应用场景:
- 要求生成唯一序列号的环境
- 在整个项目中需要一个共享访问点或共享数据,例如一个Web页面上的计数器,使用线程安全的单例模式保持计数器的值
- 创建一个对象需要消耗过多的资源,比如访问I/O和数据库
- 需要定义大量的静态常量和静态方法
- Spring中,每个Bean默认的都是单例的
//同步且高效率的单例模式:class Single{ private static Single s= null; private Single(){} public static Single getInstance(){ if(s==null){ synchronized(Single.class){ if(s==null) s=new Single(); } } }}
单例模式的扩展-有上线的多例模式
//旗舰店总共有宝马,奔驰两种车,有五个人从该旗舰店买车public class Car{ private static int maxNumOfCar = 2; private static ArrayList<String> nameList= new ArrayList<String>(); private static ArrayList<Car> carList= new ArrayList<Car>(); private static int countNumOfCar=0;static{ for(int i=0;i<maxNumOfCar ;i++){ carList.add(new Car("车"+(i+1))); }}private Car(){}private Car(String name){ nameList.add(name);}//旗舰店开始展出车public static Car getInstance(){ Random random= new Random(); countNumOfCar= random.nextInt(maxNumOfCar); return carList.get(countNumOfCar);}public static void drive(){ System.out.println("开车兜风");}}//开始购买车public class people{ public static void main(String[] args){ int peopleNum= 10; for(int i=0;i<peopleNum;i++){ //构建一个单例模式 Car car= Car.getInstance(); car.drive(); } }}
模式二:工厂方法模式
(一) 介绍
定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
工厂模式通用图:
- 抽象产品类Product负责定义产品的共性,实现对事物最抽象的定义
- Creator为抽象类创建类,也就是抽象工厂
- 如何创建产品类是由具体实现的工厂ConcreteCreator完成的
下面给出工厂类通用模板接口设计:
//抽象产品类public abstract class Product{ //产品类的公共方法 public void method1(){ //业务逻辑处理 } //抽象方法 public abstract void method2();}//具体的产品可以有多个,都继承于抽象产品类public class ConcreteProduct1 extends Product{ public void method2(){ //业务逻辑处理 }}public class ConcreteProduct2 extends Product{ public void method2(){ //业务逻辑处理 }}
抽象工厂类负责实现产品对象的产生
//抽象工厂类public abstract class Creator{ /* * 创建一个产品对象,其输入参数类型可以自行设置 *通常为String,Enum,Class等,当然也可以为空 */public abstract <T extends Product> T createProduct(Class<T> c);}
具体如何产生一个产品的对象,是由具体的工厂类实现的
//具体工厂类public class ConcreteCreator extends Creator{ public <T extends Product> T createProduct(Class<T> c){ Product product = null; try{ product=(Product)Class.forName(c.getName()).newInstance(); } catch (Exception e) { //异常处理 } return (T) product }}
实际场景应用
public class Client{ public static void main(String[] args){ Creator creator = new ConcreteCreator(); Product product = creator.creatorProduct(ConcreteProduct1.class); //继续业务处理 }}
(二) 应用
优点:
- 良好的封装性,代码结构清晰,一个调用者需要一个具体的产品对象,只要知道这个产品的类名就可以了
- 工厂方法模式的扩展性好
- 屏蔽产品类。产品类的实例化是由工厂类负责的,一个产品对象具体由哪一个产品生成是由工厂类决定
- 解耦框架
使用场景
- 工厂类模式是new一个对象的替代品,需要慎重的考虑是否需要一个工厂类进行管理,增加了代码的复杂性
- 需要灵活的、可扩展性的框架时,可以考虑采用工厂模式。比如网路测试中,需要测试不同的协议的流量,可以看成不同的产品,设计一个工厂类,根据传入的条件参数产生不同的产品(协议)
- 可用于异构项目中
- 可以使用在测试驱动开发的框架下
(三) 扩展
1、缩小为简单工厂模式
//定义人类public interface Human{ public void getColor(); public void talk();}//创建三个不同的人种public class BlackHuman implements Human{ public void getColor() { //业务逻辑 } public void talk(){ //业务逻辑 }}public class YellowHuman implements Human{ public void getColor() { //业务逻辑 } public void talk(){ //业务逻辑 }}public class WhiteHuman implements Human{ public void getColor() { //业务逻辑 } public void talk(){ //业务逻辑 }}
而工厂实现生产人类方法的输入参数应该是Human接口的实现类,所以应该为Class类型,采用泛型为createHuman的输入参数进行限制:必须是Class类型;必须是Huamn的实现类。
public abstract class AbstractHumanFactory{ public abstract <T extends Human> T createHuman(Class<T> c);}
然后就是HumanFactory的创建以及实例化
public class HumanFactory extends AbstractHumanFactory { public <T extends Human> T createHuman(Class<T> c){ Human human= null; try{ //产生一个人种 human=(T)Class.forName(c.getName()).newInstance(); }catch (Exception e){ //异常描述 } return (T)human; }}
最后就是Client的创建,进行生产人类
public class Client{ public static void main(String[] args){ AbstractHumanFactory factory = new HumanFactory(); Human whiteHuman= factory.createHuman(WhiteHuman.class); whiteHuman.getColor(); whiteHuman.talk(); //创建实例化其它的两种人类 ... }}
简化为下面的含有static参数的形式,在类图中去掉了AbstractHumanFactory 抽象类,同时把createHuman方法设置为静态类,简化了类的创建过程。
程序代码如下:
public class HumanFactory{ public static <T extends Human> T createHuman(Class<T> c){ //定义一个生产出的人种 Human human= null; try{ //产生一个人种 human=(T)Class.forName(c.getName()).newInstance(); }catch (Exception e){ //异常描述 } return (T)human; }}//相应的Client也会发生改动public class Client{ public static void main(String[] args){ Human whiteHuman= HumanFactory.createHuman(WhiteHuman.class); whiteHuman.getColor(); whiteHuman.talk(); //创建实例化其它的两种人类 ... }}
2、升级为多个工厂类
3、替代单例模式
4、延迟初始化
一个对象被消费完毕后,并不立刻释放,工厂类保持其初始状态,等待再次被使用
ProductFactory负责产品类对象的创建工作,并且通过一个prMap变量产生一个缓存。
//延迟加载的工厂类public class ProductFactory{ private static final Map<String,Product> proMap = new HashMap(); public static synchronized Product createProduct(String type) throws Exception { Product product = null; //如果Map中已经有这个对象 if(proMap.containsKey(type)){ product= proMap.get(type); }else{ if(type.equals("Product1")){ product= new ConcreteProduct1(); }else{ product= new ConcreteProduct2(); } //同时把对象放到缓存容器中 proMap.put(type,product); } return product; }}
模式三:抽象工厂模式
(一)介绍:
定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类
通用类图:
通用源码图:
代码模板:
public abstract class AbstractProductA{ //每个产品共有的方法 public void shareMethod(){ } //每个产品相同的方法,不同的实现 public abstract void doSomething();}
具体产品实现类:
//产品A1的实现类public class ProductA1 extends AbstractProductA{ public void doSomething(){ System.out.println("产品A1的实现方法"); }}//产品A2的实现类public class ProductA2 extends AbstractProductA{ public void doSomething(){ System.out.println("产品A2的实现方法"); }}//产品B1的实现类public class ProductB1 extends AbstractProductB{ public void doSomething(){ System.out.println("产品B1的实现方法"); }}//产品B2的实现类public class ProductB2 extends AbstractProductB{ public void doSomething(){ System.out.println("产品B2的实现方法"); }}
抽象工厂AbstractCreator的职责是定义每个工厂要实现的功能,在通用代码中,抽象工厂类实现了两个产品族的产品创建(如果有N个产品族,在抽象工厂类中就有N个创建方法)
public abstract class AbstractCreator { //创建A产品家族 public abstract AbstractProductA createProductA(); //创建B产品家族 public abstract AbstractProductB createProductB();}
如何创建一个产品,就应该由具体的实现类来完成(有M个产品等级就应该有M个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务)
//产品等级1的实现类public class Creator1 extends AbstractCreator { //只生产产品等级为1的A类产品 public AbstractProductA creatProductA(){ return new ProductA1(); } //只生产产品等级为1的B类产品 public AbstractProductB creatProductB(){ return new ProductB1(); }}
//产品等级2的实现类public class Creator2 extends AbstractCreator { //只生产产品等级为1的A类产品 public AbstractProductA creatProductA(){ return new ProductA2(); } //只生产产品等级为1的B类产品 public AbstractProductB creatProductB(){ return new ProductB2(); }}
最后,在具体的业务中产生一个无关的对象
public class Client { public static void main(Stirng[] args) { //定义两个工厂 AbstractCreator creator1 = new Creator1(); AbstractCreator creator2 = new Creator2(); //产生分别具有两个等级的两个不同类型的对象 AbstractProductA a1= creator1.createProductA(); AbstractProductA a2= creator2.createProductA(); AbstractProductB b1= creator1.createProductB(); AbstractProductB b2= creator2.createProductB(); //实现业务逻辑 .......... }}
(二)应用:
优点:
- 封装性
- 产品族的约束为非公开状态
缺点:
产品族扩展非常困难
使用场景:
一个对象族都有相同的约束关系
注意事项:
抽象工厂模式产品族(产品个数)扩展困难,而产品等级(产品属性)扩展容易,即横向扩展容易,纵向扩展难。
(未完待续…)
参考文献
《设计模式之禅》 秦小波著
《Java核心技术 卷I》 周立新等译
《算法分析与设计》 霍红卫译
- 设计模式学习笔记--23种设计模式(一)
- 设计模式学习笔记一
- 设计模式学习笔记 一
- 设计模式学习笔记(一)
- 设计模式学习笔记(一)
- 设计模式学习笔记(一):设计模式与设计原则
- 设计模式学习笔记(一): Bridge 模式
- 设计模式学习笔记(一):策略模式
- 【Java23种设计模式学习笔记】一:策略模式
- 《Head First 设计模式》学习笔记一:设计模式入门
- 设计模式入门--设计模式学习笔记<一>
- java设计模式学习笔记(一)-- 简述设计模式
- 设计模式学习笔记:一、设计模式简介
- 设计模式学习笔记(一)设计模式六大原则
- 设计模式学习笔记(一)
- 设计模式的学习笔记!(一)
- 设计模式学习笔记一(概述)
- 学习笔记(一)设计模式
- MAP学习--POJ1002
- Dom 经典实例
- Matlab求方差,均值,均方差,协方差的函数
- 我和刘强东的故事2:这次是真的
- iOS 同步请求和异步请求
- 设计模式学习笔记--23种设计模式(一)
- 数据结构的基本类型
- 给cin/cout提速
- hdu 5479(括号问题)
- 我的linux系统配置
- C++命名空间
- 数据模型设计
- PAT1006 换个格式输出整数
- Objective-C中一种消息处理方法performSelector: withObject: