设计模式(Design Pattern)是一套被反复使用、为多数人知晓、经过分类编目的、代码设计经验的总结。
使用设计模式的目的是为了代码重用,避免程序大量修改,同时使代码更易于理解,并且保证代码可靠性。设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
1 什么是单例模式
一、什么是单例模式
单例模式是一种对象创建模式,使用单例模式,可以保证为一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。
其实,GoF对单例模式的定义是:保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
二、为什么要使用单例模式呢?
在应用系统开发中,我们常常有以下需求:
- 在多个线程之间,比如servlet环境,共享同一个资源或者操作同一个对象
- 在整个程序空间使用全局变量,共享资源
- 在大规模系统中,为了性能的考虑,需要节省对象的创建时间等等。
因此Singleton模式可以保证为一个类只生成唯一的实例对象,所以这些情况,Singleton模式就派上用场了。
三、单例模式实现
1.饿汉式
2.懒汉式
3.双重检查(属于懒汉式,只是对懒汉式线程问题的改进)
//下面我们先不管上面的三种实现,自己写一个单例模式
public class Preson {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//构造函数私有化
private Person() {
}
//提供一个全局的静态方法(为什么要是静态方法,因为构造函数私有化了,不能再实例化,静态是保证用类名可以调用)
public static Person getPerson() {
return new Person();//其实这样依然不能够实现单例
}
}
这里没有成功实现单例
//下面我们使用饿汉式(加一个全局常量)
public class Preson {
public static final Person person = new Person();
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//构造函数私有化
private Person() {
}
//提供一个全局的静态方法
public static Person getPerson() {
return person;
}
}
//下面我们使用懒汉式(加一个全局变量)
//懒汉式只能在单线程里面保证是单例
public class Preson {
public static Person person;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//构造函数私有化
private Person() {
}
//提供一个全局的静态方法(这里进行判断)
public static Person getPerson() {
if(person == null) {
person = new Person();
}
return person;
}
}
//对于懒汉式多线程不能保证单例的情况,可以使用同步方法
public static synchronized Person getPerson() {
if(person == null) {
person = new Person();
}
return person;
}
}
//双重检查
public static synchronized Person getPerson() {
if(person == null) {
synchronized (Person.class) {
person = new Person();//这样还是不能保证单例
}
}
return person;
}
}
public static synchronized Person getPerson() {
if(person == null) {
synchronized (Person.class) {
if(Person = = null) {
person = new Person();//这样还是不能保证单例
}
}
}
return person;
}
//性能再次优化,把同步方法中需要同步的地方同步
2 什么是工厂模式
一、什么是简单工厂模式
简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
二、模式中包含的角色及其职责
- 工厂角色:简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
- 抽象角色:简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
- 具体产品角色:简单工厂模式所创建的具体实例对象。
三、简单工厂模式的优缺点
在这个模式中,工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构的优化。
不难发现,简单工厂模式的缺点也正体现在其工厂类上,由于工厂类集中了所有实例的创建逻辑,所以“高内聚”方面做的并不好。另外,当系统中的具体产品类不断增多时,可能会出现要求工厂类也要做出相应的修改,扩展性并不很好。
这段代码是我们常见的
public class Banana {
/*
*采集
*/
public void get () {
System.out.println("采集香蕉");
}
}
public class Apple {
/*
*采集
*/
public void get () {
System.out.println("采集苹果");
}
}
//测试类
public class MainClass {
public static void main (String[] args) {
//实例化一个Apple
Apple apple = new Apple();
//实例化一个Banana
Banana banana = new Banana();
apple.get();
banana.get();
}
}
Apple和Banana这两个类可以抽象出一个接口,这样定义的好处就可以使用多态
public interface Fruit {
/*
*
*/
public void get();
}
public class Banana implements Fruit {
/*
*采集
*/
public void get () {
System.out.println("采集香蕉");
}
}
public class Apple implements Fruit {
/*
*采集
*/
public void get () {
System.out.println("采集苹果");
}
}
//测试类,这里就可以使用多态
public class MainClass {
public static void main (String[] args) {
//实例化一个Apple
Fruit apple = new Apple();
//实例化一个Banana
Fruit banana = new Banana();
apple.get();
banana.get();
}
}
简单工厂模式定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
//工厂类
public class FruitFactroy {
/*
*获得Apple类的实例
*/
public Fruit getApple() {
return new Apple();
}
/*
*获得Banana类的实例
*/
public Fruit getBanana() {
return new Banana();
}
}
public interface Fruit {
/*
*
*/
public void get();
}
public class Banana implements Fruit {
/*
*采集
*/
public void get () {
System.out.println("采集香蕉");
}
}
public class Apple implements Fruit {
/*
*采集
*/
public void get () {
System.out.println("采集苹果");
}
}
//测试类,这里就可以使用多态
//有了工厂类,我们就可以用工厂类进行实例化
public class MainClass {
public static void main (String[] args) {
//实例化一个Apple
Fruit apple = new FruitFactory().getApple();
//实例化一个Banana
Fruit banana = new FruitFactory().getBanana();
apple.get();
banana.get();
}
}
上述程序可以进行优化,工厂类改为静态,那么在测试时就不需要new了,可以直接类名进行调用
下面再对上面程序继续修改,上面的工厂很粗略,里面有许多不同的get方法,分别返回对应不同的对象,那么能不能只写一个方法呢?
//工厂类
public class FruitFactroy {
/*
*get方法,获得所有产品对象,那么里面就有增加判断
*/
public Fruit getFruit(String type) {
if (type.equalsIgnoreCase("apple")) {
return Apple.class.newInstance();
} else if(type.equalsIgnoreCase("banana")) {
return Banana.class.newInstance();
} else {
System.out.prntln("找不到相应的实例化类");
return null;
}
}
}
//测试类,这里就可以使用多态
//有了工厂类,我们就可以用工厂类进行实例化
public class MainClass {
public static void main (String[] args) {
Fruit apple = FruitFactory.getFruit("apple");
Fruit banana = FruitFactory.getFruit("banana");
apple.get();
banana.get();
}
}
上面的工厂类虽然写了一个方法,但是需要判断,能不能不需要判断呢?
//但是这样也会出现弊端,测试类(输入端)就只能输入完全正确的类名,上一中判断的不一定是完整类名,比如可以使apple,ap,app等。我们一般使用上一种
//工厂类
public class FruitFactroy {
/*
*get方法,获得所有产品对象,那么里面就有增加判断
*/
public Fruit getFruit(String type) {
try {
Class fruit = Class.forName(type);
return (Fruit) fruit.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
//测试类,这里就可以使用多态
//有了工厂类,我们就可以用工厂类进行实例化
public class MainClass {
public static void main (String[] args) {
Fruit apple = FruitFactory.getFruit("Apple");
Fruit banana = FruitFactory.getFruit("Banana");
apple.get();
banana.get();
}
}
一、什么是工厂方法模式
工厂方法模式同样属于类的创建型模式,又被称为多态工厂模式。工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实现创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
二、模式中包含的角色及其职责
- 抽象工厂角色:工厂方法模式的核心,任何工厂类都必须实现这个接口。
- 具体工厂角色:具体工厂类是抽象工厂的一个实现,负责实例化产品对象。
- 抽象角色:工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
- 具体产品角色:工厂方法模式所创建的具体实例对象。
三、工厂方法模式和简单工厂模式比较
工厂方法模式与简单工厂模式在结构上的不同不是很明显。工厂方法类的核心是一个抽象工厂类,而简单工厂模式的核心放在一个具体类上。
工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。
当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了“开放-封闭”原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。
工厂方法模式退化后可以演变成简单工厂模式。
对于上面的类,如果我们增加了一个产品(梨子),该怎么办,1.增加子类梨子;2.在工厂中增加判断
public class Pear {
/*
*采集
*/
public void get () {
System.out.println("采集梨子");
}
}
//工厂类
public class FruitFactroy {
/*
*get方法,获得所有产品对象,那么里面就有增加判断
*/
public Fruit getFruit(String type) {
if (type.equalsIgnoreCase(“apple”)) {
return Apple.class.newInstance();
} else if(type.equalsIgnoreCase(“banana”)) {
return Banana.class.newInstance();
} else if(type.equalsIgnoreCase(“Pear”)) {
return Pear.class.newInstance();
} else {
System.out.prntln(“找不到相应的实例化类”);
return null;
}
}
}
上面的工厂本身是针对多有的类都在此依据判断加工出来。现在我们对工厂也抽象出一个类,或者接口,具体的实例化都继承这个类或实现这个接口
public interface FruitFactory {
public Fruit getFruit():
}
public class AppleFactory implements FruitFactory {
public Fruit getFruit() {
return new Apple();
}
}
public class BananaFactory implements FruitFactory {
public Fruit getFruit() {
return new Banana();
}
}
//测试类
public class MainClass {
public static void main (String[] args) {
//要想获得apple实例,先获得apple工厂类实例
//获得AppleFactory
FruitFactory ff = new AppleFactory();
//通过AppleFactory来获得Apple实例对象
Fruit apple = ff.getFruit();
apple.get();
}
}
对于上面的这一种模式,再添加一种产品时就只需要1.增加子类产品;2.增加子类加工工厂
一、什么是抽象工厂模式
抽象工厂模式是所在形态的工厂模式中最为抽象和最具一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不指定产品的具体类型的情况下,能够创建多个产品族的产品对象。
二、产品族和产品等级结构