java 디자인 패턴;
Java 디자인 패턴에 대한 프로그래머의 이해:
아주 간단한 것을 왜 그렇게 복잡하게 만들어야 하는지 “이해가 안 돼요”. 나중에 소프트웨어 개발 경험이 늘어남에 따라 나는 내가 본 "복잡성"이 바로 디자인 패턴의 본질이라는 것을 이해하기 시작했습니다. 내가 "단순성"으로 이해한 것은 열쇠를 사용하여 자물쇠를 여는 패턴이었고, 현재의 문제를 해결하기 위해 디자인 패턴의 "복잡성"은 모든 잠금을 해제하기 위한 솔루션을 제안할 목적으로 "마스터 키"를 구성한다는 점에 있습니다. 디자인 패턴을 제대로 이해하기 전에는 "간단한" 코드를 작성하고 있었습니다.
이 "단순함"은 기능의 단순성이 아니라 디자인의 단순함을 의미합니다. 단순한 디자인은 유연성이 부족하다는 것을 의미합니다. 코드는 매우 엄격하며 이 프로젝트에서만 유용합니다. 다른 프로젝트에서 사용하면 쓰레기가 됩니다.
--> 코드를 재사용할 수 있도록 하려면 '디자인 패턴'을 사용하여 코드를 디자인하세요.
제가 아는 많은 프로그래머들은 디자인 패턴을 접한 후 모두 바뀌었습니다. 너무 늦게 만난 것 같은 느낌이 듭니다. 어떤 사람들은 디자인 패턴을 배우고 나면 마치 다시 태어난 것 같은 느낌을 받는다고 합니다. 심지어 어떤 사람들은 디자인 패턴을 이해하는지 여부를 프로그래머의 수준을 분류하는 기준으로 간주하기도 합니다.
우리는 패턴의 함정에 빠져서 패턴을 적용하려고 하면 형식주의에 빠질 수 없습니다. 패턴을 사용할 때 패턴의 의도에 주의를 기울여야 하며 패턴의 구현 세부 사항에 너무 많은 주의를 기울이지 말아야 합니다. 이러한 구현 세부 사항은 특정 상황에서 변경될 수 있기 때문입니다. 디자인 패턴 책의 클래스 다이어그램이나 구현 코드가 패턴 자체를 나타낸다고 고집스럽게 믿지 마십시오.
디자인 원칙: (중요)
1.
논리 코드는 캡슐화에 중점을 두고 별도의 메소드로 분리되어 있어 읽고 재사용하기 쉽습니다.
한 가지 방법으로 수백 줄의 논리 코드를 작성하지 마세요. 작은 논리 코드를 각각 분리하여 읽기 쉽고 반복적으로 호출할 수 있는 다른 방법으로 작성합니다.
2.
클래스, 메소드, 함수를 작성할 때 이식성과 재사용성을 고려해야 합니다. 일회성 코드를 방지하세요!
다른 비슷한 것에서도 얻을 수 있나요? 다른 시스템에서도 얻을 수 있나요?
3.
상속 개념을 능숙하게 사용:
애플리케이션에서 동일하고 변경하기 쉽지 않은 항목을 찾아 추상 클래스로 추출하고 하위 클래스에서 상속하도록 합니다.
상속이라는 개념은 다른 사람의 업적을 바탕으로 자신의 논리를 근거로 삼는 데도 편리합니다. 예를 들어 ImageField는 JTextField를 확장합니다.
인터페이스 아이디어를 능숙하게 사용합니다.
애플리케이션에서 변경해야 할 영역을 찾아 분리하고 변경하는 코드와 혼합하지 마세요. 변경할 필요가 없습니다.
아주 간단한 일을 너무 복잡하게 만들어 일회성 코드로 디자인 패턴의 장점을 보여주는 예: (전략 모드)
설명:
시뮬레이션 오리 게임 애플리케이션, 요구 사항 : 다양한 색깔과 모양의 오리들이 게임에 등장하며, 헤엄치며 꽥꽥거리는 소리를 동시에 냅니다.
첫 번째 방법: (일회성 코드)
다양한 오리의 클래스를 직접 작성: MallardDuck//Wild duck, RedheadDuck//Red-headed duck 각 유형에 대해 세 가지 방법이 있습니다. 🎜>quack( ): 호출 방법
swim(): 수영 방법
display(): 표시 방법
즉, 오리 슈퍼클래스(Superclass)를 설계하고 다양한 오리가 이 슈퍼클래스를 상속받도록 합니다.
public class Duck{
public void quack(){ //Quack
System.out.println("Quack");
}
public void swim(){ //수영
System.out.println("Swimming");
}
public abstract void display() /*외관이 다르기 때문에 서브클래스가 스스로 결정하도록 합니다. */
}
//MallardDuck
public class MallardDuck은 Duck을 확장합니다{
public void display(){
System.out.println("청둥오리의 색...");
}
}
//빨간 머리 오리
public class RedheadDuck Extensions Duck{
public void display(){
System.out.println("빨간 머리 오리의 색입니다.. .");
}
}
한 가지 방법이면 충분합니다.
public class Duck{
public void quack(){ //Quack
System.out.println("Quack");
}
public void swim(){ //수영
System.out.println(" 수영"); */
public void fly(){
System.out.println("Fly! Duck");
}
}
날 수 없는 오리의 경우 간단한 커버리지만 필요합니다.
//Disabled Duck
public classDisabledDuck은 Duck을 확장합니다{
public void display(){
System.out.println("장애인 오리의 색상...");
}
public void fly(){
//재정의하고 아무것도 하지 않습니다.
}
}
다른 날아다니는 오리는 덮을 필요가 없습니다.
이렇게 하면 이 슈퍼 클래스를 물려받은 모든 오리가 날게 됩니다. 그런데 또 문제가 생겼고 고객은 어떤 오리는 날 수 있고 어떤 오리는 날지 못한다고 지적했습니다.
>>>>>>댓글:
위 디자인의 경우 몇 가지 단점이 있을 수 있습니다. 슈퍼 클래스에 새로운 기능이 있으면 하위 클래스도 변경되어야 합니다. 우리는 개발에서 한 클래스가 변경되고 다른 클래스도 변경되는 것을 가장 보고 싶지 않습니다. 이는 OO 디자인과 약간 일치하지 않습니다. 이것은 분명히 서로 결합되어 있습니다. 상속을 사용한다-->결합도가 너무 높다.
세 번째 방법:
변화하기 쉬운 부분을 추출하고 캡슐화하여 미래에 대처한다. 변화. 정치개혁. 코드의 양은 늘어났지만 사용성은 향상되었고 결합도는 낮아졌습니다.
Duck에서는 파리법과 꽥꽥 소리를 추출합니다.
public void fly();
}
공용 인터페이스 Quackable{
public void quack();
}
Duck의 최종 디자인은 다음과 같습니다.
public class Duck{
public void swim(){ //Swimming
System.out.println("swimming");
}
public abstract void display() /*Because 아니요, 하위 클래스가 스스로 결정하도록 하세요. */
}
MallardDuck, RedheadDuck, DisabledDuck은 다음과 같이 작성할 수 있습니다.
//Wild Duck
public class MallardDuck은 Duck 구현 Flyable,Quackable{
public void display(){
System.out.println("야생 오리의 색...");
}
public void fly(){
//이 메서드 구현
}
public void quack() {
//이 메서드 구현
}
}
//Red-Headed Duck
public class RedheadDuck extends Duck Implements Flyable,Quackable{
public void display( ){
System .out.println("빨간 머리 오리의 색...");
}
public void fly(){
//이 메서드 구현
}
public void quack(){
//이 메서드 구현
}
}
//Disabled Duck은 Quackable만 구현합니다(짖을 수는 있지만 날 수는 없음)
public class 비활성화된Duck 확장 Duck은 Quackable을 구현합니다{
public void display( ){
System.out.println("장애인 오리의 색상...");
}
public void quack(){
//이 방법을 구현합니다
}
}
>>>>>>의견:
이러한 방식으로 설계되었으므로 프로그램은 그들 사이의 결합을 줄입니다.
단점:
처음에는 Flyable 및 Quackable 인터페이스가 꽤 괜찮아 보였고 문제를 해결했지만(Flyable은 날 수 있는 오리만 구현할 수 있음) Java 인터페이스에는 구현 코드가 없으므로 구현이 인터페이스는 코드 사용의 복잡성을 달성할 수 없습니다.
네 번째 방법:
위 방법 요약:
상속의 이점: 공통 부분을 재사용할 수 있고 반복 프로그래밍을 피할 수 있습니다.
상속 단점은 다음과 같습니다. 높은 결합도. 슈퍼 클래스가 새로운 메소드를 추가하면 모든 서브클래스가 이를 상속하고 이 메소드를 갖게 됩니다. 만약 서브클래스의 상당 부분이 이 메소드를 구현하지 않는다면 많은 수정이 필요할 것입니다.
상속 시 하위 클래스는 다른 클래스를 상속할 수 없습니다.
인터페이스의 장점: 클래스 또는 인터페이스 문제를 해결합니다.
인터페이스는 좋지 않습니다. 실제로 코드를 구현할 수 없습니다. 이를 해결하려면 다음과 같은 전략 패턴을 사용할 수 있습니다.
--------- ----- strategy (전략 모드) ---------------------
우리는 디자인 원칙을 가지고 있습니다:애플리케이션에서 동일하고 변경하기 쉽지 않은 사항을 찾아 추상 클래스로 추출하고 하위 클래스에서 상속하도록 합니다.
애플리케이션에 필요할 수 있는 사항을 찾아 변경하려면 유지하세요. 분리하고 변경할 필요가 없는 코드와 혼합하지 마세요. -->중요.
이제 "변경되는 부분과 변경되지 않는 부분"을 분리하기 위해 두 개의 클래스 세트(Duck 클래스와 완전히 분리됨)를 생성하겠습니다. 하나는 "fly"와 관련된 클래스입니다. 그리고 또 다른
은 "돌팔이"와 관련이 있으며, 각 클래스 그룹은 자신의 작업을 구현합니다. 예를 들어, "croak"을 구현하는 클래스 하나, "squeak"을 구현하는 다른 클래스, "quiet"을 구현하는 다른 클래스가 있을 수 있습니다.
먼저 두 개의 인터페이스를 작성합니다. FlyBehavior(비행 동작) 및 QuackBehavior(호출 동작).
public 인터페이스 FlyBehavior{public void fly();
} public 인터페이스 QuackBehavior{
public void quack();
}
FlyBehavior에 대한 몇 가지 특정 구현을 정의하고 있습니다.
public 클래스 FlyWithWings는 FlyBehavior를 구현합니다.{
public void fly(){
//날개를 가진 모든 오리의 비행 동작을 구현합니다.
}
}
public 클래스 FlyNoWay가 FlyBehavior를 구현합니다.{
public void fly(){
}
}
QuackBehavior의 몇 가지 특정 구현입니다.
공용 클래스 Quack은 QuackBehavior를 구현합니다.{
public void quack(){
//Quacking Duck을 구현합니다.
}
}
공용 클래스 Squeak은 QuackBehavior를 구현합니다.{
public void quack(){
//삐걱거리는 오리 구현
}
}
public 클래스 MuteQuack은 QuackBehavior를 구현합니다.{
public void quack(){
/ /Do 아무것도 부르지 않음
}
}
댓글 1:
이 디자인을 사용하면 날거나 짖는 동작을 다른 개체에서 재사용할 수 있습니다. 이러한 동작은 오리와 관련이 없기 때문입니다. 더 이상. 그리고 몇 가지 새로운
마지막으로 Duck이 어떻게 디자인되었는지 살펴보겠습니다.
FlyBehavior flyBehavior;//Interface
QuackBehavior quackBehavior; / /인터페이스 public Duck(){}
public abstract void display();
public void swim(){
//수영 동작 구현
}
public void PerformFly( ; .quack();();
}
}
MallardDuck이 어떻게 작동하는지 알아보세요.
------> 생성 메소드를 통해 'fly' 및 'call'의 특정 구현 클래스 인스턴스를 생성하여 'fly' 및 'call'의 특정 속성을 지정합니다.
공개 클래스 MallardDuck extends Duck{
public MallardDuck {
flyBehavior = new FlyWithWings ();
quackBehavior = new Quack();
//MallardDuck은 Duck을 상속하므로 모든 flyBehavior 및 quackBehavior 인스턴스 변수}
public void display (){
//실현
}
}
이렇게 하면 날고 짖고 자신만의 색깔을 동시에 보여줄 수 있습니다.
이 디자인을 사용하면 flyBehavior 및 quackBehavior의 인스턴스화가 하위 클래스에 작성되는 것을 볼 수 있습니다. 동적으로 결정할 수도 있습니다.
Duck에는 두 가지 메소드만 추가하면 됩니다.
생성자에서 속성에 값을 할당하는 것과 속성 설정자를 사용하는 것의 차이점:
생성자에서 속성에 값을 할당: 고정, 불변; 🎜>
속성 설정자를 사용하면 개체를 인스턴스화한 후 개체를 동적으로 변경할 수 있어 더욱 유연합니다. public class Duck{
FlyBehavior flyBehavior;//Interface
QuackBehavior quackBehavior;//Interface
public void setFlyBehavior(FlyBehavior flyBehavior){
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior {
this.quackBehavior= quackBehavior;
}
}
--- -------- 정적 팩토리 메소드(정적 팩토리) -------- - ---
(1)
디자인 패턴에서도 Factory Method는 상대적으로 단순한 패턴이지만 EJB, RMI, COM, CORBA, Swing에서 많이 사용됩니다
기본 개념:
FactoryMethod는 창의적인 클래스입니다. 패턴은 객체 생성을 위한 인터페이스를 정의하지만 서브클래스가 인스턴스화할 클래스를 결정하도록 합니다.
일반적으로 객체 생성의 표준 방법으로 팩토리 메소드를 사용합니다. >응용 프로그램:
클래스가 어떤 유형의 객체를 생성할지 예측할 수 없는 경우 생성하거나 클래스에 생성할 객체를 지정하기 위한 하위 클래스가 필요한 경우 팩토리 메서드 패턴
을 사용해야 합니다.
기본 개념:
Singleton은 하나의 인스턴스만 보장하는 데 사용되는 창의적인 모델이며, 일부 클래스의 경우 이에 액세스할 수 있는 전역 액세스 지점을 제공하는 것이 중요합니다. 예를 들어 데이터베이스 연결이나 소켓 연결은 특정 제한을 받으며 동시에 유지되어야 합니다.
애플리케이션:
정적 변수 사용
예 1:
public class Singleton { private static Singleton s; > public static Singleton getInstance() {
if (s == null)
s = new Singleton();
return s;
}
}
// 테스트 클래스
class SingletonTest {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
if (s1= =s2)
System.out.println("s1은 s2와 동일한 인스턴스입니다.");
else
System.out.println("s1은 s2와 동일한 인스턴스가 아닙니다.");
}
}
singletonTest의 결과는 다음과 같습니다.
s1은 s2와 동일한 인스턴스입니다
(3)
인스턴스 2:
class Singleton {
static boolean instance_flag = false; // 인스턴스가 1개인 경우 true
public Singleton() {
if (instance_flag)
throw new SingletonException("단 하나의 인스턴스만 허용됨");
else
instance_flag = true; // 1개의 인스턴스에 대한 플래그 설정
}
}
---- ------------------- 관찰자 패턴(Observer) ------------- --- ---------------
(1)
기본 개념:
관찰자 패턴은 행동 패턴이며, 그 의도는 하나- 개체 간 대다 관계 종속성, 개체의 상태가 변경되면 해당 개체에 종속된 모든 개체에 알림이 전송되고 자동으로 업데이트됩니다.
이 패턴의 핵심 객체는 대상(Subject)과 관찰자(Observer)입니다. 대상에는 이에 의존하는 관찰자가 얼마든지 있을 수 있습니다. 일단 대상의 상태가 변경되면 모든 관찰자는 이 알림에 대한 응답으로 대상의 상태를 대상의 상태 동기화와 일치하도록 대상에 쿼리합니다.
적용 가능한 시나리오:
관찰자 모드는 일대다 종속성을 갖는 객체 간에 사용됩니다. 종속 항목이 변경되면 모든 종속 항목에 업데이트 알림이 전송됩니다. 따라서 종속 항목에는 종속 항목을 추가/제거할 수 있는 방법이 있어야 하며, 추가된 종속 항목은 컨테이너에 담을 수 있고 종속 항목에 업데이트를 알리는 방법이 있어야 합니다.
(2)
아이디어:
(1)
대상(주체)과 관찰자(관찰자) 인터페이스 설정:
대상(주체) 인터페이스:
설정 관찰자 객체 등록을 위한 인터페이스;
관찰자 객체 삭제를 위한 인터페이스 설정; 공개 void 분리(Observer o);
대상 상태가 변경될 때 알림을 게시하는 인터페이스를 설정합니다. 인터페이스; public void 통지();
관찰자 인터페이스:
대상 알림 수신 시 업데이트 인터페이스 설정: public void update();
(3)
예:
선생님은 전화번호를 가지고 있어요. 학생들은 선생님의 전화번호를 알아야 제때에 전화할 수 있습니다. 그런 조합에서 선생님은 관찰자입니다
(주제) 정보가 필요한 관찰자 선생님의 전화번호가 변경되면 학생들에게 통보되며 해당 전화기록
이 업데이트됩니다.
구체적인 예시는 다음과 같습니다.
제목 코드:
public 인터페이스 Subject{
public void attachment(Observer o);
public void detach(Observer o);
public void 통지();
}
관찰자 코드:
공용 인터페이스 Observer{
public void update();
}
교사 코드
import java.util.Vector;
공용 클래스 교사 구현 주제{
개인 문자열 전화;
개인 벡터 학생;
공개 교사(){
전화 = "";
Students = new Vector();
}
public void attachment(Observer o){
Students.add(o);
}
public void detach(Observer o){
Students.remove(o);
}
공개 무효 통지(){
for(int i=0;i
}
public void setPhone(String Phone){
this.phone =phone;
통지() --Key
}
public String getPhone(){
전화 반환;
}
}
Student代码:
public class Student 구현 Observer{
개인 문자열 이름;
개인 문자열 전화;
개인 교사 교사;
public Student(문자열 이름, 교사 t){
this.name = 이름;
Teacher = t;
}
public void show(){
System.out.println("이름:"+name+"n선생님의 전화:"+ phone);
}
public void update(){
phone = Teacher.getPhone();
}
}
Client代码:
packageobserver;
import java.util.Vector;
공용 클래스 클라이언트{ -->可以只定义目标者,观察者,另외적 벡터,只为了输入结果.
public static void main(String[] args){
벡터 학생 = new Vector();
교사 t = new Teacher();
for(int i= 0 ;i<10;i++){
학생 st = 새 학생("lili "+i,t);
Students.add(st);
t.attach(st);
}
t.setPhone("88803807");
for(int i =0;i<10;i++)
((Student)students.get(i)).show();
t.setPhone("88808880");
for(int i=0; i<10;i++)
((Student)students.get(i)).show();
}
}
总结:Observer模式的最知名的应用是在MVC 시스템은 Observer에서 사용되는 문서 및 분석 도구입니다.
--------- -------- 迭代器模式(반복자) ------------------
(1 )
基本概念:
迭代器模式属于行为型模式,其意图是提供一种方法顺序访问合一个聚对象中得各个元素,而又不需要暴露该对象的
内부表示。
至少可以历遍먼저,다음,이전,마지막,isOver,或是历遍选择符同某种条件的子元素.
(2)
结构:
由一个接구与一个实现类组成.
接口:
主要是定义各历遍적 방법.
实现类:
需要一个计算点private int current=0 ; 以及一个容器Vector,来存在原来的进行历遍的一团东西;再对接口方法进
行实现.
(3)
实例:
반복자接口:
패키지 반복자;
공용 인터페이스 반복자{
/*
항목:即是集合中的各对象的类型.若为String,即把所有的ITEM改为String,若为其它자신만의 선택을 하세요.
당신의 선택에 따라 선택하세요. --->중요합니다.
*/
public Item first();
public Item next();
public boolean isDone();
public Item currentItem();
}
Controller类实现了Iterator接口。
package iterator;
import java.util.Vector;
public class Controller는 Iterator를 구현합니다.{
private int current =0;
벡터 채널;
공개 컨트롤러(벡터 v){
채널 = v;
}
공개 항목 우선(){
현재 = 0;
return (Item)channel.get(current);
}
공개 항목 next(){
현재 ++;
return (Item)channel.get(current);
}
공개 항목 currentItem(){
return (항목)channel.get(현재);
}
public boolean isDone(){
return current>=channel.size()-1;
}
}
텔레비전 인터페이스:
패키지 반복자;
import java.util.Vector;
공용 인터페이스 텔레비전{
public Iterator createIterator();
}
HaierTV精结果Television电影。
패키지 반복자;
import java.util.Vector;
공용 클래스 HaierTV가 텔레비전을 구현함{ ---下载
비공개 벡터 채널;
공개 HaierTV(){
채널 = new Vector();
채널.addElement(new Item("채널 1")); --各电影,사용 벡터 형식
채널.addElement(새 항목("채널 2"));
채널.addElement(새 항목("채널 3"));
채널.addElement(new Item("채널 4"));
채널.addElement(새 항목("채널 5"));
채널.addElement(새 항목("채널 6"));
채널.addElement( new Item("channel 7"));
}
public Iterator createIterator(){
return new Controller(채널); -- 把设计VECTOR放到迭代器中國定核的中去
}
}
클라이언트 클라이언트:
패키지 반복자;
공용 클래스 클라이언트{
public static void main( String[] args){
Television tv = new HaierTV();
반복자 it =tv.createIterator();
System.out.println(it.first().getName());
while(!it.isDone()){
System.out.println(it.next().getName());
}
}
}
상품 종류 인터페이스:
패키지 반복자;
공용 클래스 항목{
비공개 문자열 이름;
공개 항목(String aName){
name = aName;
}
공개 문자열 getName( ){
이름 반환;
}
}
------------------------- -- 외관 모드(Facade) -----------------
(1)
외관 모드는 구조 모드에 속합니다. , Facade 모드는 상위 수준 인터페이스를 정의하며, 이 인터페이스는 다음 작업에 사용됩니다: 烧开水, 把tea叶改式tea地, 把烧开水改到tea杯中.
이러한 프로세스 후에는 泡법천차叶来을 수행할 수 있습니다. 이것은 일반적으로 사용되는 단계이며, 泡다 단계의 80%가 모두 이 예입니다. 이러한 작업을
함께 묶어서 전체 단계입니다. 다음 예제인 MakeACuppa()는 와 같은 파사드 모드를 사용합니다.
private boolean TeaBagIsSteeped;
public FacadeCuppaMaker( ){System.out .println("FacadeCuppaMaker 电影冲tea了");
}public TeaCup makeACuppa(){
TeaCup cup = new TeaCup();TeaBag teaBag = new TeaBag();
물 water = new Water(); cup.addFacadeTeaBag(teaBag);
water.boilFacadeWater();
cup.addFacadeWater(water);
cup .steepTeaBag();
반환 cup;
}
}
------------ ----- 어댑터 모델(어댑터) - ----------------
(1)
어댑터 모드는 기존 클래스/인터페이스를 재사용하는 모드이며, 고객이 원하는 다른 클래스/인터페이스로 변환합니다.
(2)
예제 재사용 방법: 클래스를 재사용하려면 대상 클래스의 생성 메서드에 넣고 인스턴스화한 후 호출합니다. 대상 클래스의 해당 메서드에서 원래 메서드를 수정합니다
의 매개변수를 사용하거나 해당 로직을 추가하세요. 즉, 기존 클래스의 원래 메서드를 재사용합니다.
재사용할 클래스:
public class Adaptee{
public long getPower(long base,long exp){
long result=1;
for(int i= 0; i
return result;
}
}
대상 클래스: --인터페이스 없이 직접 구현할 수도 있습니다.
공용 인터페이스 Target{
public long get2Power(long exp);
}
공용 클래스 어댑터가 Target을 구현함{
private Adaptee pt;
public Adapter(){
pt = new Adaptee();
}
public long get2Power(long exp){
return pt.getPower(2,exp) ---원래 메소드의 매개변수를 수정합니다.
}
}
(3)
또 다른 예:
SCM에 추가된 메서드:
기존 인터페이스:
public boolean updateRecordStates(Double RecordId,Double tableNameMapping, int state , boolean
subRecordUpdate)는 RemoteException을 발생시킵니다.
{
return moveTable.updateRecordStates(recordId,tableNameMapping,state,subRecordUpdate)
어댑터 모드가 사용되는 경우:
인터페이스:
public boolean updateStatesAdapterForSelfPanel(Double RecordId ,Double tableNameMapping,int state)
RemoteException 발생;
구현 클래스:
public boolean updateStatesAdapterForSelfPanel(Double RecordId,Double tableNameMapping,int state)
RemoteException 발생
{
return this.updateRecordStates(recordId,tableNameMapping,state,false);
--------- -------------- ------- 프록시 모드(프록시) ----------- -------
(1)
프록시의 장점:
-- -> 원래 논리에 다른 논리를 추가하고 마지막으로 새 논리를 생성합니다. 즉, 클래스 메서드에 몇 가지 추가 논리를 추가하고 새 메서드 논리를 생성합니다.
(2)
정적 프록시:
--> 오리지널 클래스 프록시 클래스와 일대일 대응이 있습니다.
--> 프록시 클래스에서 원래 클래스를 인스턴스화하고 원래 클래스 메서드 앞뒤에 새 논리를 추가합니다.
다음과 같습니다:
추상 역할:
abstract public class Subject
{
abstract public void request();
}
실제 역할:
public class RealSubject는 Subject를 확장합니다
{
{
System.out.println("From real subject.");
}
}
프록시 역할:
공용 클래스 ProxySubject 확장 주제
private RealSubject realSubject; //실제 역할을 프록시 역할의 속성으로 사용
{ realSubject =new RealSubject(); }
{
preRequest();
realSubject.request (); // 여기서는 실제 객체의 요청 메소드가 실행됩니다
postRequest();
{
//something 요청하기 전에 하고 싶은 일
private void postRequest()
{
//요청한 후에 하고 싶은 일
}
}
클라이언트 호출 :
Subject sub =new ProxySubject();
Sub.request();
(3)
동적 프록시 클래스
Java 동적 프록시 클래스는 Java 아래에 있습니다. lang.reflect 패키지는 일반적으로 다음 두 클래스를 포함합니다.
인터페이스 InvocationHandler: 이 인터페이스에는 하나의 메소드만 정의됩니다: 호출(Object obj,Method 메소드, Object[] args)
. 실제 사용에서 첫 번째 매개변수 obj는 일반적으로 프록시 클래스를 참조하고, method는 프록시 메소드, args는 메소드의 매개변수 배열을 나타냅니다. 이 추상 메서드
는 프록시 클래스에서 동적으로 구현됩니다.
프록시: 이 클래스는 주로 다음 내용을 포함하는 동적 프록시 클래스입니다.
정적 객체 newProxyInstance(ClassLoader loader, Class[] 인터페이스, InvocationHandler h): 프록시 클래스를 반환합니다의 인스턴스인 반환된 프록시 클래스를 프록시 클래스로 사용할 수 있습니다.
소위 동적 프록시는 클래스입니다. 이를 생성할 때 인터페이스 세트를 제공해야 하며
클래스는 이를 구현한다고 선언합니다. 인터페이스.
3)
동적 프록시 클래스를 사용하는 경우 InvocationHandler 인터페이스,
공용 인터페이스 Subject
{
public void request();
}
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
공용 클래스 DynamicSubject가 InvocationHandler를 구현합니다. {
private Object sub;
public DynamicSubject(Object obj) {
sub = obj;
}
System.out.println("호출 전 " + 메소드);
의 해당 작업을 실행하는 데 필요한 매개변수입니다. 동적 프록시 클래스를 통해 호출 전후에 몇 가지 관련 작업을 수행할 수 있습니다.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Constructor;
import java . lang.reflect.Method;
공용 클래스 클라이언트
{ static public void main(String[] args) throws Throwable
{
RealSubject rs = new RealSubject(); /여기서 프록시 클래스를 지정하세요
InvocationHandler ds = new DynamicSubject(rs); //프록시 클래스 초기화
Subject subject = (Subject) Proxy.newProxyInstance(rs.getClass().getClassLoader(),rs.getClass
().getInterfaces(),ds );
subject.request();
}
5)
예 2:
packagedynamicProxy; 🎜>공용 인터페이스 Work {
}
packagedynamicProxy;
public void startWork() {
시스템 .out.println("jason 작업 시작...");
}
}
공개 인터페이스 Play {
}
공개 클래스 JasonPlay는 Play를 구현합니다. {
public void startPlay() {
System.out.println("jason start to play...");
}
public class Test {
public static void main(String[] args)
JasonWork work=new JasonWork();
InvocationHandler DynamicProxy=new DynamicProxy(work);
Work jasonproxy=(Work)Proxy.newProxyInstance(work.getClass().getClassLoader(),
work.getClass().getInterfaces(), DynamicProxy) >
InvocationHandler DynamicProxy=new DynamicProxy(play);
Play jasonproxy=(Play)Proxy.newProxyInstance(play.getClass().getClassLoader(),
play.getClass().getInterfaces() , DynamicProxy);
jasonproxy.startPlay();
}
===>동적 프록시 클래스, 모든 유형과 함께 사용할 수 있음 실제 클래스(작업/놀이), 결합, 동적 프록시
------------ -------------- ----- 상태 모드(state) ------ ------
(1)
상태 모드 정의:
다른 상태, 다른 동작; 즉, 각 상태에는 해당 동작이 있습니다.
상태 모드는 실제 사용에서 더 일반적이며 "상태 전환"에 적합합니다. 왜냐하면 elseif를 자주 사용하기 때문입니다. 이러한 상태 전환이 반복적으로 발생하는 경우 State 모드를 사용할 수 있는지 생각해 봐야 합니다.
--> 주기적으로 변경되는 내부 상태에 적합합니다.
(2)상태는 두 부분으로 구성됩니다: 객체 + 객체 내부 속성(속성 인터페이스 + 특정 속성)
객체에는 해당 속성과 setter 및 getter가 있어야 합니다. 초기 상태 + 표시 상태를 호출하는 메서드(상태가 자체 표시 메서드를 호출함) 속성 인터페이스, 실행 메서드가 있어야 합니다.
구현에는 특정 속성이 포함되어야 합니다. 메소드의 경우, 객체에 표시될 다음 속성을 설정해야 합니다. --> 다음에 객체가 메소드를 호출할 때 해당 속성 값이 변경됩니다.
상태 모드와 관찰자 모드의 차이점:
상태 모드는 관찰자 모드와 마찬가지로 일대다 모드입니다. 하지만 관찰자 모드에서는 "하나"가 변경되면 모든 "다"도 업데이트됩니다.
상태 모드는 '다수'가 '하나'의 상태이고, '하나'의 상태가 연속적인 순환임을 강조합니다.
하나와 다의 관계를 설정하는 방법:
"다수"는 모두 인터페이스를 구현합니다. 따라서 "one" 클래스에서는 "many" 인터페이스가 선언됩니다. "many"에서 "one"과의 관계를 설정하려면 클래스에서 직접 "one"을 선언하기만 하면 됩니다.
(3)
코드:
공용 인터페이스 Color {
public void show();
}
패키지 상태;
class Light
{
Color color;
public Color getColor() {
return color;
}
public void setColor(색상 색상) {
this.color = color;
}
public Light()
{
color=new RedColor(this);
}
public void showColor()
{
color.show();
}
}
RedColor 클래스가 Color를 구현합니다
{
Light light;
public RedColor(Light light)
{
this.light=light;
}
public void show()
{
System.out .println("색상은 빨간색입니다. 차는 멈춰야 합니다!");
System.out.println("이 상태에서 수행해야 하는 모든 논리를 기록합니다....");
setColor. (new GreenColor(light));
}
}
class GreenColor는 Color를 구현합니다
{
Light light;
public GreenColor(Light light)
{
this.light=light;
}
public void show()
{
System.out.println("색상은 녹색입니다. 자동차는 달릴 수 있습니다!") ;
System.out.println("이 상태에서 이 작업을 수행해야 하는 모든 논리를 기록합니다....");
light.setColor(new YellowColor(light));
}
}
YellowColor 클래스는 Color를 구현합니다
{
Light light;
public YellowColor(Light light)
{
this.light=light;
}
public void show()
{
System.out.println("색상은 노란색입니다. 차는 멈춰야 합니다!");
System.out.println("모든 로직을 적어서 이렇게 해야 합니다. 이 상태에서....");
light.setColor(new RedColor(light));
}
}
public class CarLight {
public static void main( String[] args) {
Light light=new Light();
//초기 호출은 빨간색 표시등입니다
light.showColor();
//Recall은 녹색 표시등입니다
light.showColor();
//노란색 조명으로 다시 호출
light.showColor();
//계속 호출, 연속 루프
}
}
------------------------------- - -- 플라이웨이트 모드(Flyweight) ------------------
(1)
주로 사용됨 객체를 생성할 때 공유 기술을 사용하면 객체가 차지하는 메모리를 줄일 수 있습니다. 프로그램 효율성과 성능을 향상시키는 모드는 프로그램 작업 속도를 크게 향상시킵니다.
플라이웨이트 모드에서는 팩토리 모드가 자주 등장합니다. Flyweight의 내부 상태는 공유를 위한 것이며, Flyweight Factory는 내부 상태 개체를 저장하기 위한 개체 저장소 풀(Flyweight Pool)을 유지 관리하는 역할을 담당합니다.
Flyweight의 핵심 아이디어는 다음과 같습니다.
새 객체를 생성할 때:먼저 해시 테이블로 이동하여 획득합니다.-> 획득한 객체가 비어 있는지 확인합니다.-> 그렇다면 이 객체를 생성하고 해시테이블에 다시 넣으세요. --> 존재한다면 원본
객체를 공유하세요.
(2)
공용 인터페이스 Car {
public void showCarName();
}
class BMWCar가 Car를 구현합니다
public void showCarName()
{ System.out .println("이것은 BMWCar입니다.");
}
}
FordCar 클래스가 Car를 구현합니다
{
public void showCarName()
시스템 .out.println("이것은 FordCar 입니다.");
}
}
class CarFactory
{
public static Car car;
{
if("BMW".equals(name))
{
car = new BMWCar();
}
if("Ford".equals( name))
{
car = new FordCar();
}
return car;
}
}
class CarFlyWeightFactory
{
public Car car;
private Hashtable
public Car getCar(문자열 이름)
{
if("BMW".equals(name))
{
car=carPool .get(이름);
if(car==null)
{
car=new BMWCar();
carPool.put(이름, 자동차);
}
}
if("Ford".equals(이름))
{
car=carPool.get(이름);
if(car==null)
{
car=new FordCar();
carPool.put(이름, 자동차);
}
}
return car;
}
public int getNumber(){ return carPool.getSize (); }
}
공개 클래스 테스트 {
public static void main(String[] args) {
CarFlyWeightFactory carFlyWeightFactory=new CarFlyWeightFactory();
Car carf1=carFlyWeightFactory.getCar("Ford");
carf1.showCarName();
자동차 carf2=carFlyWeightFactory.getCar("Ford");
carf2.showCarName();
if(carf1 ==carf2)
{
System.out.println("동일부车来적");
}
else
{
System.out.println("불동일 PART车来的");
}
System.out.println("车的数weight是:"+carFlyWeightFactory.getNumber());
}
}
输출 :
이것이 바로 FordCar입니다.
이것이 FordCar입니다.
동일부车来적
------------- --------- 职责链模式(책임 사슬) ----------
(1)
책임 사슬 책임의 职责链模式:
为了避免请求的发送者와接收者之间的耦关系,使多个接受对象都有机会处理请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
-->
要沿着链转发请求,并保证接受者为隐式的,每个链上的对象tour有一致的处理请求和访问链上后继者 接口(即如下实例中,在自己方法中再调用一次상동방식)。
(2)
public class Boy {
private boolean hasCar ; // 是否有车
private boolean hasHouse; // 是否有房
private boolean hasResponsibility; // 是否有责任心
public Boy() {
}
public Boy(boolean hasCar, boolean hasHouse, boolean hasResponsibility) {
this.hasCar = hasCar;
this.hasHouse = hasHouse;
this.hasResponsibility = hasResponsibility;
}
public boolean isHasCar() {
return hasCar;
}
public void setHasCar(boolean hasCar) {
this.hasCar = hasCar;
}
public boolean isHasHouse() {
return hasHouse;
}
public void setHasHouse(boolean hasHouse) {
this.hasHouse = hasHouse;
}
public boolean isHasResponsibility() {
return hasResponsibility;
}
public void setHasResponsibility (boolean hasResponsibility) {
this.hasResponsibility = hasResponsibility;
}
}
공용 인터페이스 핸들러 {
public void handlerRequest(Boy boy);
}
공용 클래스 HouseHandler는 Handler를 구현합니다. {
private Handler handler;
public HouseHandler(Handler handler) {
this.handler = handler;
}
공용 핸들러 getHandler() {
반환 핸들러;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
public void handlerRequest(Boy boy) {
if (boy.isHasHouse()) {
System.out.println("没想到吧,我还有房子");
} else {
System.out.println("我也没有房");
handler.handleRequest(boy);
}
}
}
공개 클래스 CarHandler가 핸들러를 구현합니다. {
private Handler handler;
public CarHandler(Handler handler) {
this.handler = handler;
}
public Handler getHandler() {
반환 핸들러;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
public void handlerRequest(Boy boy) {
if (boy.isHasCar()) {
System.out.println("呵呵,我有辆车");
} else {
System.out.println("我没有车");
handler.handleRequest(boy);
}
}
}
공개 클래스 ResponsibilityHandler는 핸들러를 구현합니다. {
private Handler handler;
public ResponsibilityHandler(Handler handler) {
this.handler = handler;
}
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
public void handlerRequest(Boy boy) {
if (boy.isHasResponsibility()) {
System.out.println("我只有一颗带Responsibility的心");
} else {
System.out.println("更没有责任心");
handler.handleRequest(boy);
}
}
}
public class Girl {
public static void main(String[] args ) {
// 这个boy没有车,也没有房,不过很有责任心
Boy boy = new Boy(false, false, true);
// 也可以使사용setHanlder방법
핸들러 핸들러 = new CarHandler(new HouseHandler(
new ResponsibilityHandler(null)));
handler.handleRequest(boy);
}
}
==>
如何实例使请求沿着链에서 各接受对象中传递, 当没被第一个接受对象接受时, 会传递给第二个对象,若被第一个对象接受了,则不传递下去:
1.사용 가능한 사용 방법:
public CarHandler(Handler handler) { this.handler = handler; }
2.各具体의 接受对象实现接口적방법은handleRequest()中.재사용时,若被接受,则执行true内容,若不被接受,则执行false内容,并继续调사용再调용 handlerRequest() 방식.
3. 현재 사용 중인 처리기 중, 생성된 처리기의 처리기, 더 많은 유형의 형식을 사용합니다.最后再调用ResponsibilityHandler적 방법.
==>前两个handler是采用了有参数的构造方法,最后一个是采用了为NULL的构造方法
- ----------------------------- 备忘录模式(메멘토) ---------------- ---------------
(1)
备忘录模式属于行为型模式,其意图是我不破坏封装性前提下,并在该对象の外保存这
个状态,这样以后就可以将对象恢复到原先保存的状态。
(2)
实例如下:
有一个对象Employee.除了属性外,还需要一保存,还原状态적 방법.
有一个对象Memento,用来记录Employee每一个时刻的状态,
Care 테이커, 来保存, 拿回Memento.需要一个保存,还原状态적 방법.->需要一个指针,一个容器.
package memento; public class Memento{ String name; int age; public Memento(String name,int age){ this.name = name; this.age = age; } }
Employee模式:
package memento; public class Employee{ private String name; private int age; public Employee(String aName,int aAge){ name = aName; age = aAge; } public void setName(String aName){ name = aName; } public void setAge(int aAge){ age = aAge; } public Memento saveMemento(){ return new Memento(name,age); } public void restoreMemento(Memento memento){ age = memento.age; name = memento.name; } public int getAge(){ return age; } public String getName(){ return name; } }
CareTaker代码:
package memento; import java.util.Vector; public class CareTaker{ private Vector v; private int current; public CareTaker(){ current = -1; v = new Vector(); } public void setMemento(Memento mem){ current ++; v.add(mem); } public Memento getMemento(){ if(current>0){ current --; return(Memento) v.get(current); } return null; } }
클라이언트代码:
package memento; public class Client{ public static void show(Employee e){ System.out.println("-----------------------------------"); System.out.println("Name:"+e.getName()); System.out.println("Age:" + e.getAge()); System.out.println("-----------------------------------"); } public static void main(String[] args){ Employee e = new Employee("lili",25); CareTaker ct = new CareTaker(); show(e); ct.setMemento(e.saveMemento()); e.setName("litianli"); show(e); ct.setMemento(e.saveMemento()); e.setAge(45); show(e); ct.setMemento(e.saveMemento()); //restore e.restoreMemento(ct.getMemento()); show(e); e.restoreMemento(ct.getMemento()); show(e); } }