浅谈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就是观察者模式的应用。

设计模式是对处于特定环境下,经常出现的某类软件开发问题的一种相对成熟的设计方案,是软件设计师集体经验的体现。优雅的代码没必要刻意使用哪种设计模式,最好是它本身就体现出设计模式。

阅读全文
1 0
原创粉丝点击