话不多说奔主题,精神抖擞就是干!
Java中共包含23种设计模式,大致分为三种类型:
1. 创建型模式:单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。
2. 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
3. 行为型模式:模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式。
下面介绍常用的几种:
1. 单例模式:是个程序一般都会用到这个模式。比如日志类,整个项目工程可能只需要创建一次,重复创建也只是返回第一次创建的实例的引用。
//饿汉模式
public class HungrySingleTon implement Serializable{
// 保证序列化和反序列化时的对象的兼容性
static final long serialVersion = 42L;
//快加载,利用了JVM类的懒加载机制保证线程安全
private static final HungrySingleTon singleTon = new HungrySingleTon();
private HungrySingleTon()
{
//防止利用反射来生成实例,破坏单例机制
if (singleTon != null) {
throw new RunTimeException("单例禁止反射");
}
};
public static HungrySingleTon GetInstance() { return singleTon; }
}
//静态内部类,利用了JVM类的懒加载机制保证线程安全
public class SingleTon {
private static class InnerSingleTon {
private static SingleTon singleTon = new SingleTon();
}
private SingleTon() {
//防止利用反射来生成实例,破坏单例机制
if (singleTon != null) {
throw new RunTimeException("单例禁止反射");
}
};
public static SingleTon GetInstance() { return InnerSingleTon.singleTon; }
}
//懒汉模式
public class LazySingleTon {
//利用 volatile 禁止指令重排,保证线程之间可见性和一致性
private static volatile LazySingleTon singleTon = null;
private LazySingleTon() {};
//懒加载,利用 synchronized 保证线程间的原子性
public static LazySingleTon GetInstance() {
if (null == singleTon) {
synchronized (LazySingleTon.class) {
if (null == singleTon) {
singleTon = new LazySingleTon();
}
}
}
return singleTon;
}
}
*要点:构造函数私有化,new前双次判空加锁。
2. 工厂模式:集中化生产同一类产品(存在差异化),比如造车厂,我可能只造小轿车,但是小轿车可能有不同的颜色搭配,还有经济型、标准型、豪华型等性能搭配。
2.1 简单工厂
public class Car {
public Color color; //颜色
public Car (Color color) { this.color = color; }
}
public class PianYiCar extends Car {
public PianYICar(Color color) { super.color = color; }
}
public class XiaoZiCar extends Car {
public XiaoZiCar (Color color) { super.color = color; }
}
public class GuiCar extends Car {
public GuiCar (Color color) { super.color = color; }
}
public class CarFactory {
public Car Create(Type type, Color color) {
switch(type) {
case '经济型': return new PianYiCar (color);
case '标准型': return new XiaoZiCar (color);
case '豪华型': return new GuiCar(color);
default: return new Car(color);
}
}
}
*要点:简单工厂,其实就是条件工厂,根据不同条件去创建同一类型的差异化对象。
2.2 工厂方法:定义一个工厂类该类定义了一些标准方法但没有具体实现,通过不同的子类继承这个工厂父类并实现其标准方法去创造相同(存在差异化)或不同类型的对象。
//开闭原则
public abstract class CarFactory {
public abstract Car CreateCar(Color color);
}
//单一职责原则
public class PianYiCarFactory {
@Override
public Car CreateCar(Color color) {new PianYiCar(color); }
}
public class XiaoZiCarFactory {
@Override
public Car CreateCar(Color color) {new XiaoZiCar(color); }
}
public class GuiCarFactory {
@Override
public Car CreateCar(Color color) {new GuiCar(color); }
}
*要点:具体实施的工作不再由父工厂去完成,父工厂定义了行业标准,而子工厂根据老大说的标准,各自去完成自己的事情。
2.3 抽象工厂模式:由方法工厂组合演变而来
public interface IConn {
public IConn getConn();
}
public interface IComm {
public IComm getComm();
}
public interface IDataBaseUtils {
public IConn getConn();
public IComm getComm();
}
public class MySqlDataBase implement IDataBaseUtils {
public IConn getConn() {
system.out.println("mysql connected");
}
public IComm getComm() {
system.out.println("mysql command");
}
}
public class OracleDataBase implement IDataBaseUtils {
public IConn getConn() {
system.out.println("oracle connected");
}
public IComm getComm() {
system.out.println("oracle command");
}
}
3. 建造者模式
//使用场景:对象具有复杂结构,内部具有依赖关系顺序
public class Product {
private final string proName;
private final string part1;
private final string part2;
public Product(string proName, string part1, string part2) {
this.proName = proName;
this.part1 = part1;
this.part2 = part2;
}
public class Builder {
private string proName;
private string part1;
private string part2;
public Builder proName(string proName) { this.proName = proName; return this; }
public Builder part1(string part1) { this.part1 = part1; return this; }
public Builder part2(string part2) { this.part2 = part2; return this; }
}
public Product build () { return new Product(this.proName, this.part1, this.part2); }
}
调用
Product product = new Product.Builder().proName("Car").part1("1").part2("2").build();
*要点:建造者独立,便于扩展,内部细节可控。
4. 适配器模式
4.1 类适配器
先讲个小故事。大家在日常生活里,有没有遇到过这种情况,我的手机快没电了想要充电,但是手头只有一个二插头的充电器和一个三插头的插线板,woc,怎么办?好急啊!在线等~
那这种情况下我们是不是可以采取一些极端手段,比如把二插头的充电器的两只腿掰弯,这样是不是就能插进三插头的插线板里充电了呢?哈哈哈,没错,我真是个天才!
public Interface TwoChong {
public void TwoChongDian();
}
public Interface ThreeChong {
public void ThreeChongDian();
}
public class TwoChongImpl implements TwoChong {
@Override
public void TwoChongDian() { System.out.println("充电"); }
}
//下面这个就是你掰弯后的二插头充电器了^-^
public class TwoChongImplEx extends TwoChongImpl implements ThreeChong {
@Override
public void ThreeChongDian() { super.TwoChongDain(); }
}
*要点:其实说白了,就是对现有功能的一种扩展。
4.2 对象适配器:它是对类适配器的一种衍生,因为类适配具有强绑定、强约束性,调用污染,不方便扩展。
public class ThreeChongImpl implements ThreeChong {
private TwoChongImpl twoChongImpl = null;
public ThreeChongImpl(TwoChongImpl twoChongImpl) { this.twoChongImpl = twoChongImpl; }
@Override
public void ThreeChongDian() { twoChongImpl.TwoChongDian(); }
}
4.3 接口适配器:减少代码量,提高可读性。
public interface A {
public void Do();
}
public class AA implements A {
@Override
public void Do() {}
}
public class AAA extends AA {
@Override
public void Do() { System.out.println("实际工作"); }
}
5. 装饰者模式:扩展功能可以组合叠加,互相直接没有干扰。
public interface Phone {
public void operate();
}
public class IPhone1 implement Phone {
@Override
public void operate() { system.out.println("拍照"); }
}
public class IPhone2 implement Phone {
Phone phone;
public IPhone2(Phone phone) {this.phone = phone; }
@Override
public void operate() {
system.out.println("美颜");
phone.operate();
}
}
public class IPhone3 implement Phone {
Phone phone;
public IPhone3(Phone phone) {this.phone = phone; }
@Override
public void operate() {
system.out.println("滤镜");
phone.operate();
}
}
调用:
Phone phone = new IPhone3(new IPhone2(new IPhone1()));
输出:
滤镜
美颜
拍照
6. 代理模式:代理模式分为三种,静态代理,JDK动态代理,CGLIB动态代理。代理模式是Spring中面向切面编程的核心。
6.1 静态代理
public interface Wo {
public void Travel();
}
public class WoImpl implements Wo {
@Override
public void Travel() { Sysyem.out.println("去旅行"); }
}
public class MyProxyImpl implements Wo {
private WoImpl woImpl = null;
public MyProxyImpl(WoImpl woImpl) { this.woImpl = woImpl; }
@Override
public void Travel() {
Sysyem.out.println("订去返机票");
Sysyem.out.println("打车去机场");
woImpl.Travel();
}
}
*要点:所谓代理就是在你执行某个动作前后,帮你做一些准备动作和收尾动作。静态代理类只能用于一个类的代理,扩展性差。
6.2 JDK动态代理
public class MyProxyImpl {
public static Wo getMyProxyByJDK(Wo wo) {
Wo myProxy = (Wo) Proxy.newProxyInstance(wo.getClass().getClassLoader(),
wo.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("订去返机票");
System.out.println("打车去机场");
Object obj = method.invoke(wo, args);
return obj;
}
});
return myProxy ;
}
}
7. 模板方法模式
先讲个小故事。大家在日常生活里,有空的时候都会自己做点饭吃。那么今天我想做个炒饭吃,明天我想做个炒面吃。其实炒饭和炒面基本上做法是一样的,只是主要食材不一样。
那么我只要能把炒饭做好了,炒面自然不在话下。
public abstract class ChaoTemplate {
public void Do() {
DaoYou();
KaiHuo();
ReYou();
DaoShiCai();
FanChao();
GuanHuo();
}
public void DaoYou() { System.out.println("倒油"); }
public void KaiHuo() { System.out.println("开火"); }
public void ReYou() { System.out.println("热油"); }
public abstract void DaoShiCai();
public void FanChao() {System.out.println("翻炒"); }
public void GuanHuo() { System.out.println("关火"); }
}
public class ChaoFan extends ChaoTemplate {
@Override
public void DaoShiCai() { System.out.println(" 倒米饭"); }
}
public class ChaoMian extends ChaoTemplate {
@Override
public void DaoShiCai() { System.out.println("倒面条"); }
}
public class Test {
public static main(String[] args) {
ChaoFan chaoFan = new ChaoFan();
ChaoMian chaoMian = new ChaoMian();
chaoFan.Do();
chaoMian.Do();
}
}
*要点:其实就是将相同的动作提取出来放到父类里去实现,子类实现各自的不同工作。减少重复劳动。
8. 策略模式:定义一系列方法簇,具体实现类可以自己选择组合不同方法簇里的方法
public interface IMoveable {
public void move();
}
public class OneStepOneMove implement IMoveable{
@Override
public void move() { system.out.println("一步一步走"); }
}
public class SpaceStepMove implement IMoveable{
@Override
public void move() { system.out.println("太空步"); }
}
public interface Biteable {
public void bite();
}
public class OneStepOneBite implement Biteable{
@Override
public void bite() { system.out.println("一下一下咬"); }
}
public class HeadBite implement Biteable{
@Override
public void bite() { system.out.println("头撞"); }
}
public abstract class Zombie {
public Zombie(IMoveable moveable, IBiteable biteable) {
this.moveable = moveable;
this.biteable = biteable;
}
private IMoveable moveable;
private IBiteable biteable;
public abstract void display();
public void move() { moveable.move(); }
public void bite() { biteable.bite(); }
}
public PuTongZombie extend Zombie {
public PuTongZombie(IMoveable moveable, IBiteable biteable) {
super(moveable, biteable);
}
@Override
public void display() { system.out.println("我是普通僵尸"); }
}
public BigZombie extend Zombie {
public PuTongZBigZombieMoveable moveable, IBiteable biteable) {
super(moveable, biteable);
}
@Override
public void display() { system.out.println("我是大头僵尸"); }
}
public class Test {
public static void main(String[] args) {
Zombie putongZombie = new PuTongZombie(new OneStepOneBite(), new OneStepOneBite());
Zombie bigZombie = new BigZombie(new HeadBite(), new SpaceStepBite());
putongZombie.display();
putongZombie.move();
putongZombie.bite();
bigZombie.display();
bigZombie.move();
bigZombie.bite();
}
}
输出:
我是普通僵尸
一步一步走
一下一下咬
我是大头僵尸
太空步
头撞
欢迎看官儿们留言补充和指正,谢谢下次见!