一、简单工厂模式
简单工厂模式又叫静态工厂方法模式,他定义一个具体的工厂类负责创建一些类的实例。
优点:客户端不需要在负责对象的创建,从而明确了各个类的职责。
缺点:这个具体的工厂类要负责所有类的对象的创建,如果有新的对象增加或者某些类的创建方式不同,就需要不断的修改这个工厂类,不利于后期的维护和扩展。
下面我们通过代码通俗易懂的了解一下:
//抽象动物类
public abstract class Animal {
public abstract void eat();
}
//狗类
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
//猫类
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
以上内容和简单工厂方法本身没有太大的关联,重点在下一个动物工厂类
//动物工厂类
public class AnimalFactory {
//构造方法私有就只能通过静态方法创建对象了
private AnimalFactory(){}
public static Animal createAnimal(String type){
if("dog".equals(type)){
return new Dog();
}else if("cat".equals(type)){
return new Cat();
}else{
return null;
}
}
}
//测试类
public class Test {
public static void main(String[] args) {
Animal a=AnimalFactory.createAnimal("cat");
a.eat();//猫吃鱼
a=AnimalFactory.createAnimal("dog");
a.eat();//狗吃肉
}
}
那么可以看到,我们要创建狗或猫的对象,不用去找狗或者猫,找动物工厂就可以帮我们造出相应的对象,那如果我还想要狮子、老虎、鳄鱼、斑马这些动物,就要不停的改写动物工厂类里面createAnimal()这个方法,很显然,这样做非常不利于维护和扩展,不符合面向对象设计原则里面的开闭原则。
二、工厂方法模式
工厂方法模式就是为了弥补简单工厂模式的不足而设计的。工厂方法模式中抽象工厂类或者工厂接口负责定义创建对象的接口,具体对象的创建工作由抽象工厂类和工厂接口的具体实现类来完成。工厂方法模式和简单工厂模式的区别显而易见:工厂方法模式工厂类或接口并不负责创建对象,他是一个抽象的,具体的创建工作有抽象工厂的实现类来负责,而简单工厂模式工厂类是具体的,他要实实在在的的负责创建对象,那肯定很辛苦了,前者抽象工厂是老大,创建对象的事情小弟去做就行了。
//抽象动物类
public abstract class Animal {
public abstract void eat();
}
//狗类
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
//猫类
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
以上内容和工厂方法模式本身没有太大的关联,重点在下一个抽象工厂接口
//抽象工厂
public interface Factory {
public abstract Animal createAnimal();
}
//狗工厂
public class DogFactory implements Factory {
@Override
public Animal createAnimal() {
return new Dog();
}
}
//猫工厂
public class CatFactory implements Factory {
@Override
public Animal createAnimal() {
return new Cat();
}
}
//测试类
public class Test {
public static void main(String[] args) {
Factory f=new DogFactory();
Animal a=f.createAnimal();
a.eat();//狗吃肉
f=new CatFactory();
a=f.createAnimal();
a.eat();//猫吃鱼
}
}
如果这个时候我们还想要老虎狮子等更多的动物,那就只需要增加相关的老虎工厂、狮子工厂就可以了,而不需要在改动抽象工厂。
三、单例模式
单例模式:保证类在内存中只有一个对象
如何保证类在内存中只有一个该类的对象:
(1)把构造方法私有,这样外界就不能通过构造方法创建对象
(2)在成员位置创建一个自己的对象(私有)
(3)通过公共方法提供访问
单例模式分为饿汉式和懒汉式,所谓饿汉式就是指类一加载就创建对象,懒汉式是指用的时候再创建对象。
1、饿汉式单例
public class Student {
private Student(){}//构造私有
private static Student s=new Student();//成员位置的私有对象
public static Student getStudent(){//对外提供公共的访问方法
return s;
}
}
饿汉式单例的对象在类一加载就会创建,不存在线程安全问题,可以保证在内存中只存在一个实例。
2、懒汉式单例
public class Teacher {
private Teacher(){}//构造私有
private static Teacher t=null;//成员位置的对象
public static synchronized Teacher getTeacher(){//对外提供公共访问方法
if(t==null){
t=new Teacher();
}
return t;
}
}
这是懒汉式单例,由于懒汉式单例在多线程环境下可能存在同步问题,所以加上synchronized关键字可以保证线程安全,但是如果这样的话,每个线程需要获取对象的时候都要获取锁,如果获取不到就要阻塞,无形之间降低了并发的效率,所以我们可以尝试降低锁的粒度,如下:
public class Teacher {
private Teacher(){}//构造私有
private static Teacher t=null;//成员位置的对象
public static Teacher getTeacher(){//对外提供公共访问方法
if(t==null){
synchronized(Teacher.class){
t=new Teacher();
}
}
return t;
}
}
这样如果对象已经存在的话,就不需要再进入临界区了。
四、适配器模式
public interface UserDao {
public abstract void add();
public abstract void delete();
public abstract void update();
public abstract void find();
}
public abstract class UserAdapter implements UserDao{
@Override
public void add() {}
@Override
public void delete(){}
@Override
public void update() {}
@Override
public void find() {}
}
public class UserDaoImpl extends UserAdapter {
@Override
public void add() {
System.out.println("添加功能");
}
}
public class Test {
public static void main(String[] args) {
UserDao ud=new UserDaoImpl();
ud.add();
}
}