软件架构设计原则-开闭、依赖倒置、单一职责、接口隔离、迪米特、里氏替换、合成复用,附Java语言示例讲解:
软件架构设计原则-开闭、依赖倒置、单一职责、接口隔离、迪米特、里氏替换、合成复用,附Java语言示例讲解_霸道流氓气质的博客-CSDN博客
在上面讲了软件架构设计原则后,还有常用的设计模式-简单工厂模式、工厂模式、抽象工厂模式的使用示例。
是指由一个工厂对象决定创建哪一种产品类的实例,其不属于Gof的23种设计模式。简单工厂适用于工厂类负责创建
的对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创建对象不需要关心。
是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法模式让类的实例化推迟到
子类中进行。在工厂方法模式中用户只关心所需产品对应的工厂,无需关心创建细节,而且加入新的产品时符合开闭原则。
工厂方法模式主要解决产品扩展的问题。
在简单工厂模式中,随着商品的增多,如果每个商品的购买逻辑有区别,则工厂的职责就会变得越来越多,就比如万能工厂。
根据单一职责原则将职能拆分,专厂干专事。比如电脑由电脑工厂创建,书籍由书籍工厂创建,对工厂本身也做一个抽象。
是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们的具体类。客户端(应用层)不依赖于产品类实例如何被创建、如何
被实现等细节,强调的是一系列相关的产品对象(属于同一个产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类
的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
上图中有正方形、圆形和菱形三种图形,相同颜色深浅的代表同一个产品族,相同形状的代表同一个产品等级结构。
类比:
A厂家的多个电器,颜色最深的正方形代表A厂家的洗衣机,颜色最深的圆形代表A厂家的空调,颜色最深的菱形
代表A厂家的热水器,颜色最深的一排都属于A的电器这个产品族。
再看最右侧的菱形,颜色最深的是A厂家,第二排颜色浅点的代表B厂家,同理下面还有C厂家、D厂家、E厂家。
所以同一个厂家的就认为是具体的工厂,每个厂家都生产洗衣机、热水器和空调。
注:
博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。
以商品为例,定义一个商品的标准接口
package com.ruoyi.demo.designPattern.simpleFactory;
public interface IGoods {
/**
* 购买商品
*/
public void buy();
}
创建一个电脑商品的实现类
package com.ruoyi.demo.designPattern.simpleFactory;
public class ComputerGoods implements IGoods{
@Override
public void buy() {
System.out.println("购买了电脑商品");
}
}
客户端调用时会这样写
package com.ruoyi.demo.designPattern.simpleFactory;
public class factoryTest {
public static void main(String[] args) {
IGoods goods = new ComputerGoods();
goods.buy();
}
}
上述代码中,父类IGoods指向子类ComputerGoods的引用,应用层代码需要依赖ComputerGoods,
如果业务扩展,那么客户端依赖会越来越臃肿。
所以用简单工厂模式对代码进行优化
创建工厂GoodsFactory
package com.ruoyi.demo.designPattern.simpleFactory;
public class GoodsFactory {
public IGoods buy(Class extends IGoods> clazz){
try {
if(null != clazz){
return clazz.newInstance();
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
这里采用反射技术,当商品不断增多时,不需要修改工厂中的代码。
此时优化客户端代码
package com.ruoyi.demo.designPattern.simpleFactory;
public class factoryTest {
public static void main(String[] args) {
GoodsFactory factory = new GoodsFactory();
IGoods goods = factory.buy(ComputerGoods.class);
goods.buy();
}
}
简单工厂模式也有它的缺点:
工厂类的职责相对过重,不易于扩展过于复杂的产品结构。
为了实现专厂干专事,电脑商品由电脑工厂创建,书籍商品由书籍工厂创建,对工厂本身做一个抽象。
创建IGoodsFactory
package com.ruoyi.demo.designPattern.factoryMethod;
public interface IGoodsFactory {
IGoods create();
}
再分别创建子工厂,电脑工厂代码如下
package com.ruoyi.demo.designPattern.factoryMethod;
public class ComputerGoodsFactory implements IGoodsFactory {
@Override
public IGoods create() {
return new ComputerGoods();
}
}
书籍工厂代码如下
package com.ruoyi.demo.designPattern.factoryMethod;
public class BookGoodsFactory implements IGoodsFactory {
@Override
public IGoods create() {
return new BookGoods();
}
}
其它的如上面一样,分别是
IGoods:
package com.ruoyi.demo.designPattern.factoryMethod;
public interface IGoods {
/**
* 购买商品
*/
public void buy();
}
ComputerGoods:
package com.ruoyi.demo.designPattern.factoryMethod;
public class ComputerGoods implements IGoods {
@Override
public void buy() {
System.out.println("购买了电脑商品");
}
}
BoolGoods:
package com.ruoyi.demo.designPattern.factoryMethod;
public class BookGoods implements IGoods {
@Override
public void buy() {
System.out.println("购买了书籍商品");
}
}
测试代码如下:
package com.ruoyi.demo.designPattern.factoryMethod;
public class factoryMethodTest {
public static void main(String[] args) {
IGoodsFactory factory = new ComputerGoodsFactory();
IGoods goods = factory.create();
goods.buy();
factory = new BookGoodsFactory();
goods = factory.create();
goods.buy();
}
}
工厂方法模式适用于以下场景:
1、创建对象需要大量重复的代码。
2、客户端(应用层)不依赖于产品类实例如何被创建、如何被实现等细节。
3、一个类通过其子类来指定创建哪个对象。
工厂方法模式也有缺点:
1、类的个数容易增多,增加复杂度。
2、增加了系统的抽象性和理解难度。
通过上面同一个厂家的就认为是具体的工厂,每个厂家都生产洗衣机、热水器和空调。
假如商品要扩展经营模式,除了提供实体商品,还要提供售后服务。
在产品等级中增加两个产品:
IEntityGoods实物商品和IServiceAfterSale售后服务。
IEntityGoods:
package com.ruoyi.demo.designPattern.abstractFactory;
public interface IEntityGoods {
/**
* 购买实体商品
*/
public void buy();
}
IServiceAfterSale:
package com.ruoyi.demo.designPattern.abstractFactory;
/**
* 售后服务
*/
public interface IServiceAfterSale {
//享受售后服务
void enjoy();
}
然后创建一个抽象工厂类GoodsFactory:
package com.ruoyi.demo.designPattern.abstractFactory;
/**
* 抽象工厂是用户的主入口
* 是Spring中应用得最广泛的一种设计模式
* 易于扩展
*/
public interface GoodsFactory {
IEntityGoods createEntityGoods();
IServiceAfterSale createServiceAfterSale();
}
然后创建电脑产品组的实体电脑类
package com.ruoyi.demo.designPattern.abstractFactory;
public class ComputerEntityGoods implements IEntityGoods {
@Override
public void buy() {
System.out.println("购买了实体电脑商品");
}
}
扩展产品等级电脑的售后服务类
package com.ruoyi.demo.designPattern.abstractFactory;
public class ComputerServiceAfterSale implements IServiceAfterSale{
@Override
public void enjoy() {
System.out.println("享受了电脑的售后服务");
}
}
创建电脑产品族的具体工厂ComputerGoodsFactory
package com.ruoyi.demo.designPattern.abstractFactory;
public class ComputerGoodsFactory implements GoodsFactory{
@Override
public IEntityGoods createEntityGoods() {
return new ComputerEntityGoods();
}
@Override
public IServiceAfterSale createServiceAfterSale() {
return new ComputerServiceAfterSale();
}
}
然后再创建书籍产品的实体书籍类
package com.ruoyi.demo.designPattern.abstractFactory;
public class BookEntityGoods implements IEntityGoods {
@Override
public void buy() {
System.out.println("购买了实体书籍商品");
}
}
扩展产品等级书籍售后服务类
package com.ruoyi.demo.designPattern.abstractFactory;
public class BookServiceAfterSale implements IServiceAfterSale{
@Override
public void enjoy() {
System.out.println("享受了书籍的售后服务");
}
}
创建书籍产品族的具体工厂
package com.ruoyi.demo.designPattern.abstractFactory;
public class BookGoodsFactory implements GoodsFactory{
@Override
public IEntityGoods createEntityGoods() {
return new BookEntityGoods();
}
@Override
public IServiceAfterSale createServiceAfterSale() {
return new BookServiceAfterSale();
}
}
客户端调用代码
package com.ruoyi.demo.designPattern.abstractFactory;
public class absFacTest {
public static void main(String[] args) {
ComputerGoodsFactory computerGoodsFactory = new ComputerGoodsFactory();
computerGoodsFactory.createEntityGoods().buy();
computerGoodsFactory.createServiceAfterSale().enjoy();
BookGoodsFactory bookGoodsFactory = new BookGoodsFactory();
bookGoodsFactory.createEntityGoods().buy();
bookGoodsFactory.createServiceAfterSale().enjoy();
}
}
上面的代码完整地描述了两个产品族:电脑产品族和书籍产品族,也描述了两个产品族等级实体商品
和售后服务。抽象工厂模式完美描述了这样一层复杂的关系。但是,如果我们再扩展产品等级,
比如将运费也加入到商品,那么代码从抽象工厂到具体工厂要全部调整,不符合开闭原则。
所以抽象工厂模式是有缺点的:
1、规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。
2、增加了系统的抽象性和理解难度。