小小笔试题——企鹅2014校招——简答题——广州

        本题来自:http://blog.csdn.net/v_july_v/article/details/11921021

        题目描述:请设计一个排队系统,能够让每个进入队伍的用户都能看到自己再队列中所处的位置和变化,队伍可能随时有人加入和退出,当有人退出影响到用户的位置排名时需要及时反馈到用户。

        先在对本题进行做如下假设:

        1.不存在插队的情况,即新用户只能出现在队伍的末尾

        2.本次设计未满足随时有人加入和退出条件,即未满足同一时刻的并发处理


        那么对题目进行分析:

        第一,用户的关注点有两个:所处位置以及位置是否变化

        第二,导致位置的变化是由用户退出所引起的


        那么,根据上述的描述,如果让我来作答,会选择设计模式中的Observer(观察者模型)来作答。因为,此场景是一种订阅-推送的场景,可以参考之前我对Observer描述:http://blog.csdn.net/anger_coder/article/details/12292979

        那么基于此,分析观察者模式中的角色:

        观察者:用户

        抽象主题:加入、退出

        解释说来,就是用户作为观察者,只关注于自己的位置是否发生变化,这个变化的通知者——系统;那么系统则关心抽象主题,也就是加入、退出。实现的流程就是:观察者加入到系统中,当有关注的事件发生时,系统通知观察者。

        下面来看下类图


        上述就是实现Observer模型的类定义,按照此思路实现示例Demo(Java版):源码下载地址:TecentObserver

        关键代码如下:

         

package com.hzy.observer;

public interface Observer 
{
	/**
	 * 
	 * @param eventId
	 * 		|-- 1代表 登入
	 * 		|-- 2代表退出
	 */
	public void Update( int eventId, ConcreteSubject concreteSubject );	//观察者用于更新自身状态
}

package com.hzy.observer;

public interface Subject 
{
	//将观察者添加到目标事件
	public void Attach( Observer observer );
	//将观察者从目标事件解除
	public void Detach( Observer observer, int index );
	//事件通知观察者
	public void Notify();
	
}


package com.hzy.observer;

public class ConcreteObserver implements Observer
{
	private String name;
	private int id;
	
	public ConcreteObserver( String name )
	{
		this.name = name;
	}
	
	
	@Override
	public void Update( int eventId, ConcreteSubject concreteSubject ) 
	{
		switch( eventId )
		{
		//登录
		case 1:
			this.setId( concreteSubject.getAddId() );
			System.out.println( this.getName() + " : " + id );
			break;
		//登出
		case 2:
			if ( this.getId() > concreteSubject.getLeaveId() )
			{
				this.setId( this.getId() - 1 );
				System.out.println( this.getName() + " :" + "My Position Has Changed, after change is " + this.getId() );
			}
			break;
		}
	}
	
	protected void setId( int id )
	{
		this.id = id;
	}
	
	protected int getId()
	{
		return this.id;
	}
	
	protected String getName()
	{
		return this.name;
	}
}


package com.hzy.observer;

import java.util.Enumeration;
import java.util.Vector;

public class ConcreteSubject implements Subject
{
	static private Vector<Observer> vector;
	private int leaveId;
	private int addId;
	static{
		vector = new Vector<Observer>();
	}
	
	/**
	 * 
	 *   当通过Attach添加新人的时候 需要进行通知
	 * */
	@Override
	public void Attach( Observer observer ) 
	{
		// TODO Auto-generated method stub
		this.setAddId( vector.size() );
		observer.Update( 1, this );
		vector.add( observer );		
	}

	@Override
	public void Detach( Observer observer, int index ) 
	{
		// TODO Auto-generated method stub
		vector.remove( index - 1 );
//		System.out.println( "After Remove Size: " + vector.size() );
		this.setLeaveId( index - 1 );
		this.Notify();
	}

	@Override
	public void Notify() 
	{
		// TODO Auto-generated method stub
		Enumeration<Observer> e = vector.elements();
		
		while( e.hasMoreElements() )
		{
			e.nextElement().Update( 2, this );
		}
	}
	
	protected void setAddId( int addId )
	{
		this.addId = addId;
	}
	
	protected int getAddId( )
	{
		return this.addId;
	}
	
	protected void setLeaveId( int leaveId )
	{
		this.addId = leaveId;
	}
	
	protected int getLeaveId( )
	{
		return this.leaveId;
	}

}

        运行测试代码:

        首先加入三名用户,分别为A、B、C;而后B用户退出,C用户的位置会发生改变,再加入新用户Join,结果如下图:

        

         测试类代码:

package com.hzy.test;

import org.junit.Test;

import com.hzy.observer.ConcreteObserver;
import com.hzy.observer.ConcreteSubject;


public class TecentTest 
{
	@Test
	public void test()
	{
		ConcreteSubject concreteSubject = new ConcreteSubject();
		
		ConcreteObserver concreteObserverOne   = new ConcreteObserver( "A" );
		ConcreteObserver concreteObserverTwo   = new ConcreteObserver( "B" );
		ConcreteObserver concreteObserverThree = new ConcreteObserver( "C" );
		ConcreteObserver concreteObserverJoin  = new ConcreteObserver( "Join" );
		
		concreteSubject.Attach( concreteObserverOne );
		concreteSubject.Attach( concreteObserverTwo );
		concreteSubject.Attach( concreteObserverThree );
		
		concreteSubject.Detach( concreteObserverTwo, 2 );
		
		concreteSubject.Attach( concreteObserverJoin );
	}
}
         思路就写到这里,附带了一个简单的实现,还有很多不完善的地方,如果思路不对,或者有其他好想法,希望大家踊跃发言,集思广益嘛!!:)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值