当前位置:  编程技术>软件工程/软件设计
本页文章导读:
    ▪观察者模式(Observer)      @@@模式定义: 定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。 观察者模式又被称为发布——订阅模式。 @@@练习示例:&n.........
    ▪工厂模式 - 程序实现(java)          09年5月CSDN一网友提出如下问题: 设计一个用于管理银行客户的类BankCustomer: 仅描述客户的几个重要方面: 帐号、身份证号、姓名、联系方式、密码、账户余额。 所有的成.........
    ▪几种web并行化编程实现          当网站做到一定规模的时候,web单个页面需要涉及到的业务也会越来越多,每个页面可能会向后端发起几个、十几个甚至几十个请求。对于java、python之类的支持多线程的语言可以使.........

[1]观察者模式(Observer)
    来源: 互联网  发布时间: 2013-11-19
@@@模式定义:
定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,
所有依赖于它的对象都得到通知并被自动更新。
观察者模式又被称为发布——订阅模式。


@@@练习示例: 
订阅报纸


@@@示例代码:
\src\pattern\Subject.java

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

import java.util.ArrayList;
import java.util.List;

/**
 * 目标对象,作为被观察者
 */
public class Subject {
    /**
     * 用来保存注册的观察者对象,也就是报纸的订阅者
     */
	private List<Observer> readers = new ArrayList<Observer>();
	
	/**
	 * 报纸的读者需要向报社订阅,先要注册
	 * @param reader 报纸的读者
	 */
	public void attach(Observer reader) {
		readers.add(reader);
	}
	
	/**
	 * 报纸的读者可以取消订阅
	 * @param reader 报纸的读者
	 */
	public void detach(Observer reader) {
		readers.remove(reader);
	}
	
	/**
	 * 当每期报纸印刷出来后,就要迅速主动地被送到读者的手中
	 * 相当于通知读者,让他们知道
	 */
	protected void notifyObservers() {
		for (Observer reader : readers) {
			reader.update(this);
		}
	}
}

\src\pattern\Observer.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

/**
 * 观察者,比如报纸的读者
 */
public interface Observer {
    /**
     * 被通知的方法
     * @param subject 具体的目标对象,可以获取报纸的内容
     */
	public void update(Subject subject);
}

\src\pattern\NewsPaper.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

/**
 * 报纸对象,具体的目标对象
 */
public class NewsPaper extends Subject {
    /**
     * 报纸的具体内容
     */
	private String content;
	
	/**
	 * 获取报纸的具体内容
	 * @return 报纸的具体内容
	 */
	public String getContent() {
		return content;
	}
	
	/**
	 * 示意,设置报纸的具体内容,相当于要出版报纸了
	 * @param content 报纸的具体内容
	 */
	public void setContent(String content) {
		this.content = content;
		// 内容有了,说明又出版报纸了,那就通知所有的读者
		notifyObservers();
	}
}

\src\pattern\Reader.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

/**
 * 真正的读者,为了简单就描述一下姓名
 */
public class Reader implements Observer {
    /**
     * 读者的姓名
     */
	private String name;
	
	@Override
	public void update(Subject subject) {
		// 这里采用拉的方式
        System.out.println(name + "收到报纸了,阅读它,内容是:" 
        		+ ((NewsPaper)subject).getContent());
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

\src\user\Client.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package user;

import pattern.NewsPaper;
import pattern.Reader;

public class Client {
	public static void main(String[] args) {
		// 创建一份报纸,作为被观察者
        NewsPaper subject = new NewsPaper();
        
        // 创建读者,也就是观察者
        Reader reader1 = new Reader();
        reader1.setName("张三");
        
        Reader reader2 = new Reader();
        reader2.setName("李四");
        
        Reader reader3 = new Reader();
        reader3.setName("王五");
        
        // 注册读者
        subject.attach(reader1);
        subject.attach(reader2);
        subject.attach(reader3);
        
        // 出版报纸
        subject.setContent("本期的内容是观察者模式");
	}
}



[---使用JAVA自带的观察者模式---]


\src\pattern\NewsBook.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

/**
 * 报纸对象,具体的目标实现
 */
public class NewsBook extends java.util.Observable {
    /**
     * 报纸的具体内容
     */
	private String content;
	
	/**
	 * 获取报纸的具体内容
	 * @return 报纸的具体内容
	 */
	public String getContent() {
		return content;
	}
	
	/**
	 * 示意,设置报纸的具体内容,相当于要出版报纸了
	 * @param content 报纸的具体内容
	 */
	public void setContent(String content) {
		this.content = content;
		// 内容有了,说明又出版报纸了,那就通知所有的读者
		// 注意在使用Java中的Observer模式的时候,下面这句话不可少
		this.setChanged();
		// 然后主动通知,这里用的是推的方式
		this.notifyObservers(this.content);
		// 如果用拉的方式,这么调用
		// this.notifyObservers();
	}
}

\src\pattern\BookReader.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package pattern;

import java.util.Observable;

/**
 * 真正的读者,为了简单就描述一下姓名
 */
public class BookReader implements java.util.Observer {
    /**
     * 读者的姓名
     */
	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public void update(Observable o, Object obj) {
		// 这里采用推的方式
        System.out.println(name + "收到报纸了,阅读它,目标推过来的内容是:" 
        		+ obj);
        
        // 这里获取拉的数据
        System.out.println(name + "收到报纸了,阅读它,主动到目标对象去拉的内容是:"
        		+ ((NewsBook)o).getContent());
	}
}

\src\user\BookClient.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package user;

import pattern.BookReader;
import pattern.NewsBook;

public class BookClient {
	public static void main(String[] args) {
		// 创建一份报纸,作为被观察者
        NewsBook subject = new NewsBook();
        
        // 创建读者,也就是观察者
        BookReader reader1 = new BookReader();
        reader1.setName("张三");
        
        BookReader reader2 = new BookReader();
        reader2.setName("李四");
        
        BookReader reader3 = new BookReader();
        reader3.setName("王五");
        
        // 注册读者
        subject.addObserver(reader1);
        subject.addObserver(reader2);
        subject.addObserver(reader3);
        
        // 出版报纸
        subject.setContent("本期的内容是观察者模式");
	}

}

@@@模式的实现:
1) 目标和观察者之间一般是一对多,也可以一对一;
2) 观察者可以观察多个目标,一般需要为每个目标定义不同的回调方法而不是在update方法中来区分;
3) 观察者模式有推模型和拉模型两种方式;


@@@模式的优点:
1) 观察者模式实现了观察者和目标对象之间的抽象耦合;
2) 观察者模式实现了动态联动;
3) 观察者模式支持广播通信;


@@@模式的缺点:
1) 可能会引起无谓的操作;


@@@模式的本质:
触发联动


@@@模式体现的设计原则:
NA


作者:jinfengmusic 发表于2013-7-7 18:16:29 原文链接
阅读:0 评论:0 查看评论

    
[2]工厂模式 - 程序实现(java)
    来源: 互联网  发布时间: 2013-11-19

    09年5月CSDN一网友提出如下问题:

设计一个用于管理银行客户的类BankCustomer:
	仅描述客户的几个重要方面:
		帐号、身份证号、姓名、联系方式、密码、账户余额。
	所有的成员变量均用private访问控制,因此每一个成员变量就要有相应的存取器
	(getter和setter,即获取和设置其值的相应的成员方法。需要setter还是getter,还是两者都要,视情况而定)

	成员方法:
	开户(开户时必须要有身份证号),系统自动生成帐号,帐号使用系统时间(格式:"yyyyMMddHHmmss"14位),初始密码为“666666”。
	注意开户和构造方法之间的关系。
	存钱、取钱、显示账户信息、修改密码(密码最短要六位)
	怎样在main中使用这个类,自行安排,要表现出你设计的类的各个方面,并在main中用英语加以注释 

    根据此,使用工厂模式设计如下若干类:

    ------------factory部分---------------------------xiaobin-------------

    Customer:        抽象类(factory祖先类)

    BankCustomer:继承类(factory类)

   

    〉〉〉〉〉〉〉〉〉〉扩展部分

    ContactWay:联系方式(factory引用类)

    IM                :实时消息(ContactWay引用类)

    ------------product部分---------------------------xiaobin-------------   
    Bank:            接口(product接口)

    Account:       实现类(concrete product类)

 

   类图如下:(使用Enterprise Architect绘制)

                           

 

 

   使用EA生成的代码如下:

   Customer.java

package bankCustomer;

/**
 * @author xiaobin
 * @version 1.0
 * @created 23-5-2009 15:19:06
 */
public abstract class Customer {

	private Bank bank;
	private double myMoney;
	public Bank m_Bank;

	public Customer(){

	}

	public void finalize() throws Throwable {

	}

	public abstract Bank createAccount();

	public void myAccount(){

	}

	public void mySaveMoney(){

	}

	public void myTakeMoney(){

	}
}


    BankCustomer.java

package bankCustomer;

/**
 * @author xiaobin
 * @version 1.0
 * @created 23-5-2009 15:30:13
 */
public class BankCustomer extends Customer {

	private ContactWay contact;
	private String name;
	private String personID;
	public Account m_Account;
	public ContactWay m_ContactWay;

	public BankCustomer(){

	}

	public void finalize() throws Throwable {
		super.finalize();
	}

	public Bank createAccount(){
		return null;
	}

	private ContactWay getContact(){
		return null;
	}

	private String getName(){
		return "";
	}

	private String getPersonID(){
		return "";
	}

	/**
	 * 
	 * @param contactWay
	 */
	private void setContact(ContactWay contactWay){

	}

	/**
	 * 
	 * @param myName
	 */
	private void setName(String myName){

	}

	/**
	 * 
	 * @param myPersonID
	 */
	private void setPersonID(String myPersonID){

	}
}


   ContactWay.java

package bankCustomer;

/**
 * @author xiaobin
 * @version 1.0
 * @created 23-5-2009 15:30:29
 */
class ContactWay {

	private String email;
	private IM imContact;
	private String mobilePhone;
	private String phone;
	public IM m_IM;

	public ContactWay(){

	}

	public void finalize() throws Throwable {

	}

	private String getEmail(){
		return "";
	}

	private IM getImContact(){
		return null;
	}

	private String getMobilePhone(){
		return "";
	}

	private String getPhone(){
		return "";
	}

	/**
	 * 
	 * @param myEmail
	 */
	private void setEmail(String myEmail){

	}

	/**
	 * 
	 * @param im
	 */
	private void setImContact(IM im){

	}

	/**
	 * 
	 * @param mobilePhone
	 */
	private void setMobilePhone(String mobilePhone){

	}

	/**
	 * 
	 * @param myPhone
	 */
	private void setPhone(String myPhone){

	}
}

 

   IM.java

package bankCustomer;

/**
 * @author xiaobin
 * @version 1.0
 * @created 23-5-2009 15:30:39
 */
class IM {

	private String MSN;
	private String QQ;

	public IM(){

	}

	public void finalize() throws Throwable {

	}

	private String getMSN(){
		return "";
	}

	private String getQQ(){
		return "";
	}

	/**
	 * 
	 * @param msn
	 */
	private void setMSN(String msn){

	}

	/**
	 * 
	 * @param qq
	 */
	private void setQQ(String qq){

	}
}


    Bank.java

package bankCustomer;

/**
 * @author xiaobin
 * @version 1.0
 * @created 23-5-2009 15:19:16
 */
public interface Bank {

	/**
	 * 
	 * @param money
	 */
	public boolean saveMoney(double money);

	/**
	 * 
	 * @param money
	 */
	public boolean takeMoney(double money);

}


    Account.java

package bankCustomer;

/**
 * @author xiaobin
 * @version 1.0
 * @created 07-7-2013 20:21:35
 */
public class Account implements Bank {

	private String accountID;
	private double accountSurplus;
	private Date date;

	public Account(){

	}

	public void finalize() throws Throwable {

	}

	/**
	 * 
	 * @param val1
	 * @param val2
	 */
	private double addAlgorithm(double val1, double val2){
		return 0;
	}

	/**
	 * 
	 * @param now
	 */
	private String createMyAccount(Date now){
		return "";
	}

	private String getAccountID(){
		return "";
	}

	/**
	 * 
	 * @param oldPWD
	 * @param curPWD
	 */
	private boolean modifyPWD(String oldPWD, String curPWD){
		return false;
	}

	/**
	 * 
	 * @param money
	 */
	public synchronized boolean saveMoney(double money){
		return false;
	}

	private void setAccountID(){

	}

	/**
	 * 
	 * @param val1
	 * @param val2
	 */
	private double subAlgorithm(double val1, double val2){
		return 0;
	}

	/**
	 * 
	 * @param money
	 */
	public synchronized boolean takeMoney(double money){
		return false;
	}

}



 

 

 

作者:xiaobin_HLJ80 发表于2013-7-7 19:23:18 原文链接
阅读:5 评论:0 查看评论

    
[3]几种web并行化编程实现
    来源: 互联网  发布时间: 2013-11-19

    当网站做到一定规模的时候,web单个页面需要涉及到的业务也会越来越多,每个页面可能会向后端发起几个、十几个甚至几十个请求。对于java、python之类的支持多线程的语言可以使用多线程编程,但也会增加程序的复杂性,像php这样的不支持多线程的语言只能借助其他方法实现并行,下面总结几种比较实用的并行化框架。


1、yar 是鸟哥开发的一个 基于php扩展的RPC框架。

//service.php
class ServiceTest
{
    public function test($param){
        sleep(1);
        return 'sleep 1s';
    }
   public function test2($param){
        sleep(1);
        return 'sleep 1s';
    }

   public function test3($param){
        sleep(1);
        return 'sleep 1s';
    }

}
$service = new Yar_Server(new ServiceTest());
$service->handle();

//client.php
$api    = "http://127.0.0.1/yar/service.php";
$param  = array(1,2,3);
function callback($retval, $callinfo){
    print_r($retval);
}
Yar_Concurrent_Client::call($api, 'test', array($param), 'callback');
Yar_Concurrent_Client::call($api, 'test2', array($param), 'callback');
Yar_Concurrent_Client::call($api, 'test3', array($param), 'callback');
Yar_Concurrent_Client::loop();

上面服务端代码有3个方法都sleep一秒来模拟业务端的处理,通过yar扩展注册服务,client端通过Yar_Concurrent_Client并行请求这个三个方法,最终执行时间是大约是1s。值得一提yar的并行操作是通过libcurl的并行实现的,服务端代码必须能够通过http访问到。对于tpc和unix socket目前只能进行同步请求,如需要并行实现需要自行加入消息队列之内的东西去实现。


2、APS,是安居客集团以zmq为消息中间件,以事件驱动进行网来请求的一个跨语言的RPC框架,框架中有一个代理(device)监听两个端口或者socket文件,分别监听客户端发来的请求和转发给服务端的多个worker进程,并负责把woker处理的返回的数据转发到客户端。运行github上面用php写的demon代码如下。


3、Gearman,是一个用来把工作委派给其他机器、分布式的调用更适合做某项工作的机器、并发的做某项工作在多个调用间做负载均衡、或用来在调用其它语言的函数的系统。通过worker向Gearmand守护进程注册工作,客户端通过Gearmand将任务分派到后端的worker进程,具体实现和APS类似。


4、nodejs,是一个事件驱动的单进程语言,可以通过这种异步编程模式实现对后台业务的并行处理。下面demo是以nodejs为客户端请求php后端的一个耗时3s的方法,一个耗时2s的方法:

var http = require("http");
var url	 = require('url');
var eventProxy =  require('eventproxy');
var handle = {};
handle['/'] = test;


function start(route, handle) {
	function onRequest(request, response) {
		var pathname = url.parse(request.url).pathname;
		route(handle, pathname, response);
	}
	http.createServer(onRequest).listen(8081);
}

function route(handle, pathname, response){
	console.log("route\n");
	if (typeof handle[pathname] === 'function') {
		handle[pathname](response);
	} else {
		console.log(pathname + 'is no fund');
	}
}

function test(response) {
	var ep = new eventProxy();
	
	ep.all('data1', 'data2', function(a, b){
		response.writeHead(200, {"Content-Type": "text/plain"});
		response.write(a);
		response.write(b);
		response.end();
	});


	http.get('http://127.0.0.1/nodejs/service.php?function=test', function(data){
		var buffers = [], size = 0;
		data.on('data', function(buffer) {
			buffers.push(buffer);
			size += buffer.length;
		});
		data.on('end', function(){
     		var buffer = new Buffer(size), pos = 0;
        	for(var i = 0, l = buffers.length; i < l; i++) {
           		buffers[i].copy(buffer, pos);
           		pos += buffers[i].length;
       		 }
			ep.emit('data1', buffer);
		});
	});
	http.get('http://127.0.0.1/nodejs/service.php?function=test2', function(data){
		var buffers = [], size = 0;
		data.on('data', function(buffer) {
			buffers.push(buffer);
			size += buffer.length;
		});
		data.on('end', function(){
     		var buffer = new Buffer(size), pos = 0;
        	for(var i = 0, l = buffers.length; i < l; i++) {
           		buffers[i].copy(buffer, pos);
           		pos += buffers[i].length;
       		 }
			ep.emit('data2', buffer);
		});
	});
}

function sleep(milliSeconds) {
   var startTime = new Date().getTime();
   while (new Date().getTime() < startTime + milliSeconds);
}

start(route, handle);



总结:

上述并行请求的实现有两种方式,一是基于事件驱动模型nodejs、yar(yar底层libcurl的curl_multi应用select()),二是基于消息队列的多进程的任务调度APS、Gearman。在实际的应用中的选择什么样的并行框架可能会根据各个方面来抉择,不管选择哪个,带来的一个很大的好处是使程序SOA化,减小代码间的耦合度,更变方便扩展。

作者:wzllai 发表于2013-7-7 21:11:38 原文链接
阅读:43 评论:0 查看评论

    
最新技术文章:
▪主-主数据库系统架构    ▪java.lang.UnsupportedClassVersionError: Bad version number i...    ▪eclipse项目出现红色叉叉解决方案
▪Play!framework 项目部署到Tomcat    ▪dedecms如何做中英文网站?    ▪Spring Batch Framework– introduction chapter(上)
▪第三章 AOP 基于@AspectJ的AOP    ▪基于插件的服务集成方式    ▪Online Coding开发模式 (通过在线配置实现一个表...
▪观察者模式(Observer)    ▪工厂模式 - 程序实现(java)    ▪几种web并行化编程实现
▪机器学习理论与实战(二)决策树    ▪Hibernate(四)——全面解析一对多关联映射    ▪我所理解的设计模式(C++实现)——解释器模...
▪利用规则引擎打造轻量级的面向服务编程模式...    ▪google blink的设计计划: Out-of-Progress iframes    ▪FS SIP呼叫的消息线程和状态机线程
▪XML FREESWITCH APPLICATION 实现    ▪Drupal 实战    ▪Blink: Chromium的新渲染引擎
▪(十四)桥接模式详解(都市异能版)    ▪你不知道的Eclipse用法:使用Allocation tracker跟...    ▪Linux内核-进程
▪你不知道的Eclipse用法:使用Metrics 测量复杂度    ▪IT行业为什么没有进度    ▪Exchange Server 2010/2013三种不同的故障转移
▪第二章 IoC Spring自动扫描和管理Bean    ▪CMMI简介    ▪目标检测(Object Detection)原理与实现(六)
▪值班总结(1)——探讨sql语句的执行机制    ▪第二章 IoC Annotation注入    ▪CentOS 6.4下安装Vagrant
▪Java NIO框架Netty1简单发送接受    ▪漫画研发之八:会吃的孩子有奶吃    ▪比较ASP和ASP.NET
▪SPRING中的CONTEXTLOADERLISTENER    ▪在Nginx下对网站进行密码保护    ▪Hibernate从入门到精通(五)一对一单向关联映...
▪.NET领域驱动设计—初尝(三:穿过迷雾走向光...    ▪linux下的块设备驱动(一)    ▪Modem项目工作总结
▪工作流--JBPM简介及开发环境搭建    ▪工作流--JBPM核心服务及表结构    ▪Eclipse:使用JDepend 进行依赖项检查
▪windows下用putty上传文件到远程Linux方法    ▪iBatis和Hibernate的5点区别    ▪基于学习的Indexing算法
▪设计模式11---设计模式之中介者模式(Mediator...    ▪带你走进EJB--JMS编程模型    ▪从抽象谈起(二):观察者模式与回调
▪设计模式09---设计模式之生成器模式(Builder)也...    ▪svn_resin_持续优化中    ▪Bitmap recycle方法与制作Bitmap的内存缓存
▪Hibernate从入门到精通(四)基本映射    ▪设计模式10---设计模式之原型模式(Prototype)    ▪Dreamer 3.0 支持json、xml、文件上传
▪Eclipse:使用PMD预先检测错误    ▪Jspx.net Framework 5.1 发布    ▪从抽象谈起(一):工厂模式与策略模式
▪Eclipse:使用CheckStyle实施编码标准    ▪【论文阅读】《Chain Replication for Supporting High T...    ▪Struts2 Path_路径问题
▪spring 配置文件详解    ▪Struts2第一个工程helloStruts极其基本配置    ▪Python学习入门基础教程(learning Python)--2 Python简...
▪maven springmvc环境配置    ▪基于SCRUM的金融软件开发项目    ▪software quality assurance 常见问题收录
▪Redis集群明细文档    ▪Dreamer 框架 比Struts2 更加灵活    ▪Maven POM入门
▪git 分支篇-----不断更新中    ▪Oracle非主键自增长    ▪php设计模式——UML类图
▪Matlab,Visio等生成的图片的字体嵌入问题解决...    ▪用Darwin和live555实现的直播框架    ▪学习ORM框架—hibernate(二):由hibernate接口谈...
▪(十)装饰器模式详解(与IO不解的情缘)    ▪无锁编程:最简单例子    ▪【虚拟化实战】网络设计之四Teaming
▪OSGi:生命周期层    ▪Javascript/Jquery——简单定时器    ▪java代码 发送GET、POST请求
▪Entity Framework底层操作封装(3)    ▪HttpClient 发送GET、POST请求    ▪使用spring框架,应用启动时,加载数据
▪Linux下Apache网站目录读写权限的设置    ▪单键模式的C++描述    ▪学习ORM框架—hibernate(一):初识hibernate
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3