zoukankan      html  css  js  c++  java
  • 设计模式系列

    单例模式

    懒汉式,线程不安全。

    除非是单线程程序,否则不推荐使用。

    public class Singleton {  
        private static Singleton instance;  
        private Singleton (){}  
      
        public static Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
        }  
    }

    饿汉式,线程安全

    当程序总是使用这个类的实例时,或者在资源和时间方面创建实例的成本不太大时,可以使用它。
    可能导致资源浪费。因为类的实例总是被创建的,不管它是否必需。在创建实例时也会浪费CPU时间。
    无法处理异常。

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

    静态块,线程安全

    对象是在静态块中创建的,这样我们就可以访问它的创建,比如异常处理。同样地,对象也是在类加载时创建的。
    当在创建具有紧急初始化的对象时可能出现异常时,可以使用它。可能导致资源浪费。因为类的实例总是被创建的,不管它是否必需。

    public class Singleton  
    { 
      // public instance 
      public static Singleton instance; 
      
      private Singleton()  
      { 
        // private constructor 
      } 
      
      { 
        // static block to initialize instance 
        instance = new Singleton(); 
      } 
    }

    同步方式,线程安全

    会导致性能下降

    public class Singleton  
    { 
      // private instance, so that it can be 
      // accessed by only by getInstance() method 
      private static Singleton instance; 
      
      private Singleton()  
      { 
        // private constructor 
      } 
      
     //synchronized method to control simultaneous access 
      synchronized public static Singleton getInstance()  
      { 
        if (instance == null)  
        { 
          // if instance is null, initialize 
          instance = new Singleton(); 
        } 
        return instance; 
      } 
    } 

    双检方式,线程安全

    克服了同步代码的开销问题。延迟初始化,可以用于高性能的多线程应用。

    public class Singleton  
    { 
      // private instance, so that it can be 
      // accessed by only by getInstance() method 
      private static Singleton instance; 
      
      private Singleton()  
      { 
        // private constructor 
      } 
      
      public static Singleton getInstance() 
      { 
        if (instance == null)  
        { 
          //synchronized block to remove overhead 
          synchronized (Singleton.class) 
          { 
            if(instance==null) 
            { 
              // if instance is null, initialize 
              instance = new Singleton(); 
            } 
            
          } 
        } 
        return instance; 
      } 
    } 

    内部静态类方案,优方案

    加载单例类时,不会加载内部类,因此在加载类时不会创建对象。只有在调用getInstance()方法时才创建内部类。它是懒惰的初始化。
    这是最广泛使用的方法,因为它不使用同步,性能更好。

    public class Singleton  
    { 
      
      private Singleton()  
      { 
        // private constructor 
      } 
      
      // Inner class to provide instance of class 
      private static class BillPughSingleton 
      { 
        private static final Singleton INSTANCE = new Singleton(); 
      } 
      
      public static Singleton getInstance()  
      { 
        return BillPughSingleton.INSTANCE; 
      } 
    } 

    枚举,优方案

    自动支持序列化机制,绝对防止多次实例化。这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。

    public enum Singleton {  
        INSTANCE;  
        public void whateverMethod() {  
        }  
    }

    工厂方法

    是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
    在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

    //定义车类
    public enum CarType {
        SMALL, SEDAN, LUXURY
    }
    
    //车的基类
    public abstract class Car {
     
        public Car(CarType model) {
            this.model = model;
            arrangeParts();
        }
     
        private void arrangeParts() {
            // Do one time processing here
        }
     
        // Do subclass level processing in this method
        protected abstract void construct();
     
        private CarType model = null;
     
        public CarType getModel() {
            return model;
        }
     
        public void setModel(CarType model) {
            this.model = model;
        }
    }
    //豪华车
    public class LuxuryCar extends Car {
     
        LuxuryCar() {
            super(CarType.LUXURY);
            construct();
        }
     
        @Override
        protected void construct() {
            System.out.println("Building luxury car");
            // add accessories
        }
    }
    
    public class SmallCar extends Car {
     
        SmallCar() {
            super(CarType.SMALL);
            construct();
        }
     
        @Override
        protected void construct() {
            System.out.println("Building small car");
            // add accessories
        }
    }
    
    public class SedanCar extends Car {
     
        SedanCar() {
            super(CarType.SEDAN);
            construct();
        }
     
        @Override
        protected void construct() {
            System.out.println("Building sedan car");
            // add accessories
        }
    }
    
    public class CarFactory {
        public static Car buildCar(CarType model) {
            Car car = null;
            switch (model) {
            case SMALL:
                car = new SmallCar();
                break;
     
            case SEDAN:
                car = new SedanCar();
                break;
     
            case LUXURY:
                car = new LuxuryCar();
                break;
     
            default:
                // throw some exception
                break;
            }
            return car;
        }
    }
    
    public class TestFactoryPattern {
        public static void main(String[] args) {
            System.out.println(CarFactory.buildCar(CarType.SMALL));
            System.out.println(CarFactory.buildCar(CarType.SEDAN));
            System.out.println(CarFactory.buildCar(CarType.LUXURY));
        }
    }

    抽象工厂

    围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
    在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
    我们重用上一节的CarType

    public abstract class Car {
    
      public Car(CarType model, Location location){
        this.model = model;
        this.location = location;
      }
    
      protected abstract void construct();
    
      private CarType model = null;
      private Location location = null;
    
      //getters and setters
    
      @Override
      public String toString() {
        return "Model- "+model + " built in "+location;
      }
    }
    
    public enum Location {
      DEFAULT, USA, ASIA
    }
    
    public class LuxuryCar extends Car
    {
      public LuxuryCar(Location location)
      {
        super(CarType.LUXURY, location);
        construct();
      }
    
      @Override
      protected void construct() {
        System.out.println("Building luxury car");
        //add accessories
      }
    }
    
    public class AsiaCarFactory
    {
      public static Car buildCar(CarType model)
      {
        Car car = null;
        switch (model)
        {
          case SMALL:
          car = new SmallCar(Location.ASIA);
          break;
    
          case SEDAN:
          car = new SedanCar(Location.ASIA);
          break;
    
          case LUXURY:
          car = new LuxuryCar(Location.ASIA);
          break;
    
          default:
          //throw some exception
          break;
        }
        return car;
      }
    }
    
    public class DefaultCarFactory
    {
      public static Car buildCar(CarType model)
      {
        Car car = null;
        switch (model)
        {
          case SMALL:
          car = new SmallCar(Location.DEFAULT);
          break;
    
          case SEDAN:
          car = new SedanCar(Location.DEFAULT);
          break;
    
          case LUXURY:
          car = new LuxuryCar(Location.DEFAULT);
          break;
    
          default:
          //throw some exception
          break;
        }
        return car;
      }
    }
    
    public class USACarFactory
    {
      public static Car buildCar(CarType model)
      {
        Car car = null;
        switch (model)
        {
          case SMALL:
          car = new SmallCar(Location.USA);
          break;
    
          case SEDAN:
          car = new SedanCar(Location.USA);
          break;
    
          case LUXURY:
          car = new LuxuryCar(Location.USA);
          break;
    
          default:
          //throw some exception
          break;
        }
      return car;
      }
    }
    
    public class CarFactory
    {
      private CarFactory() {
        //Prevent instantiation
      }
     
      public static Car buildCar(CarType type,Location location)
      {
        Car car = null;
        //Use location specific car factory
        switch(location)
        {
          case USA:
            car = USACarFactory.buildCar(type);
            break;
          case ASIA:
            car = AsiaCarFactory.buildCar(type);
            break;
          default:
            car = DefaultCarFactory.buildCar(type);
        }
      return car;
      }
    }
    
    public class TestFactoryPattern
    {
      public static void main(String[] args)
      {
        System.out.println(CarFactory.buildCar(CarType.SMALL,Location.USA));
        System.out.println(CarFactory.buildCar(CarType.SEDAN,Location.USA));
        System.out.println(CarFactory.buildCar(CarType.LUXURY,Location.ASIA));
      }
    }

    这两个工厂模式的代码还有很多switch,仅仅是演示而已

    建造者模式

    建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
    一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

    interface HousePlan 
    { 
        public void setBasement(String basement); 
    
        public void setStructure(String structure); 
    
        public void setRoof(String roof); 
    
        public void setInterior(String interior); 
    } 
    
    class House implements HousePlan 
    { 
    
        private String basement; 
        private String structure; 
        private String roof; 
        private String interior; 
    
        public void setBasement(String basement) 
        { 
            this.basement = basement; 
        } 
    
        public void setStructure(String structure) 
        { 
            this.structure = structure; 
        } 
    
        public void setRoof(String roof) 
        { 
            this.roof = roof; 
        } 
    
        public void setInterior(String interior) 
        { 
            this.interior = interior; 
        } 
    
    } 
    
    
    interface HouseBuilder 
    { 
    
        public void buildBasement(); 
    
        public void buildStructure(); 
    
        public void bulidRoof(); 
    
        public void buildInterior(); 
    
        public House getHouse(); 
    } 
    
    class IglooHouseBuilder implements HouseBuilder 
    { 
        private House house; 
    
        public IglooHouseBuilder() 
        { 
            this.house = new House(); 
        } 
    
        public void buildBasement() 
        { 
            house.setBasement("Ice Bars"); 
        } 
    
        public void buildStructure() 
        { 
            house.setStructure("Ice Blocks"); 
        } 
    
        public void buildInterior() 
        { 
            house.setInterior("Ice Carvings"); 
        } 
    
        public void bulidRoof() 
        { 
            house.setRoof("Ice Dome"); 
        } 
    
        public House getHouse() 
        { 
            return this.house; 
        } 
    } 
    
    class TipiHouseBuilder implements HouseBuilder 
    { 
        private House house; 
    
        public TipiHouseBuilder() 
        { 
            this.house = new House(); 
        } 
    
        public void buildBasement() 
        { 
            house.setBasement("Wooden Poles"); 
        } 
    
        public void buildStructure() 
        { 
            house.setStructure("Wood and Ice"); 
        } 
    
        public void buildInterior() 
        { 
            house.setInterior("Fire Wood"); 
        } 
    
        public void bulidRoof() 
        { 
            house.setRoof("Wood, caribou and seal skins"); 
        } 
    
        public House getHouse() 
        { 
            return this.house; 
        } 
    
    } 
    
    class CivilEngineer 
    { 
    
        private HouseBuilder houseBuilder; 
    
        public CivilEngineer(HouseBuilder houseBuilder) 
        { 
            this.houseBuilder = houseBuilder; 
        } 
    
        public House getHouse() 
        { 
            return this.houseBuilder.getHouse(); 
        } 
    
        public void constructHouse() 
        { 
            this.houseBuilder.buildBasement(); 
            this.houseBuilder.buildStructure(); 
            this.houseBuilder.bulidRoof(); 
            this.houseBuilder.buildInterior(); 
        } 
    } 
    
    class Builder 
    { 
        public static void main(String[] args) 
        { 
            HouseBuilder iglooBuilder = new IglooHouseBuilder(); 
            CivilEngineer engineer = new CivilEngineer(iglooBuilder); 
    
            engineer.constructHouse(); 
    
            House house = engineer.getHouse(); 
    
            System.out.println("Builder constructed: "+ house); 
        } 
    } 

    以上是做分部建造,还可以避免new product的过多参数,比如:

    public User (String firstName, String lastName, int age, String phone){ ... }
    public User (String firstName, String lastName, String phone, String address){ ... }
    public User (String firstName, String lastName, int age){ ... }
    public User (String firstName, String lastName){ ... }

    如果再多十几个属性怎么办?

    public class User 
    {
        //All final attributes
        private final String firstName; // required
        private final String lastName; // required
        private final int age; // optional
        private final String phone; // optional
        private final String address; // optional
     
        private User(UserBuilder builder) {
            this.firstName = builder.firstName;
            this.lastName = builder.lastName;
            this.age = builder.age;
            this.phone = builder.phone;
            this.address = builder.address;
        }
     
        //All getter, and NO setter to provde immutability
        public String getFirstName() {
            return firstName;
        }
        public String getLastName() {
            return lastName;
        }
        public int getAge() {
            return age;
        }
        public String getPhone() {
            return phone;
        }
        public String getAddress() {
            return address;
        }
     
        @Override
        public String toString() {
            return "User: "+this.firstName+", "+this.lastName+", "+this.age+", "+this.phone+", "+this.address;
        }
     
        public static class UserBuilder 
        {
            private final String firstName;
            private final String lastName;
            private int age;
            private String phone;
            private String address;
     
            public UserBuilder(String firstName, String lastName) {
                this.firstName = firstName;
                this.lastName = lastName;
            }
            public UserBuilder age(int age) {
                this.age = age;
                return this;
            }
            public UserBuilder phone(String phone) {
                this.phone = phone;
                return this;
            }
            public UserBuilder address(String address) {
                this.address = address;
                return this;
            }
            //Return the finally consrcuted User object
            public User build() {
                User user =  new User(this);
                validateUserObject(user);
                return user;
            }
            private void validateUserObject(User user) {
                //Do some basic validations to check 
                //if user object does not break any assumption of system
            }
        }
    }
    
    public static void main(String[] args) {
        User user1 = new User.UserBuilder("Lokesh", "Gupta")
        .age(30)
        .phone("1234567")
        .address("Fake address 1234")
        .build();
     
        System.out.println(user1);
     
        User user2 = new User.UserBuilder("Jack", "Reacher")
        .age(40)
        .phone("5655")
        //no address
        .build();
     
        System.out.println(user2);
     
        User user3 = new User.UserBuilder("Super", "Man")
        //No age
        //No phone
        //no address
        .build();
     
        System.out.println(user3);
    }

    原型模式

    原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。原型设计模式用于应用程序需要创建一个类的多个实例的场景中,这些实例几乎具有相同的状态或差别非常小。
    在这个设计模式中,实际对象的一个实例(即prototype)是在启动时创建的,然后每当需要新实例时,就克隆这个原型以拥有另一个实例。这种模式的主要优点是具有最小的实例创建过程
    这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

    public interface PrototypeCapable extends Cloneable
    {
        public PrototypeCapable clone() throws CloneNotSupportedException;
    }
    
    public class Movie implements PrototypeCapable
    {
        private String name = null;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        @Override
        public Movie clone() throws CloneNotSupportedException {
            System.out.println("Cloning Movie object..");
            return (Movie) super.clone();
        }
        @Override
        public String toString() {
            return "Movie";
        }
    }
     
    public class Album implements PrototypeCapable
    {
        private String name = null;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        @Override
        public Album clone() throws CloneNotSupportedException {
            System.out.println("Cloning Album object..");
            return (Album) super.clone();
        }
        @Override
        public String toString() {
            return "Album";
        }
    }
     
    public class Show implements PrototypeCapable
    {
        private String name = null;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        @Override
        public Show clone() throws CloneNotSupportedException {
            System.out.println("Cloning Show object..");
            return (Show) super.clone();
        }
        @Override
        public String toString() {
            return "Show";
        }
    }
    
    public class PrototypeCache
    {
        public static class ModelType
        {
            public static final String MOVIE = "movie";
            public static final String ALBUM = "album";
            public static final String SHOW = "show";
        }
        private static java.util.Map<String , PrototypeCapable> prototypes = new java.util.HashMap<String , PrototypeCapable>();
     
        static
        {
            prototypes.put(ModelType.MOVIE, new Movie());
            prototypes.put(ModelType.ALBUM, new Album());
            prototypes.put(ModelType.SHOW, new Show());
        }
     
        public static PrototypeCapable getInstance(final String s) throws CloneNotSupportedException {
            return ((PrototypeCapable) prototypes.get(s)).clone();
        }
    }
    TestPrototypePattern
    public class TestPrototypePattern
    {
        public static void main(String[] args)
        {
            try
            {
                String moviePrototype  = PrototypeCache.getInstance(ModelType.MOVIE).toString();
                System.out.println(moviePrototype);
     
                String albumPrototype  = PrototypeCache.getInstance(ModelType.ALBUM).toString();
                System.out.println(albumPrototype);
     
                String showPrototype  = PrototypeCache.getInstance(ModelType.SHOW).toString();
                System.out.println(showPrototype);
     
            }
            catch (CloneNotSupportedException e)
            {
                e.printStackTrace();
            }
        }
    }
    Singleton
  • 相关阅读:
    C#读写者线程(用AutoResetEvent实现同步)(转载)
    详解大端模式和小端模式(转载)
    C/C++程序员应聘试题剖析(转载)
    strcpy和memcpy的区别(转载)
    基于mini2440的Qt移植
    分布式服务以及跨平台开发清单(全栈之路)
    软件开发模式对比(瀑布、迭代、螺旋、敏捷)
    大数开方 ACM-ICPC 2018 焦作赛区网络预赛 J. Participate in E-sports
    啊啊
    括号问题
  • 原文地址:https://www.cnblogs.com/starcrm/p/12572620.html
Copyright © 2011-2022 走看看