浅谈Java设计模式——单实例、简单工厂、抽象工厂、观察者
来源:互联网 发布:系统检测修复软件 编辑:程序博客网 时间:2024/05/17 05:51
最近的项目里面涉及到一些Java设计模式,在此简单谈一下自己的看法,以下示例一部分参考同行,大部分自己设计。
1.单例模式
如果一个类始终只能创建一个实例,则这个类成为单例类,这种设计模式称为单例模式。
class Singleton{ // 使用一个类变量缓存创建的实例 private static Singleton instance; // 隐藏构造器 private Singleton(){ } // 提供一个静态方法,用于返回Singleton实例 public static Singleton getInstance() { // 如果instance为null,表明还不曾创建Singleton对象 // 如果instance不为null,则表明已经创建了Singleton对象,将不会执行该方法 if (instance == null) { // 创建一个Singleton对象,并将其缓存起来 instance = new Singleton(); } //如果instance已经创建过,直接返回 return instance; }}
写个测试程序
public class SingletonTest{ public static void main(String[] args) { // 创建两个Singleton 对象 Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); // 将输出true System.out.println(s1 == s2); }}
Spring容器所管理的Bean实例默认是单例,可以通过scope来修改其行为方式。
使用单例模式的优势:
(1)减少系统开销(不用每次都创建新的实例)
(2)便于系统跟踪单个实例的生命周期与实例状态等。
2.简单工厂
通过工厂来创建对象的设计模式称为简单工厂模式。
当需要创建一个对象的时候不通过new 来创建,而是通过向工厂下订单来创建。
先定义一个房子(House),房子里面有张桌子(Table),还可以获得桌子的相关信息(getTableMaterial()获得桌子的材料)。
/** * * 一个House里面有张桌子table(这个table是抽象的,需要工厂根据用户的实际要求具体实现) * table通过工厂tableFactory来生产 * tableFactory根据用户所要求的材料material来定制table */public class House { private Table table; public House(Table table){ this.table = table; } //获得table 的material(所用材料) public void getTableMaterial(){ table.getMaterial(); } public static void main(String[] args){ TableFactory tableFactory = new TableFactory(); //通过工厂生产Table对象并传递给构造器 House house = new House(tableFactory.getTable("wood")); house.getTableMaterial(); }}
下面是Table接口,拥有Table的一般行为。
public interface Table { public void getMaterial();}
下面是三个具体的实现类(三种材质的桌子)。
/** * 木桌 */public class WoodTable implements Table { @Override public void getMaterial() { // TODO Auto-generated method stub System.out.println("Material of this Table is Wood!"); }}
/** * 铁桌 */public class SteelTable implements Table { @Override public void getMaterial() { // TODO Auto-generated method stub System.out.println("Material of this Table is Steel!"); }}
/** * 塑料桌 */public class PlasticTable implements Table { @Override public void getMaterial() { // TODO Auto-generated method stub System.out.println("Material of this Table is Plastic!"); }}
下面是桌子工厂,可以根据用户的需求生产相应的桌子。
public class TableFactory { public Table getTable(String material){ switch(material){ case "wood": return new WoodTable(); case "steel": return new SteelTable(); default : return new PlasticTable(); } }}
下面进行测试:
public static void main(String[] args){ TableFactory tableFactory = new TableFactory(); //工厂根据用户的需求生产Table对象并传递给构造器 House house = new House(tableFactory.getTable("wood"));//用户要求木桌(woodTable) house.getTableMaterial(); }
测试结果:
用户可以向工厂提出自己的需求(woodTable ,steelTable还是plasticTable),由工厂来生产Table(创建Table对象);
简单工厂的优势:对象的调用者与对象的创建过程分离,避免对象的调用与实现以硬编码的方式耦合,提高系统的可维护性和可拓展性。
3.抽象工厂模式
抽象工厂简单地说是工厂的工厂,抽象工厂可以创建具体工厂,由具体工厂来产生具体产品。
来看个示例。
有一个汽车商店(CarShop),里面有一辆汽车(car),还可以获得汽车的相关信息。
public class CarShop { private Car car; public CarShop(Car car){ this.car = car; } //获得汽车的相关信息 public void getCarInfo(){ car.getCarInfo(); } public static void main(String[] args) { // TODO Auto-generated method stub //通过抽象工厂获得具体工厂 CarFactory cf = CarFactoryFactory.getCarFactory("A"); //通过具体工厂创建具体car对象并传递给构造器 CarShop cs = new CarShop(cf.createCar("BMW")); cs.getCarInfo(); }}
有一个抽象汽车工厂,用来根据用户需求创建具体汽车工厂。
public class CarFactoryFactory { //根据carType创建具体工厂 public static CarFactory getCarFactory(String carType){ switch(carType){ case "A": return new ACarFactory(); case "B": return new BCarFactory(); default : return new CCarFactory(); } }}
有A、B、C三个具体汽车工厂,用来生产三种类型的汽车。
/** * A工厂 * 根据用户要求的品牌(carBrand) * 生产A类型的汽车 */public class ACarFactory implements CarFactory { @Override public Car createCar(String carBrand) { // TODO Auto-generated method stub switch(carBrand){ case "BMW": return new BMWCarA(); case "Benz": return new BenzCarA(); default : return new AudiCarA(); } }}
/*** B工厂 * 根据用户要求的品牌(carBrand) * 生产B类型的汽车 */public class BCarFactory implements CarFactory { /* (non-Javadoc) * @see com.abstructFactory.CarFactory#createCar(java.lang.String) */ @Override public Car createCar(String carBrand) { switch(carBrand){ case "BMW": return new BMWCarB(); case "Benz": return new BenzCarB(); default : return new AudiCarB(); } }}
/** * C工厂 * 根据用户要求的品牌(carBrand) * 生产C类型的汽车 */public class CCarFactory implements CarFactory { @Override public Car createCar(String carBrand) { switch(carBrand){ case "BMW": return new BMWCarC(); case "Benz": return new BenzCarC(); default : return new AudiCarC(); } }}
这三个具体工厂类都实现了同一个汽车工厂接口,该接口拥有一般汽车工厂的行为。
public interface CarFactory { public Car createCar(String carBrand);}
A、B、C三个具体汽车工厂分别生产三种品牌(BMW,Benz和Audi)的汽车。
/** * A工厂生产的Audi汽车 */public class AudiCarA implements Car { @Override public void getCarInfo() { System.out.println("Audi car from ACarFactory"); }}
/** * A工厂生产的Benz汽车 */public class BenzCarA implements Car { @Override public void getCarInfo() { System.out.println("Benz car from ACarFactory"); }}
/** * A工厂生产的BMW汽车 */public class BMWCarA implements Car { @Override public void getCarInfo() { System.out.println("BMW car from ACarFactory"); }}
/** * B工厂生产的Audi汽车 */public class AudiCarB implements Car { @Override public void getCarInfo() { System.out.println("Audi car from BCarFactory"); }}
/** * B工厂生产的Benz汽车 */public class BenzCarB implements Car { @Override public void getCarInfo() { System.out.println("Benz car from BCarFactory"); }}
/** * B工厂生产的BMW汽车 */public class BMWCarB implements Car { @Override public void getCarInfo() { System.out.println("BMW car from BCarFactory"); }}
/** * C工厂生产的Audi汽车 */public class AudiCarC implements Car { @Override public void getCarInfo() { System.out.println("BMW car from CCarFactory"); }}
/** * C工厂生产的Benz汽车 */public class BenzCarC implements Car { @Override public void getCarInfo() { System.out.println("BMW car from CCarFactory"); }}
/** * C工厂生产的BMW汽车 */public class BMWCarC implements Car { @Override public void getCarInfo() { System.out.println("BMW car from CCarFactory"); }}
这些具体的汽车产品都实现了同一个接口(Car),该接口拥有汽车的一般行为。
public interface Car { public void getCarInfo();}
下面来做个测试,用户要求一辆A工厂生产的BMW汽车:
public static void main(String[] args) { // TODO Auto-generated method stub //通过抽象工厂获得具体工厂 CarFactory cf = CarFactoryFactory.getCarFactory("A"); //通过具体工厂创建具体car对象并传递给构造器 CarShop cs = new CarShop(cf.createCar("BMW")); cs.getCarInfo(); }
测试结果:
抽象工厂可以根据用户的需求,通过不同的具体工厂生产不同的产品。
那么抽象工厂模式有什么好处呢?假如采用简单工厂模式,假如只有A工厂,当用户要求一辆B类型的BMW时,就要修改A工厂代码来生产BMWCarB对象。所以,抽象工厂模式的优势是:对象的调用者与对象的实现类以及具体的工厂分离,代码的耦合性更低,系统可维护性以及可拓展性更高。
但是抽象工厂模式有个缺陷,就是当用户需求改变的时候,需要修改代码,然后需要重新编译,最好是将用户需求(可以看做用户订单)放在一个配置文件里面,由代码根据配置文件来创建相应的工厂以及实例,这样当用户需求发生改变的时候,只需要修改配置文件(产品订单)即可。
Spring IOC容器是一个抽象工厂,既可以管理Bean实例,还可以管理工厂实例。ApplicationContext.xml可以看作是系统的订单,容器根据这个订单生产相应的Bean。
4.观察者模式
观察者模式又称发布订阅模式,定义了一种一对多依赖关系,让一个或多个观察者对象观察一个主题对象,当主题对象的状态发生改变时,系统会通知所有的依赖于此对象的观察者,从而使得观察者对象能够自动更新。
看一个示例:
有一个任务列表TaskList,里面的任务需要两个程序员去完成,TaskList可以看作是被观察的主题对象,两个程序员可以看作是依赖于此主题对象的观察者,当任务列表里面的任务更新时,要通知这两个程序员。
下面是TaskList:
public class TaskList extends Observable{ private List<String> allTask; private static TaskList instance; //私有构造器 private TaskList(){ } public static TaskList getInstance(){ if(instance == null){ instance = new TaskList(); instance.allTask = new ArrayList<String>(); } return instance; } //添加观察者 public void addTaskObserver(Observer observer){ this.addObserver(observer); } //任务列表发生改变 public void addNewTask(String newTask){ allTask.add("new Task"); System.out.println("系统添加了新任务"); //被观察对象发生改变 this.setChanged(); //通知观察者并传递新任务 this.notifyObservers(newTask); }}
下面是两个程序员:
public class ProgrammerA implements Observer{ //自动更新 @Override public void update(Observable o, Object task) { String newTask = (String)task; System.out.println("ProgrammerA 您有新的任务: " +newTask); }}
public class ProgrammerB implements Observer{ //自动更新 @Override public void update(Observable o, Object task) { String newTask = (String)task; System.out.println("ProgrammerB 您有新的任务: " +newTask); }}
下面做个测试:
public class ObserverTest { public static void main(String[] args) { //被观察的任务列表 TaskList observable = TaskList.getInstance(); //观察者 ProgrammerA pa = new ProgrammerA(); ProgrammerB pb = new ProgrammerB(); //添加观察者 observable.addObserver(pa); observable.addObserver(pb); //任务列表发生改变 observable.addNewTask("new Task"); }}
测试结果:
Java EE 应用中,主题/订阅模式下的JMS就是观察者模式的应用。
设计模式是对处于特定环境下,经常出现的某类软件开发问题的一种相对成熟的设计方案,是软件设计师集体经验的体现。优雅的代码没必要刻意使用哪种设计模式,最好是它本身就体现出设计模式。
- 浅谈Java设计模式——单实例、简单工厂、抽象工厂、观察者
- Java设计模式——工厂模式(简单工厂、工厂方法 、抽象工厂 )
- 浅谈设计模式之一——简单工厂、工厂、抽象工厂
- 设计模式——简单工厂,工厂方法,抽象工厂
- 设计模式——简单工厂、工厂方法、抽象工厂
- java设计模式示例程序之 ——简单工厂、工厂方法、抽象工厂模式
- Java设计模式—工厂方法模式&抽象工厂模式
- Java设计模式—工厂方法模式&抽象工厂模式
- <Java设计模式>—抽象工厂模式
- 设计模式——三个工厂模式(简单工厂,工厂方法,抽象工厂)
- 设计模式C#描述之——简单工厂模式、抽象工厂模式、单例与多例模式
- 设计模式C#描述之——简单工厂模式、抽象工厂模式、单例与多例模式
- Java设计模式--简单工厂模式与抽象工厂模式
- C++设计模式——简单工厂模式、工厂模式、抽象工厂模式
- 设计模式——简单工厂模式、工厂方法模式和抽象工厂模式
- 设计模式学习笔记——简单工厂模式、工厂方法模式、抽象工厂模式
- JAVA常用设计模式总结(单例,工厂,抽象工厂)
- JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式+抽象工厂模式)
- activiti学习笔记(四) 配置器
- 8.6 二叉树----基本操作
- 【OpenCv应用笔记】基于OpenCv的视频截图C++程序
- Struts2的系统架构
- Andrew Ng机器学习笔记1
- 浅谈Java设计模式——单实例、简单工厂、抽象工厂、观察者
- 理解 Linux 中的 关机命令
- SQL中Left Join 与Right Join 与 Inner Join 与 Full Join的区别
- 金融企业软件测试中心筹备书-考核及总结篇
- 入门级使用PowerDesigner软件创建数据库
- 方向
- LeetCode--First Missing Positive
- sysstat 中sar命令使用笔记
- Java并发包基石-AQS详解