设计模式学习笔记

1.单例模式:保证类的对象在内存中有且仅有一份。Spring中管理的对象都有对应的生命周期,对于scope配置为singleton的bean都是单例的,这也是Spring管理的对象的默认的生命周期。
实现1--饿汉式

public class Singleton {
  private static final Singleton single = new Singleton();
  
private Singleton() {   }
  
public static final Singleton getInstance() {     return single;   } }

实现2--懒汉式

  • 错误示例:这种方式的实现虽然延迟加载减小了内存占用,但在多线程时无法保证线程安全性,假设第一个线程执行到步骤(2)时,但是尚未完成对象的初始化过程,第二个线程执行到步骤(1)则if返回的结果为true,会导致内存中存在不唯一的single对象。
public class Singleton {
    private static Singleton single = null;
private Singleton(){ }
public static Singleton getInstance(){ if(single == null){ // (1) single = new Singleton(); //(2) } return single; } }    
  •  改进方式1:使getInstance()方法成为同步方法或者使用同步代码块。但是这样方法的效率就会很低下。
public class Singleton {
    private static Singleton single = null;
    
    private Singleton(){    
    }
    
    public static Singleton getInstance() {
        synchronized (Singleton.class) {
            if (single == null) {
                single = new Singleton();
            }
            return single;
        }
    }
}
  •  改进方式2:DCL-双重检测锁。双重检测锁在方式1的基础上提高了效率,只在第一次创建的时候会加锁,但是需要注意的是如果single对象没有使用 volatile关键字修饰依然是错误的,详细分析见博客:http://cmsblogs.com/?p=2161&from=timeline&isappinstalled=0
public class Singleton {
    private volatile static Singleton single = null;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (single == null) {
            synchronized (Singleton.class) {
                if (single == null) {
                    single = new Singleton();
                }
            }
        }
        return single;
    }
}

 2 . 模板模式:一般用于多个子类有共同的方法,父类里面定义好了方法的调用逻辑。例如Junit里面的@Test方法就使用了模板方法


  /**
  * 定义一个是抽象类作为模板方法类,子类继承这个类 ,overide需要使用的方法(如果定义成接口,则实现类需要实现所有方法)
  * 例如这里templateMethod方法按顺序执行三个方法,实现类也会按顺序执行这个方法
  * @author niepei
  */

public abstract class Template {
    
    public abstract void start(); 
    public abstract void process(); 
    public abstract void end(); 

    public void test(){
        this.start();
        this.process();
        this.end();
    }
}


public class SubTemplate extends Template {

    public void start() {
        System.out.println("第一步:start");
    }
    public void end() {
        System.out.println("第三步:end");
    }
    public void process() {
        System.out.println("第二步:process");
    }

    public static void main(String[] args) {
        Template template = new SubTemplate();
        template.test();
    }

}

// 打印结果如下:
  第一步:start
  第二步:process
  第三步:end

 3. 策略模式:策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户,JDK 中的Comparator比较器就采用了策略模式。

// 抽象策略类接口
public interface Strategy {
    // 返回两个操作数的结果
    public int getResult(int a,int b);
}

// 加法策略类
public class StrategyAdd implements Strategy {
    @Override
    public int getResult(int a,int b) {
        return a+b;
    }
}


// 乘法策略类
public class StrategyMultiple implements Strategy {
    @Override
    public int getResult(int a,int b) {
        return a*b;
    }
}

// 策略类的包装类
public class Context {
    private Strategy stragety;
    public Context(Strategy stragety) {
        this.stragety = stragety;
    }
    public int getResult(int a,int b) {
        return stragety.getResult(a,b);
    }
    public static void main(String[] args) {
        int a = 2,b=5;
        Context context;
        context = new Context(new StrategyAdd());
        System.out.println(context.getResult(a, b));
        context = new Context(new StrategyMultiple());
        System.out.println(context.getResult(a,b));
    }

}

4.装饰模式:给一个对象动态增加一些新的功能,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。JDK中的IO流以及mybatis中的query就使用了装饰者设计模式。

public interface IPicture {
    public void showPicture();
}

// 被装饰者
public class Picture implements IPicture{
    @Override
    public void showPicture() {
        System.out.println("this is a pretty picture");
    }
}
// 装饰者
public class PictureDecorator implements IPicture{
    private IPicture picture;
    public PictureDecorator(IPicture picture){
        this.picture = picture;
    }
    @Override
    public void showPicture() {
        System.out.println("the author of this picture is Van Gogh,");
        this.picture.showPicture();
        System.out.println("It's name is sunflower");
    }
    public static void main(String args[]){
        IPicture picture = new Picture();
        IPicture pictureDecorator = new PictureDecorator(picture);
        pictureDecorator.showPicture();
    }
}

// 打印结果如下

  the author of this picture is Van Gogh,
  this is a pretty picture
  It's name is sunflower

5.适配器模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

public class Source {
    public void method2() {
        System.out.println("this is method2");
    }
}

public interface Target {
    public void method1();
}

// 组合方式实现适配器
public class Adapter implements Target {
    private Source source;
    public Adapter(Source source){
        this.source = source;
    }
    @Override
    public void method1() {    
        source.method2();
    }
    public static void main(String[] args){
    Target target = new Adapter(new Source());
        target.method1();
    }
}

7.代理模式:使用一个代理类来代替原先类进行操作。代理分为静态代理(对目标对象进行封装,调用目标对象的方法即可)和动态代理(运行时生成代理对象)。Spring的AOP技术就是基于动态代理实现的。

public interface IGamePlayer {
    public void killMonster();
}

// 目标类--游戏玩家
public class GamePlayer implements IGamePlayer{
    private String name;
    @Override
    public void killMonster() {
        System.out.println(this.name + " is killing monster");
    }
}
// 代理类--游戏代练 public class GamePlayerProxy implements IGamePlayer { private IGamePlayer player; public GamePlayerProxy(IGamePlayer player) { this.player = player; } @Override public void killMonster() { this.player.killMonster(); } //代理类除了完成被代理类的方法,还可以拥有自己的方法 public void getPay() { System.out.println("一共收取费用 150¥"); }
public static void main(String[] args) { IGamePlayer player = new GamePlayer("pepper"); IGamePlayer proxyPlayer = new GamePlayerProxy(player); proxyPlayer.killMonster(); proxyPlayer.upgrade(); } }

8.享元模式:主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。

/**
 * 适用于作共享的一些个对象,他们有一些共有的属性,就拿数据库连接池来说,url、driverClassName、
 * username、password及dbname,这些属性对于每个连接来说都是一样的,所以就适合用享元模式来处理,
 * 建一个工厂类,将上述类似属性作为内部数据,其它的作为外部数据,在方法调用时,当做参数传进来,这样就节省了空间,减少了实例的数量。
 * 
 * 下面的例子是是数据库连接池的代码
 * 通过连接池的管理,实现了数据库连接的共享,不需要每一次都重新创建连接,节省了数据库重新创建的开销,提升了系统的性能
 * @author pepper
 *
 */

public class ConnectionPool {

    private List<Connection> pool;  
    
    /*公有属性*/  
    private String url = "jdbc:mysql://localhost:3306/test";  
    private String username = "root";  
    private String password = "root";  
    private String driverClassName = "com.mysql.jdbc.Driver";  
  
    private int poolSize = 100;   
    @SuppressWarnings("unused")
    private static ConnectionPool instance = null;  
    Connection conn = null;  
  
    /*构造方法,做一些初始化工作*/  
    private ConnectionPool() {  
        pool = new ArrayList<Connection>(poolSize);  
  
        for (int i = 0; i < poolSize; i++) {  
            try {  
                Class.forName(driverClassName);  
                conn = DriverManager.getConnection(url, username, password);  
                pool.add(conn);  
            } catch (ClassNotFoundException e) {  
                e.printStackTrace();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
    /* 返回连接到连接池 */  
    public synchronized void release() {  
        pool.add(conn);  
    }  
  
    /* 返回连接池中的一个数据库连接 */  
    public synchronized Connection getConnection() {  
        if (pool.size() > 0) {  
            Connection conn = pool.get(0);  
            pool.remove(conn);  
            return conn;  
        } else {  
            return null;  
        }  
    }  
    
}

9.工厂方法模式:使用工厂去管理对象的创建,而不是创建者自身。最典型的工厂模式使用者就是Spring,Spring内部的IOC容器就是一个工厂,所有bean的创建、销毁、注入都由这个容器管理。工厂模式分工厂方法模式和抽象工厂模式。它们的区别在于抽象工厂抽象程度更高,把工厂也抽象成了一个接口,这样可以再每添加一个新的对象的时候而不需要修改工厂的代码。

  • 工厂方法模式:
// 抽象产品接口
public
interface Human { public void showSkinColor(); } // 具体的产品类1 public class Human_Black implements Human { @Override public void showSkinColor() { System.out.println("my color is balck"); } } // 具体的产品类2 public class Human_White implements Human { @Override public void showSkinColor() { System.out.println("my color is white"); } } // 抽象工厂接口 public abstract class AbstractHumanFactory { public abstract <T extends Human> T createHuman(Class<T> c); } // 具体的工厂类 public class HumanFactory extends AbstractHumanFactory { @Override public <T extends Human> T createHuman(Class<T> c) { Human human = null; try { human = (Human) Class.forName(c.getName()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return (T) human; } }
  • 抽象工厂模式 :工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,为了解决这个问题就用到了抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
// 抽象产品类A--电车
public abstract class ElectroCar {
    
    public abstract void showCarInfo();

    public void engineBy() {
        System.out.println("this car is engineBy electricity!");
    }
}

// 抽象产品类A的具体产品类1--BYD
public class ElectroCar_BYD extends ElectroCar{

    @Override
    public void showCarInfo() {
        System.out.println("this is BYD Car,it belongs ElectroCar");  
    }
}
// 抽象产品类A的具体产品类2--Tesla
public class ElectroCar_Tesla extends ElectroCar{
    @Override
    public void showCarInfo() {  
        System.out.println("this is Tesla Car,it belongs ElectroCar"); 
    }

}
// 抽象产品类B
public abstract class GasCar {

    public abstract void showCarInfo();

    public void engineBy() {
        System.out.println("this car is engineBy Gasoline!");
    }
}
// 抽象产品类B的具体产品类1--Benz
public class GasCar_Benz extends GasCar{

    @Override
    public void showCarInfo() {
        
        System.out.println("this is Benz Car,it belongs GasCar");
        
    }
 
}
// 抽象产品类B的具体产品类2--BMW
public class GasCar_BMW extends GasCar {

    @Override
    public void showCarInfo() {

        System.out.println("this is BMW Car,it belongs GasCar");

    }

}

// 抽象工厂类
public abstract class AbstractCarFactory {

    public abstract GasCar createGasCar();
    
    public abstract ElectroCar createElectroCar();
}

// 具体工厂类1--生产B1和A2
public class CarFactory1 extends AbstractCarFactory {

    @Override
    public GasCar createGasCar() {

        return new GasCar_Benz();
    }

    @Override
    public ElectroCar createElectroCar() {

        return new ElectroCar_Tesla();
    }

}
// 具体工厂类2--生产B2和A1
public class CarFactory2 extends AbstractCarFactory{

    @Override
    public GasCar createGasCar() {
        
        return new GasCar_BMW();
    }

    @Override
    public ElectroCar createElectroCar() {
        
        return new ElectroCar_BYD();
    }
    
}

public class Client {
    public static void main(String[] args) {
        AbstractCarFactory carFactory1 = new CarFactory1();
        carFactory1.createGasCar().showCarInfo();
        carFactory1.createElectroCar().showCarInfo();

        AbstractCarFactory carFactory2 = new CarFactory2();
        carFactory2.createGasCar().showCarInfo();
        carFactory2.createElectroCar().showCarInfo();
    }
}

参考博客:http://www.importnew.com/24128.html

原文地址:https://www.cnblogs.com/pepper7/p/7150908.html