zoukankan      html  css  js  c++  java
  • 设计模式学习笔记

    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

  • 相关阅读:
    javascript专业八级测试答案整理
    HTML中的attribute和property
    Ajax的原理和应用
    jQuery提交form表单
    使用JavaScript和Canvas实现下雪动画效果
    JavaScript经典代码总结
    从HTML5移动应用现状谈发展趋势
    前端单元测试总结及测试工具介绍
    Web缓存基础:术语、HTTP报头和缓存策略
    为IIS Express添加MIME映射
  • 原文地址:https://www.cnblogs.com/pepper7/p/7150908.html
Copyright © 2011-2022 走看看