设计模式一 单例模式,工厂模式
单例模式
简述:是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
- 单例类只能有一个实力
- 单例类必须自己创建自己的唯一实力
- 单例类可以给所有其他对象提供这一个实例
如今实际开发中,单例模式都交给spring的bean工厂进行处理
/**
* 饿汉式
* 类加载到内存后,就实例化一个单例,JVM保证线程安全
* 简单实用,推荐使用!
* 唯一缺点:不管用到与否,类装载时就完成实例化
* Class.forName("")
* (话说你不用的,你装载它干啥)
*/
public class Mgr01 {
private static final Mgr01 INSTANCE = new Mgr01();
private Mgr01() {};
public static Mgr01 getInstance() {
return INSTANCE;
}
public void m() {
System.out.println("m");
}
public static void main(String[] args) {
Mgr01 m1 = Mgr01.getInstance();
Mgr01 m2 = Mgr01.getInstance();
System.out.println(m1 == m2);
}
}
/**
* 跟01是一个意思
*/
public class Mgr02 {
private static final Mgr02 INSTANCE;
static {
INSTANCE = new Mgr02();
}
private Mgr02() {};
public static Mgr02 getInstance() {
return INSTANCE;
}
public void m() {
System.out.println("m");
}
public static void main(String[] args) {
Mgr02 m1 = Mgr02.getInstance();
Mgr02 m2 = Mgr02.getInstance();
System.out.println(m1 == m2);
}
}
/**
* lazy loading(懒加载模式)
* 也称懒汉式
* 虽然达到了按需初始化的目的,但却带来线程不安全的问题
*/
public class Mgr03 {
private static Mgr03 INSTANCE;
private Mgr03() {
}
public static Mgr03 getInstance() {
if (INSTANCE == null) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Mgr03();
}
return INSTANCE;
}
public void m() {
System.out.println("m");
}
public static void main(String[] args) {
for(int i=0; i<100; i++) {
new Thread(()->
System.out.println(Mgr03.getInstance().hashCode())
).start();
}
}
}
/**
* lazy loading
* 也称懒汉式
* 虽然达到了按需初始化的目的,但却带来线程不安全的问题
* 可以通过synchronized解决,但也带来效率下降
*/
public class Mgr04 {
private static Mgr04 INSTANCE;
private Mgr04() {
}
public static synchronized Mgr04 getInstance() {
if (INSTANCE == null) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Mgr04();
}
return INSTANCE;
}
public void m() {
System.out.println("m");
}
public static void main(String[] args) {
for(int i=0; i<100; i++) {
new Thread(()->{
System.out.println(Mgr04.getInstance().hashCode());
}).start();
}
}
}
/**
* 静态内部类方式
* JVM保证单例
* JVM在装载静态方法的时候只装在一次,加之其加了final关键词;
* 加载外部类时不会加载内部类,这样可以实现懒加载
*/
public class Mgr05 {
private Mgr05() {
}
private static class Mgr05Holder {
private final static Mgr05 INSTANCE = new Mgr07();
}
public static Mgr05 getInstance() {
return Mgr05Holder.INSTANCE;
}
public void m() {
System.out.println("m");
}
public static void main(String[] args) {
for(int i=0; i<100; i++) {
new Thread(()->{
System.out.println(Mgr05.getInstance().hashCode());
}).start();
}
}
}
/**
* 不仅可以解决线程同步,还可以防止反序列化。
* 枚举类没有构造方法;
*/
public enum Mgr06 {
INSTANCE;
public void m() {}
public static void main(String[] args) {
for(int i=0; i<100; i++) {
new Thread(()->{
System.out.println(Mgr06.INSTANCE.hashCode());
}).start();
}
}
}
工厂模式
- 简单工厂–可拓展性差
- 静态工厂–单例模式
- 抽象工厂
- 抽象类和接口的区别问题:
- 抽象类主要是代码层面,因为其可以有普通方法,可以增加代码的复用,接口是在架构设计层面,起到约束代码的作用;
- 接口都是抽象方法,抽象类可以有普通方法,接口无普通成员变量,抽象类可以有普通成员变量(如1所述);
- 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型;
- 抽象类可以包含静态方法,接口不行,1.8之后可以,1.8以后的接口不再纯净
- 继承与实现的问题,单继承,多实现;
- 另,抽象类和接口,表达的语意不同,抽象类–》具体事物的抽象
- 抽象工厂更多是为了进行生成对象族;用工厂的方法,继承实现其方法得到不同族系的工厂类,从而从不同的工厂得到不同族系的对象;
- 抽象类和接口的区别问题:
- 更好的解决方案–>Spring的bean工厂 ,Spring->IOC,控制反转;spring的ioc可以理解为工厂模式的高级实现
抽象工厂的代码如下:
public abstract class AbastractFactory {
abstract Food createFood();
abstract Vehicle createVehicle();
abstract Weapon createWeapon();
}
public abstract class Weapon {
abstract void shoot();
}
public abstract class Vehicle { //interface
abstract void go();
}
public abstract class Vehicle { //interface
abstract void go();
}
public class AK47 extends Weapon{
public void shoot() {
System.out.println("tututututu....");
}
}
public class MagicStick extends Weapon{
public void shoot() {
System.out.println("diandian....");
}
}
public class Car extends Vehicle{
public void go() {
System.out.println("Car go wuwuwuwuw....");
}
}
public class Broom extends Vehicle{
public void go() {
System.out.println("Car go wuwuwuwuw....");
}
}
public class MushRoom extends Food{
public void printName() {
System.out.println("dmg");
}
}
public class Bread extends Food{
public void printName() {
System.out.println("bread talk");
}
}
public class MagicFactory extends AbastractFactory {
@Override
Food createFood() {
return new MushRoom();
}
@Override
Vehicle createVehicle() {
return new Broom();
}
@Override
Weapon createWeapon() {
return new MagicStick();
}
}
public class ModernFactory extends AbastractFactory {
@Override
Food createFood() {
return new Bread();
}
@Override
Vehicle createVehicle() {
return new Car();
}
@Override
Weapon createWeapon() {
return new AK47();
}
}
public class Main {
public static void main(String[] args) {
AbastractFactory f = new ModernFactory();
Vehicle c = f.createVehicle();
c.go();
Weapon w = f.createWeapon();
w.shoot();
Food b = f.createFood();
b.printName();
}
}