行为型设计模式目的是将多个类或对象相互协作,共同完成单个类或对象无法单独完成的任务。行为型设计模式共11种,分别为解释器模式、模板方法模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式。
一、解释器模式
解释器模式指预先定义一种语法,然后根据语法对传入数据进行解析。例如java中正则表达式解析就是使用该模式。其优点为扩展性好,容易实现,但执行效率较低,并且每种语法对应一种实现,需要建大量类。在解释器模式中存在抽象解释器(AbstractExpression),终结符表达式(TerminalExpression),非终结符表达式(NonterminalExpression),上下文(Context),客户类(Test)五种角色。以简单的规则定义为例,代码如下
新建抽象表达式Expression
/**
* 抽象表达式:定义所有终结符表达式和非终结符表达式的解释操作
*
* @author huaisf
*
*/
public interface Expression {
public boolean interpret(String value);
}
新建非终结符表达式NonterminalExpression
/**
* 非终结符表达式:实现非终结操作
*
* @author huaisf
*
*/
public class NonterminalExpression implements Expression {
private Expression terminalExpression = null;
public NonterminalExpression(Expression terminalExpression) {
this.terminalExpression = terminalExpression;
}
public boolean interpret(String value) {
// 没有非终结符,直接调用终结符表达式
return terminalExpression.interpret(value);
}
}
新建终结符表达式TerminalExpression
/**
* 终结符表达式:实现终结操作
*
* @author huaisf
*
*/
public class TerminalExpression implements Expression {
private Map map = new HashMap();
public TerminalExpression(String rule) {
int index = rule.indexOf(":");
String city = rule.substring(0, index);
String scenery = rule.substring(index + 1, rule.length());
map.put(city, scenery);
}
@Override
public boolean interpret(String value) {
int index = value.indexOf(":");
String city = value.substring(0, index);
String scenery = value.substring(index + 1, value.length());
String existScenery = map.get(city);
if (existScenery != null && existScenery.equals(scenery)) {
return true;
}
return false;
}
}
新建上下文Context
/**
* 上下文:完成终结表达式初始化,并对要解释的数据进行中转
*
* @author huaisf
*
*/
public class Context {
private Expression nonterminalExpression;
public Context(String rule) {
Expression terminalExpression = new TerminalExpression(rule);
nonterminalExpression = new NonterminalExpression(terminalExpression);
}
public void matches(String value) {
boolean isExist = nonterminalExpression.interpret(value);
if (isExist) {
System.out.println("城市与景区对应成功");
return;
}
System.out.println("城市与景区对应失败");
}
}
新建测试类Test
public class Test {
public static void main(String[] args) {
// 定义规则为"杭州:西湖"进行验证
Context context = new Context("杭州:西湖");
context.matches("杭州:西湖");
context.matches("苏州:西湖");
context.matches("苏州:太湖");
}
}
二、模板方法模式
模板方法指在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。使用模板方法可提取公共逻辑进行封装,对于非公共操作交由子类执行,但非公共操作如果有改变,则会影响其所有子类。模板方法中分为抽象模板(AbstractTemplate)与具体实现模板(ConcreteTemplate)两种角色。以生产插排为例,代码如下
新建抽象模板Socket
/**
* 抽象模板:定义具体操作及抽象操作,抽象操作由子类实现
*
* @author huaisf
*
*/
public abstract class Socket {
/**
* 封装公共逻辑
*/
final void create() {
// 先购买材料
buyMaterial();
// 然后材料组装成插排
assembly();
// 印上各厂商logo
printLogo();
}
void buyMaterial() {
System.out.println("购买材料");
}
void assembly() {
System.out.println("材料组装成插排");
}
/**
* 印上logo
*/
abstract void printLogo();
}
新建具体实现模板BullSocket与TCLSocket
/**
* 具体实现模板:实现父类定义的抽象方法,重写父类逻辑
*
* @author huaisf
*
*/
public class BullSocket extends Socket {
@Override
void printLogo() {
System.out.println("图上公牛的logo");
}
}
/**
* 具体实现模板:实现父类定义的抽象方法,重写父类逻辑
*
* @author huaisf
*
*/
public class TCLSocket extends Socket {
@Override
void printLogo() {
System.out.println("图上TCL的logo");
}
}
新建测试类Test
public class Test {
public static void main(String[] args) {
// 生产公牛插排
BullSocket bullSocket = new BullSocket();
bullSocket.create();
// 生成tcl插排
TCLSocket tclSocket = new TCLSocket();
tclSocket.create();
}
}
三、责任链模式
责任链模式是对某个请求的所有处理构成一条链,如果链上的某一处理者可以处理,则处理后返回。如果不能处理则将请求传递给链上的下一个处理者。责任链模式中存在抽象处理者(Handler)与具体处理者(ConcreteHandler)两种角色。以购买插排为例,代码如下:
新建抽象处理者AbstractSocketHandler
/**
* 抽象处理者:定义处理请求接口
*
* @author huaisf
*
*/
public abstract class AbstractSocketHandler {
private AbstractSocketHandler NextHandler;
public AbstractSocketHandler getNextHandler() {
return NextHandler;
}
public void setNextHandler(AbstractSocketHandler nextHandler) {
NextHandler = nextHandler;
}
/**
* 购买插排
*
* @param count
*/
abstract void buySocket(Integer count);
}
新建具体处理者OriginalPriceSocketHandler、NineDiscountSocketHandler、EightDiscountSocketHandler
/**
* 具体处理者:对抽象处理者定义的接口进行实现,如果无法处理则将请求传递给下一个处理者
*
* @author huaisf
*
*/
public class OriginalPriceSocketHandler extends AbstractSocketHandler {
@Override
void buySocket(Integer count) {
if (count <= 500) {
System.out.println("原价购买插排");
return;
}
this.getNextHandler().buySocket(count);
}
}
public class NineDiscountSocketHandler extends AbstractSocketHandler {
@Override
void buySocket(Integer count) {
if (count > 500 && count <= 5000) {
System.out.println("九折购买插排");
return;
}
this.getNextHandler().buySocket(count);
}
}
public class EightDiscountSocketHandler extends AbstractSocketHandler {
@Override
void buySocket(Integer count) {
if (count > 5000) {
System.out.println("八折购买插排");
return;
}
this.getNextHandler().buySocket(count);
}
}
新建测试类Test组装调用
public class Test {
public static void main(String[] args) {
// 组装责任链
OriginalPriceSocketHandler originalPriceSocket = new OriginalPriceSocketHandler();
NineDiscountSocketHandler nineDiscountSocket = new NineDiscountSocketHandler();
originalPriceSocket.setNextHandler(nineDiscountSocket);
nineDiscountSocket.setNextHandler(new EightDiscountSocketHandler());
originalPriceSocket.buySocket(50000);
}
}
四、命令模式
命令模式将请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,由该对象处理请求。命令模式中包括抽象命令(Command)、具体命令(Concrete Command)、接收者(Receiver)、调用者(Invoker)四种角色。使用命令模式可降低系统耦合度,提高扩展性,但每增加一个命令需要新增具体命令类造成类膨胀。以聊天为例,代码如下:
定义操作枚举ChatTypeEnum
public enum ChatTypeEnum {
GROUP_CHAT("群聊"),
PRIVATE_CHAT("私聊");
private String name;
ChatTypeEnum(String name) {
this.name = name;
}
}
新建抽象命令Command
/**
* 抽象命令:定义执行命令方法
*
* @author huaisf
*
*/
public interface Command {
void execute();
}
新建具体命令GroupChatCommand与PrivateChatCommand
/**
* 具体命令:对定义的抽象命令实现
*
* @author huaisf
*
*/
public class GroupChatCommand implements Command {
private ChatRecord chatRecord;
public GroupChatCommand() {
chatRecord = new ChatRecord();
}
@Override
public void execute() {
System.out.println("群聊消息发送给房间内所有人");
chatRecord.save();
}
}
public class PrivateChatCommand implements Command {
private ChatRecord chatRecord;
public PrivateChatCommand() {
chatRecord = new ChatRecord();
}
@Override
public void execute() {
System.out.println("私聊记录发送到对应人");
chatRecord.save();
}
}
新建接受者ChatRecord
/**
* 接收者:对真正业务进行处理
*
* @author huaisf
*
*/
public class ChatRecord {
public void save() {
System.out.println("保存聊天记录成功");
}
}
新建调用者CommandManager
/**
* 调用者:调用具体命令进行处理
*
* @author huaisf
*
*/
public class CommandManager {
public static HashMap map = new HashMap<>();
static {
map.put(ChatTypeEnum.GROUP_CHAT.name(), new GroupChatCommand());
map.put(ChatTypeEnum.PRIVATE_CHAT.name(), new PrivateChatCommand());
}
public void saveRecord(ChatTypeEnum chatTypeEnum) {
Command command = map.get(chatTypeEnum.name());
command.execute();
}
}
新建测试类Test
public class Test {
public static void main(String[] args) {
CommandManager commandManager = new CommandManager();
// 群聊消息
commandManager.saveRecord(ChatTypeEnum.GROUP_CHAT);
// 私聊消息
commandManager.saveRecord(ChatTypeEnum.PRIVATE_CHAT);
}
}
五、迭代器模式
迭代器模式提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。在迭代器模式中存在抽象容器(Aggregate)、具体容器(ConcreteAggregate)、抽象迭代器(Iterator)、具体迭代器(ConcreteIterator)。使用迭代器模式可以以不同的方式遍历一个聚合对象,并将遍历算法进行封装。但增加新的聚合类需要新增对应迭代器,提高了系统复杂性。下面以数组及集合两种数据结构遍历为例:
新建抽象迭代器AbstractIterator
/**
* 抽象迭代器:定义遍历元素所需要的方法
*
* @author huaisf
*
*/
public interface AbstractIterator {
/**
* 获取下一个元素
*
* @return
*/
Object next();
/**
* 是否有下一个元素
*
* @return
*/
boolean hashNext();
}
新建具体迭代器ArrayIterator与ListIterator
/**
* 具体迭代器:对抽象迭代器定义的方法进行实现,本迭代器为数组迭代器
* @author huaisf
*
*/
public class ArrayIterator implements AbstractIterator {
private int index = 0;
private Object[] array;
public ArrayIterator(Object[] array){
this.array=array;
}
@Override
public Object next() {
if (index <= array.length) {
return array[index-1];
}
return null;
}
@Override
public boolean hashNext() {
if (index >= array.length) {
return false;
}
index+=1;
return true;
}
}
/**
* 具体迭代器:对抽象迭代器定义的方法进行实现,本迭代器为集合迭代器
* @author huaisf
*
*/
public class ListIterator implements AbstractIterator {
private int index = 0;
private List list;
public ListIterator(List list){
this.list=list;
}
@Override
public Object next() {
if (index <= list.size()) {
return list.get(index-1);
}
return null;
}
@Override
public boolean hashNext() {
if (index >= list.size()) {
return false;
}
index+=1;
return true;
}
}
新建抽象容器AbstractContainer
/**
* 抽象容器:定义容器所需方法
*
* @author huaisf
*
*/
public interface AbstractContainer {
void add(Object object);
void delete(int index);
AbstractIterator iterator();
}
新建具体容器ArrayContainer与ListContainer
/**
* 具体容器:抽象容器的实现,对数据进行存储,本容器为数组容器
*
* @author huaisf
*
*/
public class ArrayContainer implements AbstractContainer {
private static Object[] array = new Object[0];
private int size = 0;
@Override
public void add(Object object) {
Object[] temp = new Object[size + 1];
System.arraycopy(array, 0, temp, 0, size);
temp[size] = object;
array = temp;
size += 1;
}
@Override
public void delete(int index) {
Object[] temp = new Object[size - 1];
System.arraycopy(array, 0, temp, 0, index);
System.arraycopy(array, index + 1, temp, index, size - index - 1);
array = temp;
size -= 1;
}
@Override
public AbstractIterator iterator() {
return new ArrayIterator(array);
}
}
/**
* 具体容器:抽象容器的实现,对数据进行存储,本容器为集合容器
*
* @author huaisf
*
*/
public class ListContainer implements AbstractContainer {
List list = new ArrayList();
@Override
public void add(Object object) {
list.add(object);
}
@Override
public void delete(int index) {
list.remove(index);
}
@Override
public AbstractIterator iterator() {
return new ListIterator(list);
}
}
新建测试类Test
public class Test {
public static void main(String[] args) {
// 使用list迭代器
ListContainer listContainer = new ListContainer();
for (int i = 0; i < 5; i++) {
listContainer.add(i);
}
AbstractIterator listIterator = listContainer.iterator();
while (listIterator.hashNext()) {
System.out.println(listIterator.next());
}
// 使用数组迭代器
ArrayContainer arrayContainer = new ArrayContainer();
for (int i = 5; i < 10; i++) {
arrayContainer.add(i);
}
AbstractIterator arrayIterator = arrayContainer.iterator();
while (arrayIterator.hashNext()) {
System.out.println(arrayIterator.next());
}
}
}
六、中介者模式
中介者模式是用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。该模式包括抽象中介者(Mediator)、具体中介者(Concrete Mediator)、抽象同事类(Colleague)、具体同事类(Concrete Colleague)四种角色。以买卖房屋为例,代码如下
定义操作类型OperationTypeEnum,该类型与设计模式无关
public enum OperationTypeEnum {
BUY("买房子"), SELL("卖房子");
private String name;
OperationTypeEnum(String name) {
this.name = name;
}
}
新建抽象中介者AbstractMediator
/**
* 抽象中介者:定义处理同事信息操作,保存同事对象
*
* @author huaisf
*
*/
public abstract class AbstractMediator {
BuyHouseUser buyHouseUser;
SellHouseUser sellHouseUser;
/**
* 转发消息
*
* @param type
*/
public abstract void contact(OperationTypeEnum type);
public BuyHouseUser getBuyHouseUser() {
return buyHouseUser;
}
public void setBuyHouseUser(BuyHouseUser buyHouseUser) {
this.buyHouseUser = buyHouseUser;
}
public SellHouseUser getSellHouseUser() {
return sellHouseUser;
}
public void setSellHouseUser(SellHouseUser sellHouseUser) {
this.sellHouseUser = sellHouseUser;
}
}
新建抽象同事类AbstractUser
/**
* 抽象同事类:定义同事操作接口,保存中介者对象。
*
* @author huaisf
*
*/
public abstract class AbstractUser {
AbstractMediator abstractMediator;
public AbstractUser(AbstractMediator abstractMediator) {
this.abstractMediator = abstractMediator;
}
/**
* 发送消息
*/
abstract void send();
/**
* 接收消息
*/
abstract void receive();
}
新建具体同事类BuyHouseUser与SellHouseUser
/**
* 具体同事类:对抽象同事类定义方法实现,本类为购房者同事类
*
* @author huaisf
*
*/
public class BuyHouseUser extends AbstractUser {
public BuyHouseUser(AbstractMediator abstractMediator) {
super(abstractMediator);
}
@Override
void send() {
System.out.println("发送买房请求");
super.abstractMediator.contact(OperationTypeEnum.BUY);
}
@Override
void receive() {
System.out.println("收到卖房响应");
}
}
/**
* 具体同事类:对抽象同事类定义方法实现,本类为售房者同事类
*
* @author huaisf
*
*/
public class SellHouseUser extends AbstractUser {
public SellHouseUser(AbstractMediator abstractMediator) {
super(abstractMediator);
}
@Override
void send() {
System.out.println("发送卖房响应");
super.abstractMediator.contact(OperationTypeEnum.SELL);
}
@Override
void receive() {
System.out.println("收到买房请求");
}
}
新建具体中介者HouseMediator
/**
* 具体中介者:实现抽象中介者定义方法,对同事请求进行处理
*
* @author huaisf
*
*/
public class HouseMediator extends AbstractMediator {
@Override
public void contact(OperationTypeEnum type) {
if (OperationTypeEnum.BUY == type) {
super.sellHouseUser.receive();
} else if (OperationTypeEnum.SELL == type) {
super.buyHouseUser.receive();
}
}
}
新建测试类Test
public class Test {
public static void main(String[] args) {
AbstractMediator mediator = new HouseMediator();
BuyHouseUser buyHouseUser = new BuyHouseUser(mediator);
SellHouseUser sellHouseUser = new SellHouseUser(mediator);
mediator.setBuyHouseUser(buyHouseUser);
mediator.setSellHouseUser(sellHouseUser);
buyHouseUser.send();
sellHouseUser.send();
}
}
七、备忘录模式
备忘录模式指在不破坏封装性的前提下,获取到一个对象的内部状态,并在对象之外记录或保存这个状态。在有需要的时候可将该对象恢复到原先保存的状态。使用备忘录模式可以对操作对象提供回滚操作,但对资源消耗过大,每操作一次都需要记录操作前数据。备忘录模式中包括发起人(Originator)、备忘录(Memento)、负责人(Caretaker)三种角色。以文档回滚为例,代码如下:
新建备忘录Memento
/**
* 备忘录:保存发起人数据,在需要时提供数据
*
* @author huaisf
*
*/
public class Memento {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
新建发起人Originator
/**
* 发起人:定义哪些属于备份数据,提供保存及恢复方法
*
* @author huaisf
*
*/
public class Originator {
private String content;
public Memento save() {
Memento memento = new Memento();
memento.setContent(content);
return memento;
}
public void rollback(Memento memento) {
this.content = memento.getContent();
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
新建负责人Caretaker
/**
* 负责人:对备忘录角色进行管理暂存、提供备忘录
*
* @author huaisf
*
*/
public class Caretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
新建测试类Test
public class Test {
public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Originator originator = new Originator();
originator.setContent("文档1");
System.out.println("第一次保存后文档内容:" + originator.getContent());
caretaker.setMemento(originator.save());
originator.setContent("文档2");
System.out.println("第一次保存后文档内容:" + originator.getContent());
originator.rollback(caretaker.getMemento());
System.out.println("回滚后文档内容:" + originator.getContent());
}
}
八、观察者模式
观察者模式也称发布-订阅模式,该多个观察者同时监听某一个主题对象。当主题对象变化时,会通知所有的观察者对象,使观察者可以更新自身数据。使用观察者模式可以在观察者与主题对象中建立连接关系,构成抽象耦合。但并未完全解耦,并且观察者越多,主题通知观察者耗费时间越长。在观察者模式中包括抽象主题(Subject)、具体主题(Concrete Subject)、抽象观察者(Observer)、具体观察者(Concrete Observer)四种角色。
新建抽象观察者AbstractObserver
/**
* 抽象观察者:定义主题通知时调用方法
* @author huaisf
*
*/
public interface AbstractObserver {
/**
* 更新数据
*/
void update();
}
新建具体观察者ConcreteObserverA与ConcreteObserverB
/**
* 具体观察者:实现抽象观察者定义的方法,当收到通知时进行自身业务处理
*
* @author huaisf
*
*/
public class ConcreteObserverA implements AbstractObserver {
@Override
public void update() {
System.out.println("观察者A收到通知,更新数据");
}
}
public class ConcreteObserverB implements AbstractObserver {
@Override
public void update() {
System.out.println("观察者B收到通知,更新数据");
}
}
新建抽象主题AbstractSubject
/**
* 抽象主题:定义操作观察者方法
* @author huaisf
*
*/
public interface AbstractSubject {
/**
* 添加观察者
*
* @param abstractObserver
*/
void addObserver(AbstractObserver abstractObserver);
/**
* 通知观察者
*/
void noticeObserver();
}
新建具体主题ConcreteSubject
/**
* 具体主题:对抽象观察者定义进行实现
*
* @author huaisf
*
*/
public class ConcreteSubject implements AbstractSubject {
List list = new ArrayList<>();
@Override
public void addObserver(AbstractObserver abstractObserver) {
list.add(abstractObserver);
}
@Override
public void noticeObserver() {
for (AbstractObserver abstractObserver : list) {
abstractObserver.update();
}
}
}
新建测试类Test
public class Test {
public static void main(String[] args) {
AbstractObserver observerA = new ConcreteObserverA();
AbstractObserver observerB = new ConcreteObserverB();
AbstractSubject subject = new ConcreteSubject();
// 添加观察者
subject.addObserver(observerA);
subject.addObserver(observerB);
// 对观察者进行通知
subject.noticeObserver();
}
}
九、状态模式
状态模式定义为允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。通俗来说当控制一个对象状态转换的条件表达式过于复杂时,可以使用状态模式将状态的判断逻辑转移到表示不同状态的一系列类中,将复杂的判断逻辑简化。使用状态模式可以将复杂逻辑简化到不同子类中,提高扩展性,但同样会造成类膨胀。在状态模式中存在上下文(Context)、抽象状态(State)、具体状态(ConcreteState)三种角色。以开关门状态转换为例,代码如下:
新建上下文Context
/**
* 上下文:定义外部调用方法,存储当前状态
*
* @author huaisf
*
*/
public class Context {
private DoorState doorState;
public Context(DoorState doorState) {
this.doorState = doorState;
}
public DoorState getDoorState() {
return doorState;
}
public void setDoorState(DoorState doorState) {
this.doorState = doorState;
}
public void switchOperation() {
doorState.switchOperation(this);
}
}
新建抽象状态DoorState
/**
* 抽象状态:定义不同状态的操作
*
* @author huaisf
*
*/
public abstract class DoorState {
/**
* 开关操作
*/
public abstract void switchOperation(Context context);
}
新建具体状态CloseDoorState与OpenDoorState
/**
* 具体状态:对抽象状态进行实现,在需要时进行状态切换
*
* @author huaisf
*
*/
public class CloseDoorState extends DoorState {
@Override
public void switchOperation(Context context) {
System.out.println("关门");
// 设置下一次状态为开门
context.setDoorState(new OpenDoorState());
}
}
public class OpenDoorState extends DoorState {
@Override
public void switchOperation(Context context) {
System.out.println("开门");
// 设置下一次状态为关门
context.setDoorState(new CloseDoorState());
}
}
新建测试类Test
public class Test {
public static void main(String[] args) {
Context context = new Context(new OpenDoorState());
context.switchOperation();
context.switchOperation();
context.switchOperation();
context.switchOperation();
}
}
十、策略模式
策略模式定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换,策略模式使得算法可独立于使用它的客户而变化。使用策略模式可自由切换算法,避免多重条件判断,提升扩展性。但每个策略对应一个类,复用性低。在策略模式中存在上下文(Context)、抽象策略角色(Strategy)、具体策略角色(ConcreteStrategy)三种角色。以打折促销为例,代码如下:
新建抽象策略DiscountStrategy
/**
* 抽象策略:定义策略
*
* @author huaisf
*
*/
public interface DiscountStrategy {
void buy();
}
新建具体策略OriginalPriceStrategy与EightDiscountStrategy
/**
* 具体策略:对抽象策略进行实现
*
* @author huaisf
*
*/
public class OriginalPriceStrategy implements DiscountStrategy {
@Override
public void buy() {
System.out.println("原价购买");
}
}
public class EightDiscountStrategy implements DiscountStrategy {
@Override
public void buy() {
System.out.println("八折购买");
}
}
新建上下文Context
/**
* 上下文:定义外部调用方法
*
* @author huaisf
*
*/
public class Context {
private DiscountStrategy discountStrategy;
public Context(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}
public void buy() {
discountStrategy.buy();
}
}
新建测试类Test
public class Test {
public static void main(String[] args) {
// 没有促销互动,原价购买商品
Context originalContext = new Context(new OriginalPriceStrategy());
originalContext.buy();
// 厂家促销,商品八折
Context eightContext = new Context(new EightDiscountStrategy());
eightContext.buy();
}
}
十一、访问者模式
访问者模式指封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。该模式中存在抽象访问者(Visitor)、具体访问者(ConcreteVisitor)、抽象元素(Element)、具体元素(ConcreteElement)、对象结构(Object Structure)五种角色。当对象结构比较稳定且对一个对象结构中的对象进行很多不同的且不相关的操作时可使用访问者模式。使用该模式后想增加对象操作只需增加具体访问者即可。以查账为例,账本结构固定,税务局查询到的是假账,公司内会计查到的是真账。代码如下:
新建抽象元素AccountBook
/**
* 抽象元素:定义账本接受操作
*
* @author huaisf
*
*/
public interface AccountBook {
/**
* 接受数据
* @param viewer
*/
void accept(Viewer viewer);
}
新建具体元素IncomeAccountBook与SpendingAccountBook
/**
* 具体元素:实现账本收入操作
*
* @author huaisf
*
*/
public class IncomeAccountBook implements AccountBook {
private int amount = 100000;
@Override
public void accept(Viewer viewer) {
viewer.view(this);
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
/**
* 具体元素:实现账本支出操作
*
* @author huaisf
*
*/
public class SpendingAccountBook implements AccountBook {
private int amount = 100000;
@Override
public void accept(Viewer viewer) {
viewer.view(this);
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
新建抽象访问者Viewer
/**
* 抽象访问者:定义每个具体元素访问方法
*
* @author huaisf
*
*/
public interface Viewer {
/**
* 查看收入账单
*
* @param incomeAccountBook
*/
void view(IncomeAccountBook incomeAccountBook);
/**
* 查看支出账单
*
* @param spendingAccountBook
*/
void view(SpendingAccountBook spendingAccountBook);
}
新建具体访问者AccountingViewer与RevenueViewer
/**
* 具体访问者:对抽象访问者方法进行实现,会计查到的是真账
*
* @author huaisf
*
*/
public class AccountingViewer implements Viewer {
@Override
public void view(IncomeAccountBook incomeAccountBook) {
System.out.println("财务人员查看收入:" + incomeAccountBook.getAmount());
}
@Override
public void view(SpendingAccountBook spendingAccountBook) {
System.out.println("财务人员查看支出:" + spendingAccountBook.getAmount());
}
}
/**
* 具体访问者:对抽象访问者方法进行实现,税务局查到的是假账
*
* @author huaisf
*
*/
public class RevenueViewer implements Viewer {
@Override
public void view(IncomeAccountBook incomeAccountBook) {
System.out.println("税务局查看收入:" + incomeAccountBook.getAmount() / 10);
}
@Override
public void view(SpendingAccountBook spendingAccountBook) {
System.out.println("税务局查看支出:" + spendingAccountBook.getAmount() * 10);
}
}
新建对象结构AccountBookStructure
/**
* 对象结构:存储元素并提供遍历所有元素的方法供外部调用
*
* @author huaisf
*
*/
public class AccountBookStructure {
private List accountBooks = new ArrayList();
public void add(AccountBook accountBook) {
accountBooks.add(accountBook);
}
public void show(Viewer viewer) {
for (AccountBook accountBook : accountBooks) {
accountBook.accept(viewer);
}
}
}
新建测试类Test
public class Test {
public static void main(String[] args) {
AccountBookStructure accountBookStructure = new AccountBookStructure();
accountBookStructure.add(new IncomeAccountBook());
accountBookStructure.add(new SpendingAccountBook());
// 税务局查账
accountBookStructure.show(new RevenueViewer());
// 会计查账
accountBookStructure.show(new AccountingViewer());
}
}
你可能感兴趣的:(设计模式,设计模式)
鸿蒙开发新视角:用ArkTS解锁责任链模式
谢道韫689
鸿蒙随笔 开发语言 ArkTS
责任链模式:概念与原理责任链模式(ChainofResponsibilityPattern)是一种行为型设计模式,它将多个处理者对象连接成一条链,并将请求沿着链传递,直到有一个处理者能够处理该请求。这种模式的核心思想是将请求的发送者和接收者解耦,使得系统更加灵活和可扩展。举个生活中的例子,在公司的请假流程中,员工提交请假申请后,可能需要经过组长、部门经理、总经理等多个层级的审批。如果请假天数较少,
java继承后 赋值返回_Java基础进阶 第三天 单例模式、继承、final
weixin_39757212
java继承后 赋值返回
今日任务1、能够理解单例设计模式2、能够独立使用继承3、能够独立使用final关键字1.代码块1.1.代码块的概念和格式代码块,就是使用大括号括起来的一段代码;书写格式:{代码;}1.2.代码块的分类1.2.1.静态代码块静态代码块,就是使用static修饰的代码块,直接写在类中的代码块;classDemo{static{System.out.pintln("静态代码块")}}2.png静态代码块
创建者模式——单例模式
yiyiqwq
软件设计模式 单例模式 java
3.1单例模式(Singleton)单例模式(Singleton)是一种非常简单且容易理解的设计模式。顾名思义,单例即单一的实例,确切地讲就是指在某个系统中只存在一个实例,同时提供集中、统一的访问接口,以使系统行为保持协调一致。Singleton一词在逻辑学中指“有且仅有一个元素的集合”,这非常恰当地概括了单例的概念,也就是“一个类仅有一个实例”。单例模式涉及到类负责创建自己的对象,同时保证只有该
【知识分享】C语言中的设计模式——表驱动模式
知识噬元兽
知识分享 # 设计模式 c语言 设计模式 开发语言
背景 其实在《设计模式——可利用面向对象软件的基础》一书中,提及的23种设计模式里并没有表驱动这种模式,因为《设计模式》一书更多的是根据面向对象的应用提取出来的设计方法。而表驱动模式本身是强烈依赖于数组这种数据结构的,跟对象扯不上关系,所以没有被收录在此书中。但由于它在C语言中的影响力之大,适用面之广,所以被收录在了《代码大全》(这可是另一本经典著作呀)一书中。名词释义 表驱动本身是强
C语言和设计模式(总结篇) 用了多年的C
小可嵌入式
编程语言 c语言 设计模式 1024程序员节
设计模式的书相信很多人都看过。对于设计模式这样一种方法,相信不同的人有不同的理解。我在这里写的博客只是我个人对设计模式的粗浅认识。文中肯定存在很多的不足和不成熟之处,希望朋友们谅解。望大家多多指正,谢谢!01)C语言和设计模式(继承、封装、多态)02)C语言和设计模式(访问者模式)03)C语言和设计模式(状态模式)04)C语言和设计模式(命令模式)05)C语言和设计模式(解释器模式)06)C语言和
【C++】模拟实现栈和队列
不吃肉的Humble
走进C++的世界 c++ 开发语言
目录一.设计模式二.stack的模拟实现三.queue的模拟实现四.deque的简单介绍(了解)五.课后习题在我们用C++模拟实现之前在C语言阶段的实现过的数据结构时,我们会想用更加舒服的方式写代码,这时我们就要用到设计模式那么我们就要先了解一下什么是设计模式?一.设计模式设计模式是前辈们对代码开发经验的总结,是解决特定问题的一系列套路比如适配器模式,迭代器模式迭代器模式:迭代器封装后提供统一的访
【JAVA面试题】设计模式之原型模式
今天你慧了码码码码码码码码码码
JAVA面试题 原型模式 java 设计模式
【JAVA面试题】设计模式之原型模式一、原型模式核心概念原型模式(PrototypePattern)是一种创建型设计模式,通过复制现有对象(原型)来创建新对象,避免反复初始化带来的性能损耗。适用于需要高频创建相似对象的场景。二、原型模式实战案例:敌机生成优化1.原始方案性能缺陷publicclassClient{publicstaticvoidmain(String[]args){Listenem
(十 八)趣学设计模式 之 观察者模式!
码熔burning
设计模式 设计模式 观察者模式 Java
目录一、啥是观察者模式?二、为什么要用观察者模式?三、观察者模式的实现方式四、观察者模式的优缺点五、观察者模式的应用场景六、总结我的其他文章也讲解的比较有趣,如果喜欢博主的讲解方式,可以多多支持一下,感谢!了解状态模式请看:(十七)趣学设计模式之状态模式!✨更多请看个人主页:码熔burning这篇文章带你详细认识一下设计模式中的观察者模式一、啥是观察者模式?想象一下,你订阅了一个你喜欢的博主的博客
两周学习安排
3分人生
学习
日常安排白天看MySQL实战45讲,每日一讲看图解设计模式每天1-2道力扣算法题(难度中等以上)每天复习昨天的单词,记20个单词,写一篇阅读晚上写服创项目每日产出MySQL实战45讲读书笔记设计模式读书笔记力扣算法题ac记录单词本截图项目接口文档记录,git提交记录第二周MySQL:精读第1-6讲设计模式:学习工厂方法、抽象工厂、单例、建造者、适配器、桥接模式算法:每日1-2题第三周MySQL:精
设计模式学习--观察者模式(Observer Pattern)
小巫技术博客
【技能提升之设计模式】 Head First 设计模式学习记录 设计模式
设计模式学习--观察者模式(OberserPattern)2013年5月18日天气:热!下午15:28设计模式学习中学习者:小巫什么是观察者模式?定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。怎么设计一个观察者模式的程序?确定两个对象:1.主题2.观察者确定这两个对象之间的关系:主题对象管理某些数据,一旦数据发生改变,会主动向观察者进行通知,然而
【创建型设计模式】原型设计模式
可有道?
c#设计模式 设计模式 开发语言 c# java 原型模式
引言我们在学习每一个设计模式之前,我们就应该带着问题去学习,这样才会找到我们想要的答案,而且让我们理解的更透彻,记忆的更深刻,比如:解决了一个什么问题,使用场景等。而最好的方法就是通过例子去敲代码去感受,去理解。案列供应商的信息类:供应商名称,供应商经营范围,供应商编号。现在假设我们需要复制三份供应商对象初始代码staticvoidMain(string[]args){Providerprovid
软件设计和软件架构之间的区别
前网易架构师-高司机
软件架构 软件设计 系统架构
作者简介:高科,先后在IBMPlatformComputing从事网格计算,淘米网,网易从事游戏服务器开发,拥有丰富的C++,go等语言开发经验,mysql,mongo,redis等数据库,设计模式和网络库开发经验,对战棋类,回合制,moba类页游,手游有丰富的架构设计和开发经验。并且深耕深度学习和数据集训练,提供商业化的视觉人工智能检测和预警系统(煤矿,工厂,制造业,消防等领域的工业化产品),合
Java中常见的设计模式
皮克斯的进化之路
java 设计模式 开发语言
设计模式是软件设计中针对常见问题的可复用解决方案,它们提供了代码组织和架构的最佳实践,Java中常见的设计模式可分为创建型、结构型和行为型三类。下面就给大家介绍一些常用的设计模式和案例。创建型模式:管理对象创建1.单例模式确保一个类只有一个实例,并且提供了一种访问其唯一对象的方式,不需要再实例化该类对象,可直接访问,避免重复消耗资源。(1)懒汉式publicclassSingleton{/*持有私
SpringBoot常用注解,一文搞懂!
码熔burning
SpringBoot spring boot java 后端
目录一、核心注解(CoreAnnotations)二、Web相关注解三、数据访问相关注解四、其他常用注解五、AOP相关注解六、总结我的其他文章也讲解的比较有趣,如果喜欢博主的讲解方式,可以多多支持一下,感谢!✨想了解设计模式知识请看设计模式专栏:设计模式专栏✨更多请看个人主页:码熔burning(喜欢的话可以关注,嘿嘿)这篇文章来总结以下SpringBoot中的常用注解一、核心注解(CoreAnn
【第13节】C++设计模式(行为模式)-Template( 模板)模式
攻城狮7号
c++版本设计模式 c++ 设计模式 模板方法模式
一、问题的提出Template模式:算法步骤框架与细节实现的分离假设我们正在开发一个文档处理系统,需要支持多种文档格式的导出(如PDF、Word、HTML等)。每种文档格式的导出过程大致相同,都包含以下步骤:(1)准备文档内容:获取需要导出的文档数据。(2)格式化文档:根据具体格式对文档进行格式化(如PDF的特殊排版、Word的样式设置等)。(3)生成文件:将格式化后的文档保存为具体格式的文件。(
腾讯集团软件开发-后台开发方向内推
飞300
业界资讯 mysql java
熟练掌握C/C++/Java/Go等其中一门开发语言;TCP/UDP网络协议及相关编程、进程间通讯编程;专业软件知识,包括算法、操作系统、软件工程、设计模式、数据结构、数据库系统、网络安全等有一定了解的:1、Python、Shell、Perl等脚本语言;2、MySQL及SQL语言、编程;3、NoSQL,Key-value存储原理。1、深入理解业务需求和产品设计,高效地实现并优化产品功能;2、持续优
Qt实现登录界面(C++)
DarcyCode
qt c++ 命令模式 C/C++
Qt实现登录界面(C++)在本文中,我将向您展示如何使用Qt框架和C++语言实现一个简单的登录界面。我们将创建一个具有用户名和密码输入字段以及登录按钮的窗口,并验证用户输入的凭据。首先,确保您的开发环境中已经安装了Qt框架。然后,创建一个新的QtWidgets项目,并按照以下步骤进行操作。步骤1:设计界面打开QtCreator,并在设计模式下创建一个新的窗口类。将窗口的标题设置为“登录”或其他您喜
【设计模式】破解单例模式:反射、序列化与克隆攻击的防御之道
后端java设计模式
可能有的小伙伴看了我上一篇文章里几种方式对比的表格,觉得枚举有缺点,为什么JoshuaBloch还推荐使用枚举?这就要提到单例的破解了。普通的单例模式是可以通过反射和序列化/反序列化来破解的,而Enum由于自身的特性问题,是无法破解的。当然,由于这种情况基本不会出现,因此我们在使用单例模式的时候也比较少考虑这个问题。枚举类是实现单例模式最好的方式在单例模式的实现中,除去枚举方法实现的单例模式,其它
基于PO实现web自动化,实行性能测试
程序员的世界你不懂
playwright javascript 前端 自动化 百度
使用Playwright框架可以大大提高测试的效率和可维护性。本文将探讨如何运用页面对象模型(POM)来提升Playwright的自动化测试实践,确保代码结构清晰、易于维护。1.什么是页面对象模型?页面对象模型(POM)是一种设计模式,通过将页面元素和操作封装在对象中,使测试代码更加整洁且可重用。每个页面对象对应于应用中的一个页面,封装了该页面的元素和操作方法,从而隔离测试代码与页面细节的变化。2
类似ComfyUI和Midjourney这样的文生图图生图应用的API与服务架构该怎么设计
nine是个工程师
谈谈架构 midjourney 架构
开发|界面|引擎|交付|副驾——重写全栈法则:AI原生的倍速造应用流来自全栈程序员nine的探索与实践,持续迭代中。欢迎评论私信交流。1.API设计模式1.1ComfyUI的API架构ComfyUI作为开源文生图工具的代表,其API架构设计为我们理解此类应用提供了很好的参考模型。ComfyUI的核心API架构采用了灵活的端点设计,主要包含五个关键端点:/ws:WebSocket端点,用于实时状态更
JQuery是什么
编程芝士
Java基础学习
jQuery是什么概念:一个JavaScript框架。简化JS开发jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“writeLess,DoMore”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,
React组件化深度解析(二):从受控组件到生命周期现代化
咔咔库奇
react javascript 前端 开发语言
目录一、组件设计哲学:控制与自由的博弈1.受控组件vs非受控组件:灵魂三问核心差异对比表选型决策树二、复合组件模式:隐式状态共享的艺术1.CompoundComponents设计模式实现原理四部曲2.手写可配置的Accordion组件三、生命周期现代化:从类组件到Hooks的迁移指南1.类组件生命周期图谱(React18版)React18关键变更2.useEffect与生命周期的映射关系精准对应关
责任链模式详解和在Spring Boot 项目中的使用场景
冰糖心书房
设计模式 Java 开发 责任链模式 spring boot java
责任链模式详解1.定义:责任链模式(ChainofResponsibilityPattern)是一种行为型设计模式。它将请求的发送者和接收者解耦,允许你将请求沿着处理者链进行传递,直到有一个处理者处理它为止。每个处理者都包含对下一个处理者的引用,形成一条链。2.结构:Handler(抽象处理者):定义一个处理请求的接口,并维护一个指向下一个处理者的引用。ConcreteHandler(具体处理者)
Kotlin观察者模式
tangweiguo03051987
kotlin 观察者模式 java
观察者模式是一种设计模式,它定义了对象之间的一对多依赖关系,当一个对象改变状态时,所有依赖于它的对象都会得到通知并自动更新。这种模式在许多编程场景中非常有用,例如事件处理、数据绑定和通知系统。观察者模式的主要组成部分主题(Subject):维护观察者的列表,并提供添加和删除观察者的方法。当主题的状态发生变化时,它会通知所有观察者。观察者(Observer):定义了一个更新接口,当主题状态发生变化时
iOS中的设计模式(六)- 单利模式
胖虎1
iOS中的设计模式 设计模式 单利模式 iOS中单利 Swift单利 OC单利
引言在iOS开发中,单例模式(SingletonPattern)是一种非常常见且实用的设计模式。它通过确保某个类只有一个实例,并提供一个全局的访问点,帮助开发者管理共享资源或提供全局配置。在许多应用场景中,我们需要确保某些对象在整个应用中只有一个实例,以避免资源浪费或不一致的状态。例如,在网络请求管理、数据库连接、日志记录等场景中,单例模式可以简化对象的管理,避免重复创建和销毁实例,提高性能。然而
微服务架构:深入理解与实践
需要重新演唱
微服务 架构 微服务 云原生
微服务架构:深入理解与实践引言在当今的软件开发领域,微服务架构(MicroservicesArchitecture)已经成为一种流行的设计模式。与传统的单体应用(MonolithicApplication)相比,微服务架构将应用程序拆分成一系列小型、独立的服务,每个服务运行在自己的进程中,通过轻量级机制(如HTTPRESTfulAPI)进行通信。这种架构模式提供了更高的灵活性、可扩展性和可维护性,
设计模式概述--七大设计原则
仰望星空@脚踏实地
设计模式
设计模式(DesignPattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。1995年,GoF(GangofFour,四人组/四人帮)合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了23种设计模式,从此树立了软件设计模式领域的里程碑,人称「GoF设计模式」。面向对象设计原则
软件架构的23个基本原则:构建稳健、可扩展的系统
潘多编程
java 开发语言
软件架构是任何软件项目成功的关键。良好的架构不仅能够支撑软件的功能实现,还能确保其性能、可维护性、可扩展性和安全性。在软件工程领域,经过多年的研究和实践,已经总结出了许多宝贵的原则和模式,用以指导软件架构的设计。以下是软件架构的23个基本原则,这些原则涵盖了从设计模式到架构风格,从组件交互到系统集成的方方面面,旨在帮助软件工程师和架构师构建更加稳健、可扩展的系统。单一职责原则(SRP)每个模块或类
ThinkPHP运行目录设置为public子目录
NightReader
运维
ThinkPHP是一个快速、兼容和简单的面向对象的PHP框架,它遵循MVC(模型-视图-控制器)设计模式。在ThinkPHP框架中,public目录扮演着非常重要的角色,它被设计为框架的公共访问目录。Public目录设置的原因和解决方案是ThinkPHP框架结构和安全策略的核心部分。原因:1)安全性:将public设为唯一的公共访问目录可以增强应用的安全性。通过限制对框架其他部分的访问,可以防止潜
深度解析与实践:外观模式
代码世界的浪客
java设计模式深度详解 外观模式
1.什么是外观模式1.1外观模式的定义外观模式(FacadePattern)是一种结构性设计模式,它为复杂的子系统提供一个更简单、更易用的接口。通过这种方式,外部客户端无需直接与复杂的子系统交互,而是通过一个统一的外观类来访问子系统的功能。外观模式主要用于简化客户程序与复杂系统之间的接口。1.2为什么需要外观模式当程序需要处理多个子系统的复杂交互时,直接操作这些子系统可能会给客户端带来很大的负担。
矩阵求逆(JAVA)初等行变换
qiuwanchi
矩阵求逆(JAVA)
package gaodai.matrix;
import gaodai.determinant.DeterminantCalculation;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* 矩阵求逆(初等行变换)
* @author 邱万迟
*
JDK timer
antlove
java jdk schedule code timer
1.java.util.Timer.schedule(TimerTask task, long delay):多长时间(毫秒)后执行任务
2.java.util.Timer.schedule(TimerTask task, Date time):设定某个时间执行任务
3.java.util.Timer.schedule(TimerTask task, long delay,longperiod
JVM调优总结 -Xms -Xmx -Xmn -Xss
coder_xpf
jvm 应用服务器
堆大小设置JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
典型设置:
java -Xmx
JDBC连接数据库
Array_06
jdbc
package Util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCUtil {
//完
Unsupported major.minor version 51.0(jdk版本错误)
oloz
java
java.lang.UnsupportedClassVersionError: cn/support/cache/CacheType : Unsupported major.minor version 51.0 (unable to load class cn.support.cache.CacheType)
at org.apache.catalina.loader.WebappClassL
用多个线程处理1个List集合
362217990
多线程 thread list 集合
昨天发了一个提问,启动5个线程将一个List中的内容,然后将5个线程的内容拼接起来,由于时间比较急迫,自己就写了一个Demo,希望对菜鸟有参考意义。。
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public c
JSP简单访问数据库
香水浓
sql mysql jsp
学习使用javaBean,代码很烂,仅为留个脚印
public class DBHelper {
private String driverName;
private String url;
private String user;
private String password;
private Connection connection;
privat
Flex4中使用组件添加柱状图、饼状图等图表
AdyZhang
Flex
1.添加一个最简单的柱状图
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
<?xml version=
"1.0"&n
Android 5.0 - ProgressBar 进度条无法展示到按钮的前面
aijuans
android
在低于SDK < 21 的版本中,ProgressBar 可以展示到按钮前面,并且为之在按钮的中间,但是切换到android 5.0后进度条ProgressBar 展示顺序变化了,按钮再前面,ProgressBar 在后面了我的xml配置文件如下:
[html]
view plain
copy
<RelativeLa
查询汇总的sql
baalwolf
sql
select list.listname, list.createtime,listcount from dream_list as list , (select listid,count(listid) as listcount from dream_list_user group by listid order by count(
Linux du命令和df命令区别
BigBird2012
linux
1,两者区别
du,disk usage,是通过搜索文件来计算每个文件的大小然后累加,du能看到的文件只是一些当前存在的,没有被删除的。他计算的大小就是当前他认为存在的所有文件大小的累加和。
AngularJS中的$apply,用还是不用?
bijian1013
JavaScript AngularJS $apply
在AngularJS开发中,何时应该调用$scope.$apply(),何时不应该调用。下面我们透彻地解释这个问题。
但是首先,让我们把$apply转换成一种简化的形式。
scope.$apply就像一个懒惰的工人。它需要按照命
[Zookeeper学习笔记十]Zookeeper源代码分析之ClientCnxn数据序列化和反序列化
bit1129
zookeeper
ClientCnxn是Zookeeper客户端和Zookeeper服务器端进行通信和事件通知处理的主要类,它内部包含两个类,1. SendThread 2. EventThread, SendThread负责客户端和服务器端的数据通信,也包括事件信息的传输,EventThread主要在客户端回调注册的Watchers进行通知处理
ClientCnxn构造方法
&
【Java命令一】jmap
bit1129
Java命令
jmap命令的用法:
[hadoop@hadoop sbin]$ jmap
Usage:
jmap [option] <pid>
(to connect to running process)
jmap [option] <executable <core>
(to connect to a
Apache 服务器安全防护及实战
ronin47
此文转自IBM.
Apache 服务简介
Web 服务器也称为 WWW 服务器或 HTTP 服务器 (HTTP Server),它是 Internet 上最常见也是使用最频繁的服务器之一,Web 服务器能够为用户提供网页浏览、论坛访问等等服务。
由于用户在通过 Web 浏览器访问信息资源的过程中,无须再关心一些技术性的细节,而且界面非常友好,因而 Web 在 Internet 上一推出就得到
unity 3d实例化位置出现布置?
brotherlamp
unity教程 unity unity资料 unity视频 unity自学
问:unity 3d实例化位置出现布置?
答:实例化的同时就可以指定被实例化的物体的位置,即 position
Instantiate (original : Object, position : Vector3, rotation : Quaternion) : Object
这样你不需要再用Transform.Position了,
如果你省略了第二个参数(
《重构,改善现有代码的设计》第八章 Duplicate Observed Data
bylijinnan
java 重构
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusE
struts2更改struts.xml配置目录
chiangfai
struts.xml
struts2默认是读取classes目录下的配置文件,要更改配置文件目录,比如放在WEB-INF下,路径应该写成../struts.xml(非/WEB-INF/struts.xml)
web.xml文件修改如下:
<filter>
<filter-name>struts2</filter-name>
<filter-class&g
redis做缓存时的一点优化
chenchao051
redis hadoop pipeline
最近集群上有个job,其中需要短时间内频繁访问缓存,大概7亿多次。我这边的缓存是使用redis来做的,问题就来了。
首先,redis中存的是普通kv,没有考虑使用hash等解结构,那么以为着这个job需要访问7亿多次redis,导致效率低,且出现很多redi
mysql导出数据不输出标题行
daizj
mysql 数据导出 去掉第一行 去掉标题
当想使用数据库中的某些数据,想将其导入到文件中,而想去掉第一行的标题是可以加上-N参数
如通过下面命令导出数据:
mysql -uuserName -ppasswd -hhost -Pport -Ddatabase -e " select * from tableName" > exportResult.txt
结果为:
studentid
phpexcel导出excel表简单入门示例
dcj3sjt126com
PHP Excel phpexcel
先下载PHPEXCEL类文件,放在class目录下面,然后新建一个index.php文件,内容如下
<?php
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
if (PHP_SAPI == 'cli')
die('
爱情格言
dcj3sjt126com
格言
1) I love you not because of who you are, but because of who I am when I am with you. 我爱你,不是因为你是一个怎样的人,而是因为我喜欢与你在一起时的感觉。 2) No man or woman is worth your tears, and the one who is, won‘t
转 Activity 详解——Activity文档翻译
e200702084
android UI sqlite 配置管理 网络应用
activity 展现在用户面前的经常是全屏窗口,你也可以将 activity 作为浮动窗口来使用(使用设置了 windowIsFloating 的主题),或者嵌入到其他的 activity (使用 ActivityGroup )中。 当用户离开 activity 时你可以在 onPause() 进行相应的操作 。更重要的是,用户做的任何改变都应该在该点上提交 ( 经常提交到 ContentPro
win7安装MongoDB服务
geeksun
mongodb
1. 下载MongoDB的windows版本:mongodb-win32-x86_64-2008plus-ssl-3.0.4.zip,Linux版本也在这里下载,下载地址: http://www.mongodb.org/downloads
2. 解压MongoDB在D:\server\mongodb, 在D:\server\mongodb下创建d
Javascript魔法方法:__defineGetter__,__defineSetter__
hongtoushizi
js
转载自: http://www.blackglory.me/javascript-magic-method-definegetter-definesetter/
在javascript的类中,可以用defineGetter和defineSetter_控制成员变量的Get和Set行为
例如,在一个图书类中,我们自动为Book加上书名符号:
function Book(name){
错误的日期格式可能导致走nginx proxy cache时不能进行304响应
jinnianshilongnian
cache
昨天在整合某些系统的nginx配置时,出现了当使用nginx cache时无法返回304响应的情况,出问题的响应头: Content-Type:text/html; charset=gb2312 Date:Mon, 05 Jan 2015 01:58:05 GMT Expires:Mon , 05 Jan 15 02:03:00 GMT Last-Modified:Mon, 05
数据源架构模式之行数据入口
home198979
PHP 架构 行数据入口
注:看不懂的请勿踩,此文章非针对java,java爱好者可直接略过。
一、概念
行数据入口(Row Data Gateway):充当数据源中单条记录入口的对象,每行一个实例。
二、简单实现行数据入口
为了方便理解,还是先简单实现:
<?php
/**
* 行数据入口类
*/
class OrderGateway {
/*定义元数
Linux各个目录的作用及内容
pda158
linux 脚本
1)根目录“/” 根目录位于目录结构的最顶层,用斜线(/)表示,类似于
Windows
操作系统的“C:\“,包含Fedora操作系统中所有的目录和文件。 2)/bin /bin 目录又称为二进制目录,包含了那些供系统管理员和普通用户使用的重要
linux命令的二进制映像。该目录存放的内容包括各种可执行文件,还有某些可执行文件的符号连接。常用的命令有:cp、d
ubuntu12.04上编译openjdk7
ol_beta
HotSpot jvm jdk OpenJDK
获取源码
从openjdk代码仓库获取(比较慢)
安装mercurial Mercurial是一个版本管理工具。 sudo apt-get install mercurial
将以下内容添加到$HOME/.hgrc文件中,如果没有则自己创建一个: [extensions] forest=/home/lichengwu/hgforest-crew/forest.py fe
将数据库字段转换成设计文档所需的字段
vipbooks
设计模式 工作 正则表达式
哈哈,出差这么久终于回来了,回家的感觉真好!
PowerDesigner的物理数据库一出来,设计文档中要改的字段就多得不计其数,如果要把PowerDesigner中的字段一个个Copy到设计文档中,那将会是一件非常痛苦的事情。