zoukankan      html  css  js  c++  java
  • Java之常用设计模式(精简)

    话不多说奔主题,精神抖擞就是干!

    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();

      }

    }

    输出:

    我是普通僵尸

    一步一步走

    一下一下咬

    我是大头僵尸

    太空步

    头撞

    欢迎看官儿们留言补充和指正,谢谢下次见!

  • 相关阅读:
    哲学家进餐
    文件系统
    文件读写原理(转)
    数据库join种类
    http与https区别
    数字证书(转)
    B. Rebranding
    扩展欧几里德算法、证明及其应用
    CodeForces 7C Line
    UVALive 7147 World Cup
  • 原文地址:https://www.cnblogs.com/chenyixun/p/13140307.html
Copyright © 2011-2022 走看看