1、单例模式(Singleton Pattern)
单例模式能够保证在JVM中只有一个实例存在。可以省去new,减少内存使用频率,还有一些核心的类在内存中只能有一个实例。
如下
package com.remote3c.singleton;
public class Car {
//构造方法设置为private,只能它自身创建对象,其他地方不能 new Car()
private Car(){
}
//生产一个静态的car对象,保证JVM中只有一个
private static Car car = new Car();
//添加获取实例的方法
public static Car getInstance(){
return car;
}
}
测试
package com.remote3c.singleton;
public class Test {
/**
* @author zhangyoushuai
* @version 1.0.0
* @param args
*/
public static void main(String[] args) {
Car car1 = Car.getInstance();
Car car2 = Car.getInstance();
if(car1==car2){
System.out.println("car1=car2");
}
}
}
还有一种更好的写法,需要的时候再产生。
public class Singleton {
private Singleton(){}
public static Singleton getInstance(){
return SingletonInstance.instance;
}
private static class SingletonInstance{
static Singleton instance = new Singleton();
}
}
2、工厂模式(FactoryPattern)
当需要大量的创建对象时,可以考虑工厂模式,工厂模式特点创建对象和使用对象分开。
简单工厂,模拟 老张开车去东北,老张可以开着车,可以开着飞机,也可以骑着扫帚等等交通工具, 实现任意变换交通工具和生产交通工具的过程。
一提到任意变换,肯定用到多态,用到多态肯定就少不了继承,重写,父类引用指向子类对象。这里的继承泛指实现。
首先我们写一个交通工具的接口Moveable:
package com.remote3c.simplefactory;
public interface Moveable {
public void run();
}
接着写实现了这个接口的具体的交通工具car和palane
package com.remote3c.simplefactory;
public class Car implements Moveable {
public void run() {
System.out.println("开着车,冒着烟,突突突突……去了东北");
}
}
package com.remote3c.simplefactory;
public class Plane implements Moveable {
public void run() {
System.out.println("开着飞机,呜呜呜呜……的去了东北");
}
}
按照题意还要实现任意变换生产交通工具的生产过程,那就先建立一个交通工具的接口
package com.remote3c.simplefactory;
public interface VehicleFactory {
//生产交通工具 Vehicle-交通工具
public Moveable produce();
}
接着写实现了这个接口的car工厂和plane工厂
package com.remote3c.simplefactory;
/**
* @author zhangyoushuai
* 汽车工厂
*/
public class CarFactory implements VehicleFactory{
public Moveable produce() {
return new Car();
}
}
package com.remote3c.simplefactory;
/**
* @author zhangyoushuai
* 飞机工厂
*/
public class PlaneFactory implements VehicleFactory {
public Moveable produce() {
return new Plane();
}
}
最后写测试类
package com.remote3c.simplefactory;
public class Test {
/**
* @author zhangyoushuai
* @version 1.0.0
* @param args
* 模拟 老张开车去东北
* 老张可以开着车,也可以开着飞机,骑着扫帚等等交通工具
* 实现任意变换交通工具和生产交通工具的过程
* 当需要大量的创建对象时,可以考虑工厂模式,工厂模式特点创建对象和使用对象分开
*/
public static void main(String[] args) {
/**
这里可以任意变换生产交通工具的工厂,下面去东北所乘的交通工具也随之改变
当有新的交通工具添加进来的时候,只需实现moveable接口创建交通工具,
再实现VehicleFactory接口创建工厂即可,
*/
VehicleFactory vehicle =new PlaneFactory();
// VehicleFactory vehicle =new CarFactory();
Moveable moveable =vehicle.produce();
moveable.run();
}
}
3、抽象工厂模式(AbstractFactoryPattern)
上面的工厂模式,有时候会造成很多工厂,工厂泛滥的情况,还有就是乘交通工具的同时再有吃着东西,打着枪等行为时该怎么办呢?
抽象工厂就是同时解决一系列产品或行为的一种模式,提供一个接口,用于创建相关或者依赖对象的家族。而不像上面那样一个工厂只生产一种产品或者行为,
而是生产一系列的产品或者行为。
下面用代码详细的模拟乘着交通工具,吃着食物,拿着武器一系列行为去东北的情况
首先创建一个抽象的总工厂
package com.remote3c.abstractfactory;
public abstract class AbstractFactory {
public abstract Vehicle createVehicle();//生产交通工具
public abstract Weapon createWeapon();//生产武器
public abstract Food createFood();//生产食物
}
接着再创建 Vehicle(交通工具),Weapon(武器),Food(食物)的抽象类
package com.remote3c.abstractfactory;
public abstract class Vehicle {
public abstract void run();
}
package com.remote3c.abstractfactory;
public abstract class Weapon {
public abstract void shoot();
}
package com.remote3c.abstractfactory;
public abstract class Food {
public abstract void getName();
}
同时Vehicle有run(),Weapon有shoot(),Food有getName()方法,
接着通过实现Vehicle,Weapon,Food创建真正的交通工具,武器,食物
交通工具
package com.remote3c.abstractfactory;
public class Car extends Vehicle {
@Override
public void run() {
System.out.println("开着车 突突突突………………");
}
}
package com.remote3c.abstractfactory;
public class Broom extends Vehicle {
//扫帚
@Override
public void run() {
System.out.println("骑着扫帚呼啦哗啦,狼烟滚滚而去…………");
}
}
具体的武器
package com.remote3c.abstractfactory;
public class AK47 extends Weapon {
@Override
public void shoot() {
System.out.println("拿着武器AK47,发射 突突突突突……");
}
}
package com.remote3c.abstractfactory;
public class Magicstick extends Weapon {
//魔法棒
@Override
public void shoot() {
System.out.println("挥舞着魔法棒 天灵灵,地灵灵,魔法棒快显灵……");
}
}
具体的食物
package com.remote3c.abstractfactory;
public class Apple extends Food {
@Override
public void getName() {
System.out.println("吃着 Apple");
}
}
package com.remote3c.abstractfactory;
public class Mushroom extends Food {
//蘑菇
@Override
public void getName() {
System.out.println(" 吃着 Mushroom");
}
}
好了接下来该建立真正的工厂了
正常的普通的工厂
package com.remote3c.abstractfactory;
public class NormalFactory extends AbstractFactory {
//正常的,一般的工厂
@Override
public Food createFood() {
// TODO Auto-generated method stub
return new Apple();
}
@Override
public Vehicle createVehicle() {
// TODO Auto-generated method stub
return new Car();
}
@Override
public Weapon createWeapon() {
// TODO Auto-generated method stub
return new AK47();
}
}
带有魔法的工厂
package com.remote3c.abstractfactory;
public class MagicFactory extends AbstractFactory{
//有魔法的工厂
@Override
public Food createFood() {
// TODO Auto-generated method stub
return new Mushroom();
}
@Override
public Vehicle createVehicle() {
// TODO Auto-generated method stub
return new Broom();
}
@Override
public Weapon createWeapon() {
// TODO Auto-generated method stub
return new Magicstick();
}
}
最后终于写完了,该写测试程序啦
package com.remote3c.abstractfactory;
public class Test {
/**
* @author zhangyoushuai
* @version 1.0.0
* @param args
*/
public static void main(String[] args) {
//在这里可以随意的切换工厂,添加工厂也不用修改现有的code,具有很强的extensibility可扩展性
// AbstractFactory ab = new NormalFactory();
AbstractFactory ab = new MagicFactory();
Vehicle vehicle = ab.createVehicle();
vehicle.run();
Food food = ab.createFood();
food.getName();
Weapon weapon = ab.createWeapon();
weapon.shoot();
}
}
测试结果
骑着扫帚呼啦哗啦,狼烟滚滚而去…………
吃着 Mushroom
挥舞着魔法棒 天灵灵,地灵灵,魔法棒快显灵……
这就是抽象工厂,可以同时切换一族行为或产品,当你需要创建产品家族或想让制造的相关产品集合起来时,可以考虑使用抽象工厂。
但是抽象工厂也有它的短处,就是新增一种行为时,比如乘着交通工具,吃着东西,拿着武器的同时,再增加一种听着音乐的行为时,就需要改变抽象总工厂,会很麻烦。
如果行为不确定,最好不要用这种方法。
网上一些模式相关的链接
http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html
http://www.uml.org.cn/j2ee/201010214.asp
https://www.zhihu.com/question/39972591