设计模式:单例、工厂、适配器、责任链、观察者等等

什么是设计模式

设计模式是一种解决方案,用于解决在软件设计中普遍存在的问题,是前辈们对之前软件设计中反复出现的问题的一个总结

我们学设计模式,是为了学习如果合理的组织我们的代码,如何解耦,如何真正的达到对修改封闭扩展开放的效果,而不是去背诵那些类的集成模式,然后自己记不住,回过头感觉设计模式把代码搞的太复杂,搞反设计模式

常见的模式

单例模式(创建型模式)

  • 作用
    用于保证一个类有且仅有一个实例,用来解决一个全局使用的类频繁的创建和销毁,从而节约系统资源。
    • 懒汉型,线程不安全
      此方法线程不安全,因此在严格意义上来说不能算作单例模式。
public callss singleton {
    private static Singleton instance;
    private Singletone(){}
    public static singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }

}
  • 懒汉型,线程安全
    该方法通过synchronized关键字保证线程安全,但效率会有所降低。
public class Singleton {
    private static Singleton instance;
    private Singleton(){}
    public static synchronized Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}
  • 饿汉型
    饿汉型没有使用Synchronize关键字,因而效率较高,但是没有达到lazy loading的效果
public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton getInstance() {
        return instance;
    }
}
  • 双检锁/双重检验锁
    双锁机制保证了线程安全且在大多数情况下保持高性能,达到了lazy loading效果。
public class Singleton {
   private volatile static Singleton singleton;
   private Singleton(){}
   public static Singleton getSingleton() {
       if (singleton == null) {
           synchronized (Singleton.class){
               singleton = new Singleton();
           }
       }
       return singleton;
   }

}
  • 静态内部类
public class Singleton {
    private static class SingletonHolder {
    private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton(){}
    public static final Singleton getInstance() {
      return SingletonHolder.INSTANCE;
    }
}
  • 枚举
pubilc enum Singleton{
    INSTANCE;
    public void whateverMethod(){
    }
}

工厂模式(创建型模式)

  • 作用
    用于创建复制对象,明确地计划不同条件下创建不同的实例。
  • 优点
    使代码结构清晰,能够更加有效的进行封装。对调用者屏蔽具体的产品实现。降低耦合度。
  • 缺点
    对于简单对象,使用工厂模式会增加其系统的复杂度。
//产品类接口
interface IProduct {  
    public void productMethod();  
}  

//产品类实体
class Product implements IProduct {  
    public void productMethod() {  
        System.out.println("产品");  
    }  
}  

//工厂类接口
interface IFactory {  
    public IProduct createProduct();  
}  

//工厂类实体
class Factory implements IFactory {  
    public IProduct createProduct() {  
        return new Product();  
    }  
}  

//用户
public class Client {  
    public static void main(String[] args) {  
        IFactory factory = new Factory();  
        IProduct prodect = factory.createProduct();  
        prodect.productMethod();  
    }  
}  

代理模式(结构型模式)

  • 作用
    为其他对象提供一种代理来控制对某个对象的访问,在一些已有的方法在使用的时候需要对已有的方法进行拓展,可用此模式来完成。
  • 优点
    职责清晰,有更高的拓展性,更加的智能。
  • 缺点
    实现代理模式增加了工作量,且通过代理模式访问会使性能降低。
//源对象接口
public interface Sourceable {  
    public void method();  
}

//源对象实现类
public class Source implements Sourceable {  

    @Override  
    public void method() {  
        System.out.println("the original method!");  
    }  
}

//代理类
public class Proxy implements Sourceable {  

    private Source source;  
    public Proxy(){
        this.source = new Source();  
    }

    @Override  
    public void method() {  
        if (source == null){
            source = new Source ();
        } 
        source.method();  
    }   
} 

装饰器模式(结构性模式)

  • 作用
    通过一个更加灵活的方式动态的为某一个对象添加一些额外的职责
  • 优点
    可以再不添加很多子类的情况下拓展类,且装饰类和被装饰类可以独立方法。
  • 缺点
    多层装饰较为复杂
//需被拓展的类的接口
public interface Shape {
   void draw();
}

//需被拓展的类
public class Rectangle implements Shape {
   @Override
   public void draw() {
      System.out.println("Shape: Rectangle");
   }
}

//创建实现了 Shape 接口的抽象装饰类。
public abstract class ShapeDecorator implements Shape {
   protected Shape decoratedShape;

   public ShapeDecorator(Shape decoratedShape){
      this.decoratedShape = decoratedShape;
   }

   public void draw(){
      decoratedShape.draw();
   }    
}

//扩展了 ShapeDecorator 类的实体装饰类
public class RedShapeDecorator extends ShapeDecorator {
   public RedShapeDecorator(Shape decoratedShape) {
      super(decoratedShape);        
   }

   @Override
   public void draw() {
      decoratedShape.draw();           
      setRedBorder(decoratedShape);
   }

   private void setRedBorder(Shape decoratedShape){
      System.out.println("Border Color: Red");
   }
}

观察者模式(行为型模式)

  • 作用
    用于在易用和低耦合下实现一个对象改变给其他对象通知的功能。
  • 优点
    观察者和被观察抽象耦合的。
  • 缺点
    当观察者较多时,完成通知耗时较长,观察者和被观察是循环依赖时,会导致循环调用,可能会使导致系统崩溃
//创建被观察者
public class Subject {

   private List<Observer> observers 
      = new ArrayList<Observer>();
   private int state;

   public int getState() {
      return state;
   }

   public void setState(int state) {
      this.state = state;
      notifyAllObservers();
   }

   public void attach(Observer observer){
      observers.add(observer);      
   }

  public void notifyAllObservers(){
      for (Observer observer : observers) {
         observer.update();
      }
   }

//创建观察者抽象类
public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}

//观察者实现类1
public class BinaryObserver extends Observer{

   public BinaryObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }

   @Override
   public void update() {
      System.out.println( "Binary String: " 
      + Integer.toBinaryString( subject.getState() ) ); 
   }
}

//观察者实现类2
public class OctalObserver extends Observer{

   public OctalObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }

   @Override
   public void update() {
     System.out.println( "Octal String: " 
     + Integer.toOctalString( subject.getState() ) ); 
   }
}

//改变被观察者状态
public class ObserverPatternDemo {
   public static void main(String[] args) {
      Subject subject = new Subject();

      new OctalObserver(subject);
      new BinaryObserver(subject);

      System.out.println("First state change: 15"); 
      subject.setState(15);
      System.out.println("Second state change: 10");    
      subject.setState(10);
   }
}

设计模式的六大原则

1、开闭原则

开闭原则:实现热插拔,提高扩展性。

开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

2、里氏代换原则

里氏代换原则:实现抽象的规范,实现子父类互相替换

里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

3、依赖倒转原则

这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。

4、接口隔离原则

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。

5、迪米特法则

迪米特法则,又称最少知道原则

最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。

6、合成复用原则

合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值