자바 상용 디자인 모델 학습 총화

27810 단어
상용 디자인 모델 요약:
창설 형: 단일 모드, 공장 방법 모드 등
구조 형: 정적 에이전트 모드, 동적 에이전트 모드, 장식 자 모드, 어댑터 모드, 브리지 모드
행위 형: 관찰자 모드, 명령 모드, 책임 체인 모드, 상태 모드, 방문 자 모드
1. 단일 모드
응용 장면: 말 그대로 처음부터 끝까지 같은 대상 을 조작 할 때 단일 모델 을 사용 해 야 한다.
​/**
 *      (    )
 */
public class SingletonPatternLazy {
	
	private SingletonPatternLazy() {}
	
	public static SingletonPatternLazy getInstance () {
		return SingletonPatternInstance.singletonPatternLazy;
	}
	
	private static class SingletonPatternInstance {
		final static SingletonPatternLazy singletonPatternLazy = new SingletonPatternLazy();
	}
	
	public static void main(String[] args) {
		SingletonPatternLazy instance1 = SingletonPatternLazy.getInstance();
		SingletonPatternLazy instance2 = SingletonPatternLazy.getInstance();
		
		System.out.println(instance1 == instance2);
	}

}

​/**
 *      (    )
 */
public class SingletonPattern {
	
	private SingletonPattern() {}
	
	private final static SingletonPattern singletonPattern = new SingletonPattern();
	
	public static SingletonPattern getInstance() {
		return singletonPattern;
	}

	public static void main(String[] args) {
		SingletonPattern instance1 = SingletonPattern.getInstance();
		SingletonPattern instance2 = SingletonPattern.getInstance();
		System.out.println(instance1 == instance2);
	}

}

단일 모드 최적화 업그레이드 버 전 (추천)
/**
 *      (        )
 */
public class SingletonPatternLazy {

	private static SingletonPatternLazy instance = null;

	private SingletonPatternLazy() {
	}

	public static SingletonPatternLazy getInstance() {
		if (instance == null) {
			newInstance();
		}
		return instance;
	}

	private synchronized static void newInstance() {
		if (instance == null) {
			instance = new SingletonPatternLazy();
		}
	}

	public static void main(String[] args) {
		
		for(int i = 0; i < 100; i ++) {
			new Thread(() -> System.out.println(SingletonPatternLazy.getInstance())).start();
		}

	}

}

 
2. 공장 방법 모델
응용 필드:
우 리 는 같은 규범 에서 서로 다른 실현 대상 을 얻 고 이런 대상 을 얻 을 때 비교적 번 거 로 운 상황 에서 공장 모델 을 사용 하 는 것 을 고려 할 수 있다.
확장 규범 이 실 현 될 때 공장 을 확장 해 야 한다. 확장 에 편리 하고 개폐 원칙 에 적응 하기 위해 공장 방법 모델 이 생 겼 다. 즉, 한 공장 은 규범 아래 의 실현 대상 만 만 만 들 었 다.
서로 다른 대상 이 서로 다른 공장 을 만 들 면 서로 다른 공장 들 은 하나의 템 플 릿 을 추상 화하 거나 인 터 페 이 스 를 미리 정의 할 수 있다.
​
/*
 *           source
 */
//Person  
public interface Person {
	void work();
}

//Person       ,Programmer
public class Programmer implements Person {
	@Override
	public void work() {
		System.out.println("   work");
	}
}

/*
 *     
 */
//    
public interface PersonFactory {
	Person getInstance();
}

//         ProgrammerFactory 
public class ProgrammerFactory implements PersonFactory {

	private Programmer programmer;
	
	@Override
	public Person getInstance() {
		if(programmer == null) {
			newInstance();
		}
		return programmer;
	}
	
	private synchronized void newInstance() {
		if(programmer == null) {
			programmer = new Programmer();
		}
	}

}

/*
 *         
 */
public class PersonFactoryBuilder {

	
	public static PersonFactory build(Class extends PersonFactory> clazz) {
		try {
			return clazz.newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static void main(String[] args) {
		PersonFactory personFactory = PersonFactoryBuilder.build(ProgrammerFactory.class);
		for(int i = 0; i < 100; i ++) {
			new Thread(() -> System.out.println(personFactory.getInstance())).start();
		}
		
	}
	
}

3. 정적 에이전트 모드
응용 장면: 많이 사용 하지 않 습 니 다. 보통 동적 대 리 를 사용 합 니 다.
//      
public interface IPerson {
	void doSome();
}

//      
public class Person implements IPerson{
	
	public void doSome(){
		System.out.println("    ...");
	}
	
}

//   
public class PersonProxy implements IPerson{
	
	private IPerson person;
	
    //            
	public PersonProxy(IPerson person){
		this.person = person;
	}
	
	public void doSome(){
		before();
		person.doSome();
		after();
	}
	
	public void before(){
		System.out.println("before...");
	}
	
	public void after(){
		System.out.println("after...");
	}
}

/*
 *      
 */
public static void testProxy(){
	IPerson proxy = new PersonProxy(new Person());
	proxy.doSome();
}

4. 동적 에이전트 모드
응용 장면: spring 의 op 바 텀 은 동적 대 리 를 바탕 으로 하 는 것 입 니 다. 우 리 는 가로로 프로그램 을 확장 해 야 합 니 다. 즉, 임의의 대상 을 확장 하 는 방법 이 필요 할 때 동적 대 리 를 사용 할 수 있 습 니 다.
jdk 동적 에이전트
//     
public interface ISource {
	void doSome(String inputSome);
}

//      
public class SourceImpl implements ISource{
	
	public void doSome(String inputSome){
		System.out.println("    ,    :" + inputSome);
	}
	
}

//               
public class BeforeAfterInvocationHandler implements InvocationHandler {
	
	private Object source;

	public BeforeAfterInvocationHandler(Object source){
		this.source = source;
	}
	
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		before();
		method.invoke(source, args);
		after();
		return null;
	}
	
	
	public void before(){
		System.out.println("------  before-------");
	}
	
	public void after(){
		System.out.println("------  after-------");
	}
	
	/**
	 *   t       
	 * @param t       
	 * @return       
	 */
	@SuppressWarnings("all")
	public static  T getProxy(T t){
		BeforeAfterInvocationHandler invocationHandler = new BeforeAfterInvocationHandler(t);
		Class[] interfaces = t.getClass().getInterfaces();
		T tProxy = (T) Proxy.newProxyInstance(invocationHandler.getClass().getClassLoader(), interfaces, invocationHandler);
		return tProxy;
	}
	
}

//      
public static void testDynamicProxy(){
	ISource source = new SourceImpl();
	BeforeAfterInvocationHandler.getProxy(source).doSome("             ");
}

cglib 동적 에이전트
cglib 에 의존:
    cglib     cglib     3.3.0
//    
public class Programmer {
	
	public String getUsername() {
		return "lucy";
	}

	public void doSome() {
		System.out.println("   doSome()");
	}

}

//      
public class CGlibProxyHandler implements MethodInterceptor {
	
	public Object createProxy(Object source){
		Enhancer enhancer = new Enhancer();
		enhancer.setCallback(this);
		enhancer.setSuperclass(source.getClass());
		return enhancer.create();
	}

	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		before(obj, args);
		Object object = proxy.invokeSuper(obj, args);
		after(object);
		return object;
	}
	
	//    
	private void before(Object obj, Object[] args) {
		System.out.println("before:" + obj.getClass().getSuperclass().getName());
	}
	
	//    
	private void after(Object object) {
		System.out.println("after:" + JSONObject.toJSONString(object));
	}
	
	@SuppressWarnings("unchecked")
	public static  T getProxy(T t){
		CGlibProxyHandler handler = new CGlibProxyHandler();
		return (T) handler.createProxy(t);
	}

}

//  
public static void main(String[] args) {
	Programmer proxy = CGlibProxyHandler.getProxy(new Programmer());
	String name = proxy.getUsername();
	System.out.println(name);
	proxy.doSome();
}

 
5. 장식 자 모드
응용 장면: 우리 가 동적 인 가로 확장 프로그램 이 필요 할 때, 즉 특정한 대상 을 동적 으로 확장 하 는 방법 으로 장식 자 모드 를 사용 할 수 있 습 니 다.
동적 에이전트 와 의 차이 점 주의:
동적 대 리 는 임의의 대상 을 확장 하 는 방법 이지 만 확장 내용 은 고정 적 으로 변 하지 않 습 니 다.
장식 자 모드 는 특정한 대상 의 방법 을 확장 하고 확장 하 는 내용 은 동적 으로 변화 할 수 있다.
//      
public interface IPerson {
	void doSome();
}

//        
public class PersonImpl implements IPerson {

	public void doSome() {
		System.out.println("    ....");
	}

}

//     
public abstract class PersonDecorator implements IPerson {
	
	private IPerson person;
	
	public PersonDecorator(IPerson person){
		this.person = person;
	}
	
	//          person   dosome()
	public void doSome() {
		person.doSome();
	}

}

//   Student
public class Student extends PersonDecorator {
	
	//        person  
	public Student(IPerson person){
		//         
		super(person);
	}
	
	public void doSome(){

		/*
		 *  ,     doSome()
		 *  ,              person   dosome()
		 */
		super.doSome();
		System.out.println("    ...");
	}
}

//   Worker
public class Worker extends PersonDecorator {
	
	public Worker(IPerson person){
		super(person);
	}
	
	public void doSome(){
		super.doSome();
		System.out.println("    ...");
	}

}

//       
public static void testDecorator(){
	//   person
	PersonImpl person = new PersonImpl();
	System.out.println("--------------person: --------------");
	//   person    
	person.doSome();

	// worker      person
	Worker worker = new Worker(person);
	System.out.println("--------------worker: --------------");
	// worker    person    
	worker.doSome();

	//       worker
	Student student = new Student(worker);
	System.out.println("--------------student: --------------");
	//       worker    
	student.doSome();
}

6. 어댑터 모드
응용 장면: 예 를 들 어 응용 에 A 류 가 하나 있 고 규범 이 하나 있 으 며 규범 화 된 특정한 방법 이나 여러 가지 방법 이 A 류 와 똑 같은 실현 을 가지 기 때문에 이런 방법 을 따로 실현 할 필요 가 없다. 추상 적 인 어댑터 류 를 추가 하고 유형 A 를 직접 계승 한 다음 에 새로운 추상 적 인 규범 을 정의 할 수 있다.
//    
public class Animal {
	public void eat() {
		System.out.println("eat()*************************");
	}
}

//    Animal   
public interface IPerson {	
	public void doWork();	
}

//   
public class AnimalAdpter extends Animal implements IPerson {

	@Override
	public void doWork() {
		before();
		super.eat();
		after();
	}
	
	private void before() {
		System.out.println("AnimalAdpter.before()*************************");
	}
	
	private void after() {
		System.out.println("AnimalAdpter.after()*************************");
	}
	
	public static void main(String[] args) {
		IPerson person = new AnimalAdpter();
		person.doWork();
	}

}

7. 브리지 모드
응용 장면: 우리 가 조작 규범 이 필요 하지만 고정 적 으로 실현 할 수 없 을 때 한 조 의 규범 을 제공 하여 고객 측 이 실현 하도록 할 수 있다. 우리 가 조작 할 때 고객 측의 실현 대상 만 주입 해 야 한다. 이런 모델 은 바로 브리지 모델 이다. 예 를 들 어 jdbc 는 구동 규범 을 정 의 했 고 각 데이터 베이스 업 체 는 서로 다른 구동 실현 을 제공 했다.
//       IBridgeAble
public interface IBridgeAble {	
	public void doSome(String arg0, String arg1);	
}

//          BridgeAble
public class BridgeAble implements IBridgeAble {
	
	private IBridgeAble bridgeAble;
	
	public BridgeAble(IBridgeAble bridgeAble){
		this.bridgeAble = bridgeAble;
	}

	public void doSome(String arg0, String arg1) {	
		bridgeAble.doSome(arg0, arg1);
	}

}

//A        BrideAbleImplA
public class BrideAbleImplA implements IBridgeAble{

	public void doSome(String arg0, String arg1) {
		System.out.println("BrideAbleImplA.arg0: " + arg0 + " BrideAbleImplA.arg1: " + arg1);
	}

}

//B        BrideAbleImplB
public class BrideAbleImplB implements IBridgeAble{

	public void doSome(String arg0, String arg1) {
		System.out.println("BrideAbleImplB.arg0: " + arg0 + " BrideAbleImplB.arg1: " + arg1);
	}

}

//      
public static void testBridge(){
	BridgeAble bridge = new BridgeAble(new BrideAbleImplA());
	bridge.doSome("A", "A1");
}

8. 관찰자 모드
응용 장면: 관찰자 모델 은 이해 하기 어렵 지만 매우 중요 하 다. 예 를 들 어 모니터 는 관찰자 모델 로 실현 해 야 한다.
//       
public interface IObserver {
	void operate();
}

//   ObserverOne,             ,       ,     
public class ObserverOne implements IObserver {
	@Override
	public void operate() {
		System.out.println("   1      ");
	}
}

//   ObserverTwo
public class ObserverTwo implements IObserver {
	@Override
	public void operate() {
		System.out.println("   2      ");
	}
}

//       BeObserver
public abstract class BeObserver {
	
	private Set observers;
	
	public BeObserver(Set observers) {
		this.observers = observers;
	}
	
	public abstract void doSome();

	protected void notifyObserver() {
		if(observers != null) {
			observers.forEach(observer -> observer.operate());			
		}
	}

}

//      DefaultBeObserver
public class DefaultBeObserver extends BeObserver {
	
	public DefaultBeObserver(Set observers) {
		super(observers);
	}

	@Override
	public void doSome() {
		super.notifyObserver();
		System.out.println("doSome()***********");
	}

}

//       
public static void testObserver(){
	HashSet observers = new HashSet();
	observers.add(new ObserverOne());
	observers.add(new ObserverTwo());
	new DefaultBeObserver(observers).doSome();
}

9. 모니터
//  
public class Event {
	public void print() {
		System.out.println("    :" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
	}
}

//       
public interface Listener {
	void onEvent(Event e);
}

//            
public class ListenerImpl implements Listener{	
	@Override
	public void onEvent(Event e) {
		e.print();
	}
}

//   
public class EventResource {

	private List listenerList = new ArrayList<>();
	
	private Event e = new Event();
	
	public void register(Listener listener) {
		this.listenerList.add(listener);
	}
	
	public void operte() {
		System.out.println("EventResource.operte***************");
		this.listenerList.forEach(listener -> listener.onEvent(e));
	}
	
	public static void main(String[] args) {
		EventResource eventResource = new EventResource();
		eventResource.register(new ListenerImpl());
		eventResource.operte();
	}
	
}

10. 명령 모드
응용 장면: 응용 이 그리 광범 위 하지 않 습 니 다. 예 를 들 어 activiti 는 데이터 베이스 에 대한 각종 조작 에 대해 명령 모드 를 사 용 했 습 니 다. activiti 는 데이터 베이스 에 대한 조작 을 모두 서로 다른 명령 에 밀봉 하고 호출 자 는 명령 을 내 리 는 사람 입 니 다. 데이터 베 이 스 를 조작 하 는 API 즉 집행 자 이 며 서로 의존 하 는 인 터 페 이 스 는 디 결합 입 니 다.
여기 에는 세 개의 대상, 명령 하달 자 (명령 대상 소지), 명령 (최소한 하나의 명령 집행자 대상 과 명령 내용 소지), 명령 집행자 (명령 집행) 에 주의해 야 한다.
//      
public interface ILeader {
	//    
	void command();
}

//          
public class LeaderImplOne implements ILeader{

	//      
	private ICommand command;

	//        
	public LeaderImplOne(ICommand command){
		this.command = command;
	}
	
	//    
	public void command() {
		command.transferCommand();
	}

}

//       ...N

//    
public interface ICommand {
	//    
	void transferCommand();
}

//    1
public class CommandImplOne implements ICommand{
	
	//          
	private IExecutor[] executors;
	
	//          
	private IExecutor executor;
	
	//      
	private String content;
	
	//        ,            ,     
	public CommandImplOne (IExecutor[] executors,String content){
		this.executors = executors;
		this.content = content;
	}
	
	//        ,            ,     
	public CommandImplOne (IExecutor executor,String content){
		this.executor = executor;
		this.content = content;
	}

	//             
	public void transferCommand() {
		if(executors != null && executors.length > 0){
			for(int i = 0; i < executors.length; i++){
				executors[i].execute(content);
			}
		}		
		
		if(executor != null){
			executor.execute(content);
		}
		
	}
	
}

//    2
public class CommandImplTwo implements ICommand{
	
	//          
	private IExecutor[] executors;
	
	//          
	private IExecutor executor;
	
	//      
	private Map content;
	
	//        ,            ,     
	public CommandImplTwo (IExecutor[] executors,Map content){
		this.executors = executors;
		this.content = content;
	}
	
	//        ,            ,     
	public CommandImplTwo (IExecutor executor,Map content){
		this.executor = executor;
		this.content = content;
	}

	//             
	public void transferCommand() {
		if(executors != null && executors.length > 0){
			for(int i = 0; i < executors.length; i++){
				executors[i].execute(content);
			}
		}
		
		if(executor != null){
			executor.execute(content);
		}
		
	}
	
}

//    ...N

//       
public interface IExecutor {
	//    
	void execute(String content);
	
	//    
	void execute(Map content);
}

//       1
public class ExecutorImplOne implements IExecutor {


	public void execute(String content) {
		//           
		System.out.println("    1     ,   content:" + content);
	}

	public void execute(Map content) {		
		//           
		System.out.println("    1     ,   content.size:" + content.size());
	}

}

//       2
public class ExecutorImpTwo implements IExecutor {


	public void execute(String content) {
		//           
		System.out.println("     2     ,   content:" + content);
	}

	public void execute(Map content) {		
		//           
		System.out.println("     2     ,   content.size:" + content.size());
	}

}

//       ...N

//      
public static void testCommand(){
	//              
	IExecutor[] executors = {new ExecutorImplOne(),new ExecutorImpTwo()};

	//      ,             ,    		
	CommandImplOne commandOne = new CommandImplOne(executors,"  1");
	
	//       ,    
	new LeaderImplOne(commandOne).command();
}

11. 책임 체인 모드
응용 장면: 책임 체인 의 응용 은 상당히 광범 위 하 다. 예 를 들 어 springmvc 의 프로세서 체인 은 이 디자인 모델 을 사용 했다. 그 원 리 는 프론트 데스크 톱 에서 요청 을 보 내 면 프로세서 체인 의 각종 차단기 에 의 해 차단 되 고 각자 의 처 리 를 하 는 것 이다.한 마디 로 하면 만약 에 한 대상 이 다른 여러 대상 에 의 해 서로 다른 처 리 를 해 야 하고 이 과정 이 선형, 즉 동기 화 되 어야 한다 면 우 리 는 책임 체인 모델 을 사용 하 는 것 을 고려 할 수 있다.이렇게 하 는 장점 은 피 처리 대상 과 각 처리 대상 이 결합 을 풀 고 자 유 롭 게 조립 하 는 것 이다.
//           
public abstract class Handler {

	//      
	protected Handler nextHandler;
	
	//      
	protected Handler lastHandler;
	
	//       
	protected String handlerName;
	
	//         
	public Handler (String handlerName){
		this.handlerName = handlerName;
	}
	
	//        ,                    
	public void setNextHandler(Handler nextHandler){
		this.nextHandler = nextHandler;
		nextHandler.lastHandler = this; 
	}

	//      ,    Request  
	public abstract void handle(Request request);

}

//       
public class Request {
	
	//    map     
	private Map attributes;

	//      , new  attributes
	public Request(){
		attributes = new HashMap<>();
	}
	
	//       attributes
	public Request(Map attributes){
		this.attributes = attributes;
	}

	//attributes set、get  
	public Map getAttributes() {
		return attributes;
	}
	public void setAttributes(Map attributes) {
		this.attributes = attributes;
	}
	
	// attributes     
	public void setAttribute(String key,Object value){
		attributes.put(key, value);
	}
	
	//  key attributes     
	public Object getAttribute(String key){
		return attributes.get(key);
	}
	
}

//        HandlerImplA
public class HandlerImplA extends Handler {

	public HandlerImplA(String handlerName) {
		super(handlerName);
	}

	@Override
	public void handle(Request request) {
		System.out.println("HandlerImplA    request      :" + request.getAttributes().size());
		request.setAttribute(this.handlerName + ".attr", this.handlerName + ".val");	
		nextHandler.handle(request);
	}

}

//        HandlerImplB
public class HandlerImplB extends Handler {

	public HandlerImplB(String handlerName) {
		super(handlerName);
	}

	@Override
	public void handle(Request request) {
		System.out.println("HandlerImplB           :" + lastHandler.handlerName);
		nextHandler.handle(request);
	}

}

//         ActualHandler
public class ActualHandler extends Handler {

	public ActualHandler(String handlerName) {
		super(handlerName);
	}

	@Override
	public void handle(Request request) {
		System.out.println("ActualHandler  request        :");
		Map attributes = request.getAttributes();
		Set> entrySet = attributes.entrySet();
		for (Entry entry : entrySet) {
			System.out.println("request.attrName:" + entry.getKey() + " request.attrVal:" + entry.getValue());
		}
	}

}

//       
public static void testResponsibility(){
	//    
	Request request = new Request();
	ActualHandler handler = new ActualHandler("handler");
	HandlerImplB handlerB = new HandlerImplB("handlerB");
	handlerB.setNextHandler(handler);
	HandlerImplA handlerA = new HandlerImplA("handlerA");
	handlerA.setNextHandler(handlerB);
	// A    
	handlerA.handle(request);
}

콘 솔 인쇄 는 다음 과 같 습 니 다.
HandlerImplA 현재 request 의 속성 을 인쇄 합 니 다: 0 HandlerImplB 이전 처리 이름 을 인쇄 합 니 다: handlerA ActualHandler 인쇄 request 의 모든 매개 변 수 는 다음 과 같 습 니 다: request. attrName: handlerA. attr request. attrVal: handlerA. val
12. 상태 모드
응용 장면: 논리 적 으로 3 층 이 넘 는 if - else 코드 는 위 문 이나 상태 모드 를 사용 하여 실현 할 수 있 습 니 다.이 말 은 아 리 의 자바 개발 매 뉴 얼 의 규범 으로 뚜렷 하 다. 상태 모델 의 디자인 은 if - else 를 교체 하기 위 한 것 이다.그렇다면 왜 상태 모드 로 if - else 를 교체 해 야 합 니까?이것 이 바로 상태 모드 를 사용 하 는 이유 입 니 다. 인터넷 에서 대부분 사람들 이 부화뇌동 하 는 것 은 유지 와 확장 을 편리 하 게 하기 위해 서 라 고 설명 하지만 상태 모드 를 사용 하면 어떻게 원래 코드 를 수정 하지 않 고 확장 할 수 있 는 지 생각 하지 않 았 습 니 다. 하지만 배 워 보 세 요. 유지 하기 쉽 기 때 문 입 니 다.
//           
public class ThingObject {
	
	//    
	private StateTemplate state;

	//       null
	public ThingObject() {
		this.state = null;
	}
	
	//       
	public StateTemplate getState() {
		return state;
	}

	//      ,          
	public boolean setState(StateTemplate state) {
		this.state = state;
		return state.doAction();				
	}
	
	//              
	public static void doAction(){
		//           
		System.out.println("           ");
	}
	
}

//        
public abstract class StateTemplate {
	
	//    
	protected int states;
	
	//        
	public StateTemplate(int states){
		this.states = states;
	}

	//    
	public abstract boolean doAction();
	
}

//          states   
public enum StatesEnum {
	
	STATE1(1),STATE2(2),STATE3(3),STATE4(4),STATE5(5),STATE6(6),STATE7(7),STATE8(8);
	
	public Integer value;
	
	private StatesEnum(Integer value){
		this.value = value;
	}
	
}

//  1  
public class StateOne extends StateTemplate {
	
	//             
	public StateOne(int states) {
		super(states);
	}

	@Override
	public boolean doAction() {

		//         1      ,       
		if(super.states == StatesEnum.STATE1.value){
			System.out.println("  111     ");
			return true;
		}
		return false;
	}

}

//  2  
public class StateTwo extends StateTemplate {

	public StateTwo(int states) {
		super(states);
	}

	@Override
	public boolean doAction() {
		if(super.states == StatesEnum.STATE2.value){
			//  2     
			System.out.println("  222     ");
			return true;
		}
		return false;
	}

}

//  3  
public class StateThree extends StateTemplate {

	public StateThree(int states) {
		super(states);
	}

	@Override
	public boolean doAction() {
		if(super.states == StatesEnum.STATE3.value){
			//  2     
			System.out.println("  333     ");
			return true;
		}
		return false;
	}

}

//  N...  

//      
public static void testState(int states){		
	
	ThingObject t = new ThingObject();
	if(t.setState(new StateOne(states))) return;
	if(t.setState(new StateTwo(states))) return;	
	if(t.setState(new StateThree(states))) return;
	
	//           
	ThingObject.doAction();
	
}

       상기 테스트 코드 의 if return 은 지 울 수 있 습 니 다. if - else 의 효 과 를 완전히 모 의 하기 위해 서 만 추 가 됩 니 다. 만약 에 지금 조건 4 를 확장 해 야 한다 면 상태 템 플 릿 을 추가 하여 State Four 를 실현 한 다음 에 테스트 코드 의 마지막 줄 에 if (t. setState (new State Four (states) return 을 추가 합 니 다.즉, 클 라 이언 트 가 소스 코드 를 수정 해 야 하 는 것 이 분명 하고 개폐 원칙 을 진정 으로 실현 하지 못 했다.
13. 방문 자 모드
응용 장면: 소스 대상 에 대한 다양한 조작 을 추상 적 으로 하나의 규범 으로 만 든 다음 에 이 규범 을 실현 하 는 각 실현 유형 은 바로 방문 자 대상 이 고 방문 자 는 소스 대상 을 가지 기 때문에 소스 대상 의 데이터 구 조 를 조작 할 수 있다.이 럴 때 이 모델 을 사용 할 수 있다. 예 를 들 어 한 모듈 의 여러 장의 보고 서 를 개발 할 때 이 모델 을 사용 할 수 있다. 보고 서 를 추가 할 필요 가 있 으 면 방문 자 를 추가 하면 된다.
//      
public class BeVisitor {

    //      
	public void accept(IVisitor visitor) {
		visitor.visite(this);
	}

	private Integer attr1;
	private String attr2;
	private boolean attr3;

	public Integer getAttr1() {
		return attr1;
	}

	public void setAttr1(Integer attr1) {
		this.attr1 = attr1;
	}

	public String getAttr2() {
		return attr2;
	}

	public void setAttr2(String attr2) {
		this.attr2 = attr2;
	}

	public boolean isAttr3() {
		return attr3;
	}

	public void setAttr3(boolean attr3) {
		this.attr3 = attr3;
	}

}

//     
public interface IVisitor {
	void visite(BeVisitor beVisitor);
}

//   1
public class VisitorOne implements IVisitor {

	public void visite(BeVisitor beVisitor) {
		System.out.println("------------VisitorOne print:------------");
		System.out.println(beVisitor.getAttr1() + "---" + beVisitor.getAttr2());
	}

}

//   2
public class VisitorTwo implements IVisitor {

	public void visite(BeVisitor beVisitor) {
		System.out.println("------------VisitorTwo print:------------");
		if(beVisitor.isAttr3()){
			System.out.println(beVisitor.getAttr1() + "---" + beVisitor.getAttr2());
		}else{
			System.out.println("beVisitor.isAttr3(): " + false);
		}
	}

}

//       
public static void testVisitor(){
	BeVisitor beVisitor = new BeVisitor();
	beVisitor.setAttr1(20);
	beVisitor.setAttr2("  ");
	beVisitor.setAttr3(false);
    //     1   
	beVisitor.accept(new VisitorOne());
    //     2   
	beVisitor.accept(new VisitorTwo());
}

14. 템 플 릿 방법
응용 장면: 만약 에 규범 중의 방법 을 각각 실현 해 야 한다 면 이런 모델 을 사용 할 수 있다.
//  
public interface IPhone {
	
	public void call();
	
	public void photograph();
	
	public void music();
	
	public void sendMsg();
}

//     
public abstract class PhoneTemplate implements IPhone {

	@Override
	public void call() {
		System.out.println("call()*********");
	}

	@Override
	public void sendMsg() {
		System.out.println("sendMsg()********");
	}

}

//  Vivo
public class Vivo extends PhoneTemplate {

	@Override
	public void photograph() {
		System.out.println("vivo -> photograph()********");
	}

	@Override
	public void music() {
		System.out.println("vivo -> music()********");
	}
	
}

//  XiaoMi
public class XiaoMi extends PhoneTemplate {

	@Override
	public void photograph() {
		System.out.println("XiaoMi -> photograph()********");
	}

	@Override
	public void music() {
		System.out.println("XiaoMi -> music()********");
	}

}

//  
public static void main(String[] args) {
	XiaoMi xiaoMi = new XiaoMi();
	xiaoMi.call();
	xiaoMi.sendMsg();
	xiaoMi.music();
}

15. 전략 모드
사용 장면 이 매우 광범 위 하고 한 행위 가 서로 다른 표현 형식 을 가 질 때 전략 모델 을 사용 할 수 있다.
전략 모델 과 브리지 모델 은 코드 차원 에서 본질 적 인 차이 가 없고 디자인 의 출발점 만 다르다.
예 를 들 어 네 가지 연산 법칙 은 하나의 연산 행위 (전략) 를 정의 하고 가감 곱 하기 네 가지 연산 형식 (전략 실현) 이 있 으 며 전략 소지 (전략 사용자) 가 있다.
//    
public interface StrategyCalculate {

	public double calculate(double a, double b);
	
}

//      
public class DefaultStrategyCalculate implements StrategyCalculate {

	@Override
	public double calculate(double a, double b) {
		return a + b;
	}

}

//       
public class SubtractionStrategyCalculate implements StrategyCalculate {

	@Override
	public double calculate(double a, double b) {
		return a - b;
	}

}

//     
public class StrategyCalculateHolder {
	
	private StrategyCalculate strategyCalculate;
	
	public StrategyCalculateHolder(StrategyCalculate strategyCalculate) {
		this.strategyCalculate = strategyCalculate;
	}
	
	public double calculate(double a, double b) {
		return this.strategyCalculate.calculate(a, b);
	}
	
	public static void main(String[] args) {
		System.out.println(new StrategyCalculateHolder(new DefaultStrategyCalculate()).calculate(20, 10));
		System.out.println(new StrategyCalculateHolder(new SubtractionStrategyCalculate()).calculate(20, 10));
	}
	
}

좋은 웹페이지 즐겨찾기