Javaのデザインパターンを学習する前に、デザインパターンの原理を理解する必要があります。
オープンクローズ原理
定義
このようなクラス、モジュールや機能などのソフトウェアエンティティは、拡張のためにオープンであるべきであるが、変形のため閉鎖
- で、拡張フレーム抽象に構成の詳細を達成
利点:ソフトウェアの再利用性と保守性を向上させます
コーディング
インタフェースの作成
public interface ICourse {
Integer getId();
String getName();
Double getPrice();
}
実装クラスを作成します
@ToString
@AllArgsConstructor
public class JavaCourse implements ICourse {
@Getter
private Integer id;
@Getter
private String name;
@Getter
private Double price;
}
テストカテゴリ
public class Test {
public static void main(String[] args) {
ICourse iCourse = new JavaCourse(96, "我的Java课程", 348d);
System.out.println("课程ID: " + iCourse.getId() + " 课程名称: " + iCourse.getName() + "课程价格: " + iCourse.getPrice());
}
}
コンソール出力
课程ID: 96 课程名称: 我的Java课程课程价格: 348.0
あなたは今の拡張のためのオープン、デザインに開閉の原則に従い、割引プログラムで販売したいが、修正のために閉じている場合。
割引クラスの作成
public class JavaDiscountCourse extends JavaCourse {
public JavaDiscountCourse(Integer id, String name, Double price) {
super(id, name, price);
}
public Double getOriginPrice() {
return super.getPrice();
}
@Override
public Double getPrice() {
return super.getPrice() * 0.8;
}
}
アプリケーションクラスを変更します。
public class Test {
public static void main(String[] args) {
ICourse javaCourse = new JavaDiscountCourse(96, "我的Java课程", 348d);
JavaDiscountCourse iCourse = (JavaDiscountCourse) javaCourse;
System.out.println("课程ID: " + iCourse.getId() + " 课程名称: " + iCourse.getName() + "课程原价: " + iCourse.getOriginPrice() + " 课程折后价格: " + iCourse.getPrice());
}
}
コンソール出力
课程ID: 96 课程名称: 我的Java课程课程原价: 348.0 课程折后价格: 278.40000000000003
ここでは、ノートに場所であるDouble * 0.8
出力はケースを失った後、あなたが使用できるポイント精度浮動コンストラクタを解決するには。BigDecimal
String
public BigDecimal(String val)
修正JavaDiscountCourse
public class JavaDiscountCourse extends JavaCourse {
public JavaDiscountCourse(Integer id, String name, Double price) {
super(id, name, price);
}
public Double getOriginPrice() {
return super.getPrice();
}
@Override
public Double getPrice() {
return new BigDecimal(super.getPrice().toString()).multiply(new BigDecimal("0.8")).doubleValue();
}
}
コンソール出力
课程ID: 96 课程名称: 我的Java课程课程原价: 348.0 课程折后价格: 278.4
依存関係逆転の原則
定義
- その抽象的に頼る必要があり、どちらも高レベルのモジュールの低レベルのモジュールに依存してはなりません、
- 要旨は細部に頼るべきではありません。詳細は抽象的に依存している必要があります
- プログラミングのためではなく、プログラミングを実現するためのインタフェース
- 、クラス間の結合のリスクを軽減するシステムの安定性を向上させ、コードの可読性と保守性を向上させる、によって引き起こされるプログラムを変更減らすことができる:メリット
コーディング
反例
クラスを作成します
public class Geely {
public void studyJavaCourse() {
System.out.println("Geely在学习Java课程");
}
public void studyFECourse() {
System.out.println("Geely在学习FE课程");
}
public void studyPythonCourse() {
System.out.println("Geely在学习Python课程");
}
}
テストカテゴリ
public class Test {
// v1
public static void main(String[] args) {
Geely geely = new Geely();
geely.studyFECourse();
geely.studyJavaCourse();
}
}
コンソール出力
Geely在学习FE课程
Geely在学习Java课程
私たちはRubyの吉利のコースを勉強したい場合は、この時点では、我々は唯一できるGeely
クラスを追加します
public void studyRubyCourse() {
System.out.println("Geely在学习Ruby课程");
}
その後、テストクラスで
geely.studyRubyCourse();
{%ノート警告%}
依存関係逆転の原則を満たしていません
{%文末%}
正例
インタフェースの作成
public interface ICourse {
void studyCourse();
}
メンバ変数を持つクラスを作成します。ICourse course
@AllArgsConstructor
public class Geely {
@Setter
private ICourse course;
public void studyImoocCourse() {
course.studyCourse();
}
}
実装クラスを作成します
public class FECourse implements ICourse {
@Override
public void studyCourse() {
System.out.println("Geely在学习FE课程");
}
}
public class JavaCourse implements ICourse {
@Override
public void studyCourse() {
System.out.println("Geely在学习Java课程");
}
}
public class PythonCourse implements ICourse {
@Override
public void studyCourse() {
System.out.println("Geely在学习Python课程");
}
}
テストカテゴリ
public class Test {
public static void main(String[] args) {
Geely geely = new Geely(new JavaCourse());
geely.studyImoocCourse();
geely.setCourse(new FECourse());
geely.studyImoocCourse();
}
}
コンソール出力
Geely在学习Java课程
Geely在学习FE课程
あなたは新しいコースを追加したい場合は、結果として、あなただけの実装クラスを作成することができます。次いで、依存性逆転の原則に沿って、他のコードを変更せずに、アプリケーションクラスの実装クラスを設定します。
単一責任の原則
定義
- その理由は、変更に複数のクラスのリードはありません
- クラス/インタフェース/メソッドは、義務のためにのみ責任があります
- 利点:クラスは、読みやすさを向上させ、クラスの複雑さを軽減、システムの保守性を向上させる、変化によるリスクを軽減
コーディング
反例
クラスを作成します
public class Bird {
public void mainMoveMode(String birdName) {
System.out.println(birdName + " 用翅膀飞");
}
}
テストカテゴリ
public class Test {
public static void main(String[] args) {
Bird bird = new Bird();
bird.mainMoveMode("大雁");
bird.mainMoveMode("鸵鸟");
}
}
コンソール出力
大雁 用翅膀飞
鸵鸟 用翅膀飞
ダチョウの足が離れたので、私たちは鳥のクラスを変更しました
public class Bird {
public void mainMoveMode(String birdName) {
if ("鸵鸟".equals(birdName)) {
System.out.println(birdName + " 用脚走");
} else {
System.out.println(birdName + " 用翅膀飞");
}
}
}
より多くの鳥がある場合は、より多くの他の我々は、書き込みコードにする必要があります。
正例
私たちは、下の反例の例を修正しました
public class FlyBird {
public void mainMoveMode(String birdName) {
System.out.println(birdName + " 用翅膀飞");
}
}
public class WalkBird {
public void mainMoveMode(String birdName) {
System.out.println(birdName + " 用脚走");
}
}
テストクラスを追加します。
public class Test {
public static void main(String[] args) {
FlyBird flyBird = new FlyBird();
flyBird.mainMoveMode("大雁");
WalkBird walkBird = new WalkBird();
walkBird.mainMoveMode("鸵鸟");
}
}
コンソール出力
大雁 用翅膀飞
鸵鸟 用脚走
別の例として、
インタフェースの作成
/**
* 课程内容
*
* @author gaochen
* Created on 2019/7/27.
*/
public interface ICourseContent {
String getCoursName();
byte[] getCourseVideo();
}
/**
* 课程管理
*
* @author gaochen
* Created on 2019/7/27.
*/
public interface ICourseManager {
void studyCourse();
void refundCourse();
}
実装クラスを作成し、コースの内容やコース管理は、2つの機能を持っています
public class CourseImpl implements ICourseContent, ICourseManager {
@Override
public String getCoursName() {
return null;
}
@Override
public byte[] getCourseVideo() {
return new byte[0];
}
@Override
public void studyCourse() {
}
@Override
public void refundCourse() {
}
}
インターフェイスの棲み分け原理
定義
- むしろ合計単一のインターフェースを使用するよりも、専用の複数のインタフェース、それに依存してはならないクライアントは、インタフェースありません
- クラスのクラスは、最小インタフェースの確立に依存しなければなりません
- 単一のインタフェースの確立は、肥大化したインターフェースを作成しないでください
- インタフェースを最小限に抑えることができる改良プロセスをインターフェース
- 長所:私たちは、多くの場合、クラスは良い読みやすさ、拡張性と保守性を持っているように、高い凝集および低カップリングのデザインに沿ったものを言います。
{%ノート警告%}
比例の原則は、適切でなければならないことに注意
{%文末%}
コーディング
反例
インタフェースの作成
public interface IAnimalAction {
void eat();
void fly();
void swim();
}
実装クラスを作成します
public class Bird implements IAnimalAction {
@Override
public void eat() {
System.out.println("鸟 吃饭");
}
@Override
public void fly() {
System.out.println("鸟 飞");
}
@Override
public void swim() {
// 鸟不会游泳,空实现
}
}
public class Dog implements IAnimalAction {
@Override
public void eat() {
System.out.println("狗 吃饭");
}
@Override
public void fly() {
// 狗不会飞,空实现
}
@Override
public void swim() {
System.out.println("狗 游泳");
}
}
私たちは、空の実装の形をとることができ、それぞれが役に立たないインタフェース、原則に違反してインタフェースの分離を持ち、鳥や犬がインターフェイスを実現していることがわかります。しかし、消費者のために、それはまだスペースの実現を得るために、犬のフライメソッドを呼び出すことができます。
正例
3つの別々のインターフェイスに例インタフェースインタフェース分割の反応
public interface IEatAnimalAction {
void eat();
}
public interface IFlyAnimalAction {
void fly();
}
public interface ISwimAnimalAction {
void swim();
}
Dog
変更
public class Dog implements IEatAnimalAction,ISwimAnimalAction {
@Override
public void eat() {
System.out.println("狗 吃饭");
}
@Override
public void swim() {
System.out.println("狗 游泳");
}
}
Bird
変更
public class Bird implements IEatAnimalAction,IFlyAnimalAction {
@Override
public void eat() {
System.out.println("鸟 吃饭");
}
@Override
public void fly() {
System.out.println("鸟 飞");
}
}
これは、必要に応じて複数のインターフェース機能を実装することができ、小さなインターフェースの実装クラスの共同責任のために最適化され大成功インターフェイスになります。
ドミトリー原則
定義
- オブジェクトが他のオブジェクトの最小の理解に抑える必要があります。また、少なくともノウハウの原則として知られています
- クラスとクラス間の結合を最小化
- 長所:クラス間の結合を低減
コーディング
反例
クラスのカリキュラムを作成します。
public class Course {
}
プロジェクトマネージャークラスを作成します。
public class TeamLeader {
public void checkNumberOfCourse(List<Course> courseList) {
System.out.println("在线课程的数量是 :" + courseList.size());
}
}
作成ボスクラス
public class Boss {
public void commandCheckNumber(TeamLeader teamLeader) {
List<Course> courseList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
courseList.add(new Course());
}
teamLeader.checkNumberOfCourse(courseList);
}
}
テストカテゴリ
在线课程的数量是 :20
私たちはよく見を持って、実際には、ボスは、プロジェクトマネージャの必要性は、プロジェクトマネージャーは、ボス部20回のオンラインコースを教えて持っているどのように多くのコース、聞いて、当然の詳細を知る必要はありません。コースではなく、上司、プロジェクトマネージャーの統計情報の記載されています。
私たちは、UMLのクラス図を見ます
正例
変更されたクラスのためのプロジェクトマネージャー
public class TeamLeader {
public void checkNumberOfCourse() {
List<Course> courseList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
courseList.add(new Course());
}
System.out.println("在线课程的数量是 :" + courseList.size());
}
}
ボスクラス
public class Boss {
public void commandCheckNumber(TeamLeader teamLeader) {
teamLeader.checkNumberOfCourse();
}
}
今回は、それは、同じ結果を実行します。しかし、ビューのUMLクラス図の観点から、最適化がたくさんあります。