第二に、内臓ハートデザインパターンの建築家
内臓ハートデザインパターンの2アーキテクト
2.1。コースの目的
1、この章の研究を通じてデザインパターンの起源を理解することです。
2、デザインパターンは、私たちはどのような問題を解決することができます導入されました。
3、アプリケーションシナリオ工場の起源とモードの歴史の分析。
2.2。コンテンツターゲティング
デザインパターンがなければ不可能ではないが、良いデザインパターンで、私たちはより良い現実的な問題を解決するために助けることができる、最も重要な設計パターンが
分離されています。毎日使用してパターンを設計しますが、自分自身が、無認識。私たちは、トピックとして、パターン、デザインパターンの主に研究設計
教訓どのように、自分自身の使用のための経験を。ビジネスは達成するために非常に効果的な技術を必要とする翻訳するためにデザインパターンを学ぶのも行使する
方法を。
2.3。ソフトウェア設計の原則を想起
設計の原則 | 説明 |
---|---|
オープンクローズ原理 | 修正のため閉鎖の拡張のためのオープン、 |
依存関係逆転の原則 | それぞれのクラスやモジュールを抽象化することで、互い、疎結合に影響を与えません。 |
単一責任の原則 | クラス、インタフェース、メソッド、一つだけ。 |
インターフェイスの棲み分け原理 | インタフェースの純度を確保しようとすると、クライアントが不要なインターフェースを頼るべきではありません。 |
デメテル | また少なくともノウハウ、ノウハウの原則として知られている、より良いクラスは、そのクラスに依存します。 |
リヒター置換原則 | サブクラスは、親クラスの機能を拡張することができますが、元の関数の親クラスを変更することはできません。 |
多重化の原則の合成 | コードの再利用にオブジェクトの継承関係を使用せずに、オブジェクト合成、重合を利用すること。 |
2.4。デザインパターンの概要
エレガントなコードを書きます
より良い復興プロジェクト
古典的なフレームワークは、デザインパターンの問題を解決するためにあります
春は、古典的なフレームワークの頭を持つデザインパターンで実際には、クラスの名前からそれを見ることができます、と私はそれらを一覧表示します:
デザインパターンの名前 | 例えば |
---|---|
ファクトリパターン | たBeanFactory |
デコレーター | BeanWrapper |
プロキシモード | AopProxy |
委任モード | DispatcherServlet |
戦略モード | ハンドラーマッピング |
アダプタモード | ハンドラアダプタ |
テンプレートモード | JdbcTemplate |
Observerパターン | ContextLoaderListener |
私たちのコースはIOC、AOP、MVC、JDBCの周りに春になる
展開のアイデアので、その設計の種類に応じての順序を説明するために設計されています。
タイプ | 名前 | 英文 |
---|---|---|
スキーマを作成します。 | ファクトリパターン | ファクトリパターン |
シングルトン | Singletonパターン | |
プロトタイプモード | Prototypeパターン | |
構造モデル | アダプタモード | Adapterパターン |
デコレーター | デコレーターパター | |
プロキシモード | Proxyパターン | |
行動パターン | 戦略モード | Strategyパターン |
テンプレートモード | テンプレートパターン | |
委任モード | デリゲートパターン | |
Observerパターン | Observerパターン |
3.詳細なファクトリパターン
歴史的起源3.1。Factoryパターン
原始社会の自給自足(無工場)、小さな農業コミュニティワークショップ(シンプル工場、民俗ワイン
スクエア)、産業革命ライン(ファクトリメソッド、国産)、近代的な産業チェーンのファウンドリ(抽象工場、Foxconnの)
3.2。単純なファクトリパターン
3.2.1定義
単純なファクトリパターン(単純なファクトリパターン)クラスの製品のインスタンスを作成するファクトリオブジェクトによって決定手段
が、GOF 23デザインパターンは属しません。単純なファクトリクラスのシーンを作成するための責任小さなオブジェクトに適した施設、およびクライアントの必要性は
気にしないロジックのオブジェクトを作成する方法を、工場出荷時のクラスにパラメータを渡します。
3.2.2.demo
public class SimpleFactoryTest {
public static void main(String[] args) {
CourseFactory factory = new CourseFactory();
ICourse course = factory.create(JavaCourse.class);
course.record();
}
}
public class JavaCourse implements ICourse {
public void record() {
System.out.println("录制Java课程");
}
}
public class CourseFactory {
public ICourse create(Class<? extends ICourse> clazz){
// 反射
try {
if (null != clazz) {
return clazz.newInstance();
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
3.2.3。ソース
Calendar.getInstance()
LoggerFactory.getLogger()
JDKのソースのシンプルな工場出荷時のパターンは、我々は今、このようなCalendarクラスとして、あなたの例を与える、どこにでもある、参照
Calendar.getInstance()メソッドを、次のようにカレンダーのクラスを作成するためのオープンコンクリートは次のとおりです。
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
if (provider != null) {
try {
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
Calendar cal = null;
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
if (cal == null) {
// If no known calendar type is explicitly specified,
// perform the traditional way to create a Calendar:
// create a BuddhistCalendar for th_TH locale,
// a JapaneseImperialCalendar for ja_JP_JP locale, or
// a GregorianCalendar for any other locales.
// NOTE: The language, country and variant strings are interned.
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
return cal;
}
私たちはしばしばlogbackが使用し、我々はLoggerFactoryはメソッドオーバーロードされたよりも多く存在していることがわかります
のgetLogger():
public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
public static Logger getLogger(Class clazz) {
return getLogger(clazz.getName());
}
3.2.4長所と短所
- 利点
- シンプル
- 缺点
- 工厂类的职责相对过重,不易于扩展过于复杂的产品结构。
3.3.工厂方法模式
3.3.1.定义
工厂方法模式(Factory Method Pattern)是指定义一个创建对象的接口,但让实现这个接口的类
来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。在工厂方法模式中用户只需要关心所
需产品对应的工厂,无须关心创建细节,而且加入新的产品符合开闭原则。
3.3.2.demo
public class FactoryMethodTest {
public static void main(String[] args) {
// Python课程工厂
ICourseFactory factory = new PythonCourseFactory();
ICourse course = factory.create();
course.record();
// Java课程工厂
factory = new JavaCourseFactory();
course = factory.create();
course.record();
}
}
public class JavaCourseFactory implements ICourseFactory {
public ICourse create() {
return new JavaCourse();
}
}
public interface ICourseFactory {
ICourse create();
}
public class JavaCourse implements ICourse {
public void record() {
System.out.println("录制Java课程");
}
}
public interface ICourse {
void record();
}
3.3.3.源码
ApplicationContext就是工厂方法模式
再来看看logback中工厂方法模式的应用,看看类图就OK了:
3.3.4.优缺点
- 工厂方法适用于以下场景:
- 创建对象需要大量重复的代码。
- 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
- 一个类通过其子类来指定创建哪个对象。
- 工厂方法也有缺点:
- 类的个数容易过多,增加复杂度。
- 增加了系统的抽象性和理解难度。
3.4.抽象工厂模式
3.4.1.定义
抽象工厂模式(AbastractFactory Pattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。客户端(应用层)不依赖于产品类实例如何被创建、实现等细节,强调的是一
系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类
的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
讲解抽象工厂之前,我们要了解两个概念产品等级结构和产品族,看下面的图:
从上图中看出有正方形,圆形和菱形三种图形,相同颜色深浅的就代表同一个产品族,相同形状的代表
同一个产品等级结构。同样可以从生活中来举例,比如,美的电器生产多种家用电器。那么上图中,颜
色最深的正方形就代表美的洗衣机、颜色最深的圆形代表美的空调、颜色最深的菱形代表美的热水器,
颜色最深的一排都属于美的品牌,都是美的电器这个产品族。再看最右侧的菱形,颜色最深的我们指定
了代表美的热水器,那么第二排颜色稍微浅一点的菱形,代表海信的热水器。同理,同一产品结构下还
有格力热水器,格力空调,格力洗衣机。
再看下面的这张图,最左侧的小房子我们就认为具体的工厂,有美的工厂,有海信工厂,有格力工厂。
每个品牌的工厂都生产洗衣机、热水器和空调。
3.4.2.demo
public class AbstractFactoryTest {
public static void main(String[] args) {
JavaCourseFactory factory = new JavaCourseFactory();
factory.createNote().edit();
factory.createVideo().record();
}
}
/**
* 抽象工厂CourseFactory类:
* 抽象工厂是用户的主入口
* 在Spring中应用得最为广泛的一种设计模式
* 易于扩展
*/
public abstract class CourseFactory {
public void init(){
System.out.println("初始化基础数据");
}
protected abstract INote createNote();
protected abstract IVideo createVideo();
}
/**
* 创建Java产品族的具体工厂JavaCourseFactory
*/
public class JavaCourseFactory extends CourseFactory {
public INote createNote() {
super.init();
return new JavaNote();
}
public IVideo createVideo() {
super.init();
return new JavaVideo();
}
}
/**
* 创建Java产品族,Java视频JavaVideo类:Java视频
*/
public class JavaVideo implements IVideo {
public void record() {
System.out.println("录制Java视频");
}
}
/**
* 录播视频:IVideo接口
*/
public interface IVideo {
void record();
}
/**
* 扩展产品等级Java课堂笔记JavaNote类:Java笔记
*/
public class JavaNote implements INote {
public void edit() {
System.out.println("编写Java笔记");
}
}
/**
* 课堂笔记:INote接口
*/
public interface INote {
void edit();
}
// 创建Python产品族的具体工厂PythonCourseFactory省略。。。
上面的代码完整地描述了两个产品族Java课程和Python课程,也描述了两个产品等级视频和手记。抽象工厂非常完美清晰地描述这样一层复杂的关系。但是,不知道大家有没有发现,如果我们再继续扩展
产品等级,将源码 Source也加入到课程中,那么我们的代码从抽象工厂,到具体工厂要全部调整,很显然不符合开闭原则。
3.4.3.源码
AbstractFactory
AnnotationApplicationContext
Xml
适合长时间不变动的场景
3.4.3.优缺点
抽象工厂缺点
- 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。
- 增加了系统的抽象性和理解难度。
3.5.简单工厂 vs 工厂方法 vs 抽象工厂
简单工厂:产品的工厂
工厂方法:工厂的工厂
抽象工厂:复杂产品的工厂
简单工厂:工厂是一个实体类,内部直接根据逻辑创建对应的产品。
工厂方法:工厂首先有个接口定义规范。不同的产品使用不同的实体类工厂根据规范和需求创建对应的产品。这就是它们的区别。
工厂方法是生产一类产品,抽象工厂是生产一个产品族
3.6.作业
1、工厂类一定需要将构造方法私有化吗,为什么?
不一定。抽象工厂类就不能,否则父类的私有构造方法就不能被子类调用。
2、用工厂模式设计支付业务场景,包含跨境支付,支付宝、微信、银联支付,并画出类图。
/**
* description: 支付接口
*/
public interface IPay {
/**
* 支付方法
*/
void pay();
}
/**
* description: 支付宝支付
*/
public class AliPay implements IPay {
public void pay() {
System.out.println("支付宝支付");
}
}
/**
* description: 微信支付
*/
public class WxPay implements IPay {
public void pay() {
System.out.println("微信支付");
}
}
/**
* description: 银联支付
*/
public class UniPay implements IPay {
public void pay() {
System.out.println("银联支付");
}
}
/**
* description: 苹果支付
*/
public class ApplePay implements IPay {
public void pay() {
System.out.println("苹果支付");
}
}
/**
* description: 支付抽象工厂
*/
public abstract class AbstractPayFactory {
public void init() {
System.out.println("初始化基础数据");
}
}
/**
* description: 国内支付
*/
public class ChinaPayFactory extends AbstractPayFactory {
protected IPay createAliPay() {
super.init();
return new AliPay();
}
protected IPay createWxPay() {
super.init();
return new WxPay();
}
protected IPay createUniPay() {
super.init();
return new UniPay();
}
}
/**
* description: 国外支付
*/
public class ForeignPayFactory extends AbstractPayFactory {
protected IPay createApplePay() {
super.init();
return new ApplePay();
}
}
/**
* description: 抽象工厂方法测试
*/
public class AbstractPayFactoryTest {
public static void main(String[] args) {
ChinaPayFactory chinaPayFactory = new ChinaPayFactory();
chinaPayFactory.createAliPay().pay();
chinaPayFactory.createWxPay().pay();
chinaPayFactory.createUniPay().pay();
ForeignPayFactory foreignPayFactory = new ForeignPayFactory();
foreignPayFactory.createApplePay().pay();
}
}