Java设计模式

1.单例模式 实现

懒汉式

public class Singleton {  
   /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */  
   private static Singleton instance = null;  
 
   /* 私有构造方法,防止被实例化 */  
   private Singleton() {}  
 
   /* 1:懒汉式,静态工程方法,创建实例 */  
   public static Singleton getInstance() {  
       if (instance == null) {  
           instance = new Singleton();  
      }  
       return instance;  
  }  
}  
//优点:延迟加载(需要的时候才去加载),适合单线程操作
//缺点: 线程不安全,在多线程中很容易出现不同步的情况,如在数据库对象进行的频繁读写操作时

双重线程检查模式

public class SingletonInner {  
   private static volatile SingletonInner sInst = null;  //这里添加了 volatile 可见性 有序性
   private SingletonInner() {}  
 
   public static SingletonInner getInstance() {  
       SingletonInner inst = sInst;  // <<< 在这里创建临时变量
       if (inst == null) {
           synchronized (SingletonInner.class) {
               inst = sInst;
               if (inst == null) {
                   inst = new SingletonInner();
                   sInst = inst;
              }
          }
      }
       return inst;  // <<< 注意这里返回的是临时变量
  }
   protected void method() {  
       System.out.println("SingletonInner");  
  }  
}  
//优点:延迟加载,线程安全
//缺点: 写法复杂,不简洁

内部类的实现

public class SingletonInner {  
   /**
    * 内部类实现单例模式
    * 延迟加载,减少内存开销  
    */  
   private static class SingletonHolder {  
       private static SingletonInner instance = new SingletonInner();  
  }  
 
   /**
    * 私有的构造函数
    */  
   private SingletonInner() {}  
 
   public static SingletonInner getInstance() {  
       return SingletonHolder.instance;  
  }  
 
   protected void method() {  
       System.out.println("SingletonInner");  
  }  
}  
//优点:延迟加载,线程安全(java中class加载时互斥的),也减少了内存消耗,推荐使用内部类方式。

Num2:工厂模式

简单工厂模式:该模式对对象创建管理方式最为简单,因为其仅仅简单的对不同类对象的创建进行了一层薄薄的封装。该模式通过向工厂传递类型来指定要创建的对象,

public interface Phone {
   void make();
}
public class MiPhone implements Phone {
   public MiPhone() {
       this.make();
  }
   @Override
   public void make() {
       // TODO Auto-generated method stub
       System.out.println("make xiaomi phone!");
  }
}
public class IPhone implements Phone {
   public IPhone() {
       this.make();
  }
   @Override
   public void make() {
       // TODO Auto-generated method stub
       System.out.println("make iphone!");
  }
}
public class PhoneFactory {
   public Phone makePhone(String phoneType) {
       if(phoneType.equalsIgnoreCase("MiPhone")){
           return new MiPhone();
      }
       else if(phoneType.equalsIgnoreCase("iPhone")) {
           return new IPhone();
      }
       return null;
  }
}
//测试类
public class Demo {
   public static void main(String[] arg) {
       PhoneFactory factory = new PhoneFactory();
       Phone miPhone = factory.makePhone("MiPhone");            // make xiaomi phone!
       IPhone iPhone = (IPhone)factory.makePhone("iPhone");    // make iphone!
  }
}

工厂方法模式:也就是定义一个抽象工厂,其定义了产品的生产接口,但不负责具体的产品,将生产任务交给不同的派生类工厂。这样不用通过指定类型来创建对象了。


public interface AbstractFactory {
   Phone makePhone();
}

public class XiaoMiFactory implements AbstractFactory{
   @Override
   public Phone makePhone() {
       return new MiPhone();
  }
}

public class AppleFactory implements AbstractFactory {
   @Override
   public Phone makePhone() {
       return new IPhone();
  }
}
//测试类
public class Demo {
   public static void main(String[] arg) {
       AbstractFactory miFactory = new XiaoMiFactory();
       AbstractFactory appleFactory = new AppleFactory();
       miFactory.makePhone();            // make xiaomi phone!
       appleFactory.makePhone();        // make iphone!
  }
}

抽象工厂模式:抽象工厂模式通过在AbstarctFactory中增加创建产品的接口,并在具体子工厂中实现新加产品的创建,当然前提是子工厂支持生产该产品。否则继承的这个接口可以什么也不干。

public interface PC {
   void make();
}
public class MiPC implements PC {
   public MiPC() {
       this.make();
  }
   @Override
   public void make() {
       // TODO Auto-generated method stub
       System.out.println("make xiaomi PC!");
  }
}
public class MAC implements PC {
   public MAC() {
       this.make();
  }
   @Override
   public void make() {
       // TODO Auto-generated method stub
       System.out.println("make MAC!");
  }
}

public interface AbstractFactory {
   Phone makePhone();
   PC makePC();
}

public class XiaoMiFactory implements AbstractFactory{
   @Override
   public Phone makePhone() {
       return new MiPhone();
  }
   @Override
   public PC makePC() {
       return new MiPC();
  }
}
public class AppleFactory implements AbstractFactory {
   @Override
   public Phone makePhone() {
       return new IPhone();
  }
   @Override
   public PC makePC() {
       return new MAC();
  }
}  //测试类
public class Demo {
   public static void main(String[] arg) {
       AbstractFactory miFactory = new XiaoMiFactory();
       AbstractFactory appleFactory = new AppleFactory();
       miFactory.makePhone();            // make xiaomi phone!
       miFactory.makePC();                // make xiaomi PC!
       appleFactory.makePhone();        // make iphone!
       appleFactory.makePC();            // make MAC!
  }
}

Num3:模板方法模式(Template Method)

是指:一个抽象类中,有一个主方法,再定义1...n个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承该抽象类,重写抽象方法,通过调用抽象类,实现对子类的调用,先看个关系图:

    public abstract class AbstractCalculator {    
       //主方法,实现对本类其它方法的调用  
       public final int calculate(String exp,String opt){  
           int array[] = split(exp,opt);  
           return calculate(array[0],array[1]);  
      }    
       //被子类重写的方法
       abstract public int calculate(int num1,int num2);  

       public int[] split(String exp,String opt){  
           String array[] = exp.split(opt);  
           int arrayInt[] = new int[2];  
           arrayInt[0] = Integer.parseInt(array[0]);  
           arrayInt[1] = Integer.parseInt(array[1]);  
           return arrayInt;  
      }  
  }  
   public class Plus extends AbstractCalculator {  
       @Override  
       public int calculate(int num1,int num2) {  
           return num1 + num2;  
      }  
  }  

Num4:代理模式

interface Game {

   void play();
}

class LeagueOfLegends implements Game {

   @Override
   public void play() {
       System.out.println(getClass().getSimpleName() + "打野中");
  }
}

/**
* 静态代理
*/
class LeagueOfLegendsProxy implements Game {

   private Game mGame;
   private String mUserName;
   private String mUserPwd;
   private boolean isLogin;

   LeagueOfLegendsProxy(Game game, String userName, String userPwd) {
       mGame = game;
       mUserName = userName;
       mUserPwd = userPwd;
  }

   @Override
   public void play() {
       if (login(mUserName, mUserPwd)) {
           System.out.println(getClass().getSimpleName() + "登陆成功");
           mGame.play();
           System.out.println(getClass().getSimpleName() + "游戏胜利");
           if (playAgain()) {
               play();
          } else {
               isLogin = false;
               System.out.println(getClass().getSimpleName() + "退出登陆");
          }
      } else {
           System.out.println(getClass().getSimpleName() + "登陆失败");
      }
  }

   private boolean login(String userName, String userPwd) {
       if (isLogin) {
           return true;
      } else {
           System.out.println(getClass().getSimpleName() + "正在登陆对方账户:" + mUserName);
           isLogin = new Random().nextInt(10) % 2 == 0;
      }
       return isLogin;
  }

   private boolean playAgain() {
       return new Random().nextInt(10) % 2 == 0;
  }
}

/**
* 动态代理
*/
class DynamicProxyHandler implements InvocationHandler {

   private Game mGame;

   DynamicProxyHandler(Game Game) {
       mGame = Game;
  }

   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       System.out.println(getClass().getSimpleName() + "准备代打");
       Object invoke = method.invoke(mGame, args);
       System.out.println(getClass().getSimpleName() + "代打成功");
       return invoke;
  }
}

public class ProxyTest {

   public static final String TAG = ProxyTest.class.getSimpleName();

   public static void main(String[] args) {
       // 静态代理使用
       new LeagueOfLegendsProxy(new LeagueOfLegends(), "LiuGuoQing", "qwer1234").play();
       // 动态代理使用
       DynamicProxyHandler handler = new DynamicProxyHandler(new LeagueOfLegends());
       Game proxyInstance = (Game)
           Proxy.newProxyInstance(LeagueOfLegends.class.getClassLoader(),
                                  LeagueOfLegends.class.getInterfaces(), handler);
       proxyInstance.play();
  }

}    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(){  
           super();  
           this.source = new Source();  
      }  
       @Override  
       public void method() {  
           before();  
           source.method();  
           atfer();  
      }  
       private void atfer() {  
           System.out.println("after proxy!");  
      }  
       private void before() {  
           System.out.println("before proxy!");  
      }  
  }  
测试类:
   public class ProxyTest {  
       public static void main(String[] args) {  
           Sourceable source = new Proxy();  
           source.method();  
      }  
  }  

Num5:装饰模式

/**
* 角色
*/
interface Role {

   void decorate();
}

/**
* 男性角色
*/
class MaleRole implements Role {

   @Override
   public void decorate() {
       System.out.println("初始化男性角色");
  }
}

/**
* 装备
*/
abstract class Clothes implements Role {

   protected Role mRole;

   public Clothes(Role role) {
       mRole = role;
  }

   @Override
   public void decorate() {
       mRole.decorate();
  }
}

/**
* 功能宝珠
*/
abstract class Gem implements Role {

   protected Role mRole;

   public Gem(Role role) {
       mRole = role;
  }

   @Override
   public void decorate() {
       mRole.decorate();
  }
}

/**
* 玄铁甲
*/
class XuanTieJia extends Clothes {

   public XuanTieJia(Role role) {
       super(role);
  }

   @Override
   public void decorate() {
       System.out.println("穿上玄铁甲");
  }
}

/**
* 火系宝珠
*/
class FireGem extends Gem {

   public FireGem(Role role) {
       super(role);                   //抽象类实现接口,装饰类继承抽象类再重写
  }

   @Override
   public void decorate() {
       System.out.println("镶嵌火系宝珠");
  }
}
public class DecorationTest {

   public static final String TAG = DecorationTest.class.getSimpleName();

   public static void main(String[] args) {
       // 初始化角色
       Role role = new MaleRole();
       // 穿个玄铁甲
       XuanTieJia xuanTieJia = new XuanTieJia(role);
       // 给玄铁甲镶嵌个火系宝珠
       FireGem fireGem = new FireGem(xuanTieJia);
       fireGem.decorate();
  }
}              

装饰器模式和代理模式之间de差别

装饰模式应该为所装饰的对象增强功能;代理模式对代理的对象施加控制,但不对对象本身的功能进行增强。

Num6:适配器(Adapter)模式

把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

image-20200310203807145

public interface MicroUSB {                                  //类适配器
   void isMicroUSB();    //有个传统的Micro USB的充电线
}
public interface TypeC {
   void isTypeC();     //手机充电口为typec
}
public class TypeCImpl implements TypeC{
   @Override
   public void isTypeC() {
       System.out.println("typec充电口");
  }
}                        //用于将MicroUSB接口转化成tytpec接口
public class Adapter extends TypeCImpl implements MicroUSB{
   @Override
   public void isMicroUSB() {
       isTypeC();
  }
}
//测试类
public class App {
   public static void main(String[] args) {
       MicroUSB microUSB = new Adapter();
       microUSB.isMicroUSB();
  }
}
public interface MicroUSB {                                  //对象适配器  代理实现
    void isMicroUSB();    //有个传统的Micro USB的充电线
}
public interface TypeC {
    void isTypeC();     //手机充电口为typec
}
public class TypeCImpl implements TypeC{
    @Override
    public void isTypeC() { 
        System.out.println("typec充电口");
    }
}                       
public class Adapter implements MicroUSB{
    private TypeC typeC;
    public Adapter(TypeC typeC){
        this.typeC = typeC;
    }
    @Override
    public void isMicroUSB() {
        typeC.isTypeC();
    }
}

Num7:观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

JAVA提供的对观察者模式的支持

在JAVA语言的java.util库里面,提供了一个Observable类以及一个Observer接口,构成JAVA语言对观察者模式的支持。

public interface Observer {
    void update(Observable o, Object arg);
}

被观察者类都是java.util.Observable类的子类。java.util.Observable提供公开的方法支持观察者对象,这些方法中有两个对Observable的子类非常重要:一个是setChanged(),另一个是notifyObservers()。第一方法setChanged()被调用之后会设置一个内部标记变量,代表被观察者对象的状态发生了变化。第二个是notifyObservers(),这个方法被调用时,会调用所有登记过的观察者对象的update()方法,使这些观察者对象可以更新自己。

public class Observable {
   private boolean changed = false;
   private Vector obs;
 
   /** Construct an Observable with zero Observers. */

   public Observable() {
   obs = new Vector();
  }

   /**
    * 将一个观察者添加到观察者聚集上面
    */
   public synchronized void addObserver(Observer o) {
       if (o == null)
           throw new NullPointerException();
   if (!obs.contains(o)) {
       obs.addElement(o);
  }
  }

   /**
    * 将一个观察者从观察者聚集上删除
    */
   public synchronized void deleteObserver(Observer o) {
       obs.removeElement(o);
  }

   public void notifyObservers() {
   notifyObservers(null);
  }

   /**
    * 如果本对象有变化(那时hasChanged 方法会返回true)
    * 调用本方法通知所有登记的观察者,即调用它们的update()方法
    * 传入this和arg作为参数
    */
   public void notifyObservers(Object arg) {

       Object[] arrLocal;

   synchronized (this) {

       if (!changed)
               return;
           arrLocal = obs.toArray();
           clearChanged();
      }

       for (int i = arrLocal.length-1; i>=0; i--)
          ((Observer)arrLocal[i]).update(this, arg);
  }

   /**
    * 将观察者聚集清空
    */
   public synchronized void deleteObservers() {
   obs.removeAllElements();
  }

   /**
    * 将“已变化”设置为true
    */
   protected synchronized void setChanged() {
   changed = true;
  }

   /**
    * 将“已变化”重置为false
    */
   protected synchronized void clearChanged() {
   changed = false;
  }

   /**
    * 检测本对象是否已变化
    */
   public synchronized boolean hasChanged() {
   return changed;
  }

   /**
    * Returns the number of observers of this <tt>Observable</tt> object.
    *
    * @return the number of observers of this object.
    */
   public synchronized int countObservers() {
   return obs.size();
  }
}

怎样使用JAVA对观察者模式的支持

public class Watched extends Observable{          // 被观察者Watched类源代码
   private String data = "";
   public String getData() {
       return data;
  }
   public void setData(String data) {      
       if(!this.data.equals(data)){
           this.data = data;
           setChanged();
      }
       notifyObservers();
  }                                        
                                                   //观察者类源代码
   public class Watcher implements Observer{
   public Watcher(Observable o){
       o.addObserver(this);
  }
   @Override
   public void update(Observable o, Object arg) {
       
       System.out.println("状态发生改变:" + ((Watched)o).getData());
  }
}
   //测试类
   public class Test {
   public static void main(String[] args) {  
       //创建被观察者对象
       Watched watched = new Watched();
       //创建观察者对象,并将被观察者对象登记
       Observer watcher = new Watcher(watched);
       //给被观察者状态赋值
       watched.setData("start");
       watched.setData("run");
       watched.setData("stop");
  }}
   Test对象首先创建了Watched和Watcher对象。在创建Watcher对象时,将Watched对象作为参数传入;然后Test对象调用Watched对象的setData()方法,触发Watched对象的内部状态变化;Watched对象进而通知实现登记过的Watcher对象,也就是调用它的update()方法。

Num8:建造(Builder)者模式

建造者模式能够将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。这句话理解起来可能有点抽象,简单来说就是调用相同的创建对象的方法(建造过程)可以创建出不同的对象。

如果说我要创建一部手机,我需要先制造手机的几个核心部件,例如:屏幕、电池、听筒、话筒、机身等。

public class MobilePhone {

    //手机屏幕
    private String screen;
    //电池
    private String battery;
    //话筒
    private String microphone;
    //听筒
    private String phoneReceiver;
    //机身
    private String phoneBody;
   //...get  ,set.....
}

public interface IBuildPhone {
    //建造手机屏幕
    void buildScreen();
    //建造手机电池
    void buildBattery();
    //建造手机听筒
    void buildMicrophone();
	// 建造手机话筒
    void buildPhoneReceiver();
	//建造手机机身
    void buildPhoneBody();
}
public class IPhoneX implements IBuildPhone {
    private MobilePhone mobilePhone;
    public IPhoneX(){
        mobilePhone =  new MobilePhone();
    }
    //建造手机屏幕
    @Override
    public void buildScreen() {
        mobilePhone.setScreen("OLED显示屏");
    }
   // 建造手机电池
    @Override
    public void buildBattery() {
        mobilePhone.setBattery("2700mAh电池容量");
    }
	// 建造手机听筒
    @Override
    public void buildMicrophone() {
        mobilePhone.setMicrophone("听筒");
    }
	//建造手机话筒
    @Override
    public void buildPhoneReceiver() {
        mobilePhone.setPhoneReceiver("话筒");
    }
    // 建造手机机身
    @Override
    public void buildPhoneBody() {
        mobilePhone.setPhoneBody("iphoneX机身");
    }
	//创建手机  
    public MobilePhone build(){
        return mobilePhone;
    }
}

public class Director {

    /**
     * 建造一部手机
     * @param buildPhone
     * @return
     */
    public MobilePhone createMobilePhone(IBuildPhone buildPhone){

        buildPhone.buildBattery();
        buildPhone.buildMicrophone();
        buildPhone.buildScreen();
        buildPhone.buildPhoneReceiver();
        buildPhone.buildPhoneBody();

        return buildPhone.createMobilePhone();
    }

    @Test
    public void thatTest(){
        System.out.println(JSON.toJSONString(createMobilePhone(new IPhoneX())));
    }
}
  1. 策略模式(strategy)

    策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法 的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类可有可无,属于辅助类),提供辅助函数。策略模式的决定权在用户,系统本身提供不同算法的实现,新增或者删除算法,对各种算法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可

//创建一个接口。
public interface Strategy {
   public int doOperation(int num1, int num2);
}
//创建实现接口的实体类。
public class OperationAdd implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}
public class OperationSubstract implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}
public class OperationMultiply implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 * num2;
   }
}
//创建 Context 类。
public class Context {
   private Strategy strategy;
 
   public Context(Strategy strategy){
      this.strategy = strategy;
   }
 
   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}
//使用 Context 来查看当它改变策略 Strategy 时的行为变化。

public class StrategyPatternDemo {
   public static void main(String[] args) {
      Context context = new Context(new OperationAdd());    
      System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
 
      context = new Context(new OperationSubstract());      
      System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
 
      context = new Context(new OperationMultiply());    
      System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
   }
}

10.桥接模式
桥接(Bridge)模式的定义如下:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

桥接(Bridge)模式的优点是:

  • 由于抽象与实现分离,所以扩展能力强;
  • 其实现细节对客户透明。

缺点是:由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,这增加了系统的理解与设计难度。

 

    package bridge;
    public class BridgeTest
    {
        public static void main(String[] args)
        {
            Implementor imple=new ConcreteImplementorA();
            Abstraction abs=new RefinedAbstraction(imple);
            abs.Operation();
        }
    }
    //实现化角色
    interface Implementor
    {
        public void OperationImpl();
    }
    //具体实现化角色
    class ConcreteImplementorA implements Implementor
    {
        public void OperationImpl()
        {
            System.out.println("具体实现化(Concrete Implementor)角色被访问" );
        }
    }
    //抽象化角色
    abstract class Abstraction
    {
       protected Implementor imple;
       protected Abstraction(Implementor imple)
       {
           this.imple=imple;
       }
       public abstract void Operation();   
    }
    //扩展抽象化角色
    class RefinedAbstraction extends Abstraction
    {
       protected RefinedAbstraction(Implementor imple)
       {
           super(imple);
       }
       public void Operation()
       {
           System.out.println("扩展抽象化(Refined Abstraction)角色被访问" );
           imple.OperationImpl();
       }
    }

 

11.原型模式

原型模式的克隆分为浅克隆和深克隆,Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。其代码如下:

 

//浅拷贝
@Setter
@Getter
public class User implements Cloneable {
    private String id;
    private String username;
    private Date birthday;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                '}' + super.toString();
    }
}

 

//深拷贝
protected Object clone() {
try {
// 序列化
 ByteArrayOutputStream bos = new ByteArrayOutputStream();
 ObjectOutputStream oos = new ObjectOutputStream(bos);
 oos.writeObject(this);
 // 反序列化
 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
 ObjectInputStream ois = new ObjectInputStream(bis);
 
 return ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}

 

posted on 2020-04-20 12:11  TheKingJames  阅读(172)  评论(0编辑  收藏  举报