0
点赞
收藏
分享

微信扫一扫

设计模式之结构型


适配器模式

  • 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。它结合了两个独立接口的功能。这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。
  • 意图:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
  • 何时使用: 1、系统需要使用现有的类,而此类的接口不符合系统的需要。 2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。 3、通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)
  • 优点: 1、可以让任何两个没有关联的类一起运行。 2、提高了类的复用。 3、增加了类的透明度。 4、灵活性好。
  • 单一职责原则你可以将接口或数据转换代码从程序主要业务逻辑中分离。
  • 开闭原则。 只要客户端代码通过客户端接口与适配器进行交互, 你就能在不修改现有客户端代码的情况下在程序中添加新类型的适配器。
  • 缺点: 1、过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。 2.由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
  • 使用场景:有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。

实现

设计模式之结构型_java


设计模式之结构型_java_02

步骤 1 为媒体播放器和更高级的媒体播放器创建接口。
MediaPlayer.java
public interface MediaPlayer {
public void play(String audioType, String fileName);
}

AdvancedMediaPlayer.java
public interface AdvancedMediaPlayer {
public void playVlc(String fileName);
public void playMp4(String fileName);
}

步骤 2 创建实现了 AdvancedMediaPlayer 接口的实体类。
VlcPlayer.java
public class VlcPlayer implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
System.out.println("Playing vlc file. Name: "+ fileName);
}

@Override
public void playMp4(String fileName) {
//什么也不做
}
}

Mp4Player.java
public class Mp4Player implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
//什么也不做
}

@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: "+ fileName);
}
}

步骤 3 创建实现了 MediaPlayer 接口的适配器类。
MediaAdapter.java
public class MediaAdapter implements MediaPlayer {

AdvancedMediaPlayer advancedMusicPlayer;

public MediaAdapter(String audioType){
if(audioType.equalsIgnoreCase("vlc") ){
advancedMusicPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer = new Mp4Player();
}
}

@Override
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer.playVlc(fileName);
}else if(audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer.playMp4(fileName);
}
}
}

步骤 4 创建实现了 MediaPlayer 接口的实体类。

AudioPlayer.java
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;

@Override
public void play(String audioType, String fileName) {
//播放 mp3 音乐文件的内置支持
if(audioType.equalsIgnoreCase("mp3")){
System.out.println("Playing mp3 file. Name: "+ fileName);
}

//mediaAdapter 提供了播放其他文件格式的支持
else if(audioType.equalsIgnoreCase("vlc")
|| audioType.equalsIgnoreCase("mp4")){
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}
else{
System.out.println("Invalid media. "+
audioType + " format not supported");
}
}
}

步骤 5 使用 AudioPlayer 来播放不同类型的音频格式。

AdapterPatternDemo.java
public class AdapterPatternDemo {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("mp3", "beyond the horizon.mp3");
audioPlayer.play("mp4", "alone.mp4");
audioPlayer.play("vlc", "far far away.vlc");
audioPlayer.play("avi", "mind me.avi");
}
}

步骤 6 执行程序,输出结果:
Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported

桥接模式

  • 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
  • 意图:将抽象部分与实现部分分离,使它们都可以独立的变化。
  • 开闭原则。 你可以新增抽象部分和实现部分, 且它们之间不会相互影响。
  • 单一职责原则。 抽象部分专注于处理高层逻辑, 实现部分处理平台细节。
  • 何时使用:实现系统可能有多个角度分类,每一种角度都可能变化。
  • 如何解决:把这种多角度分类分离出来,让它们独立变化,减少它们之间耦合。
  • 关键代码:抽象类依赖实现类。
  • 优点: 1、抽象和实现的分离。 2、优秀的扩展能力。 3、实现细节对客户透明。
  • 缺点:
  • 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
  • 对高内聚的类使用该模式可能会让代码更加复杂。
  • 使用场景: 1、如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。 2、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。 3、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
  • 注意事项:对于两个独立变化的维度,使用桥接模式再适合不过了。

实现

设计模式之结构型_java_03


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lEwYWhsv-1665330113045)(https://www.runoob.com/wp-content/uploads/2014/08/20201015-bridge.svg#crop=0&crop=0&crop=1&crop=1&height=344&id=hb79m&originHeight=470&originWidth=760&originalType=binary&ratio=1&rotatinotallow=0&showTitle=false&status=done&style=none&title=&width=556)]

步骤 1  创建桥接实现接口。
DrawAPI.java
public interface DrawAPI {
public void drawCircle(int radius, int x, int y);
}


步骤 2 创建实现了 DrawAPI 接口的实体桥接实现类。
RedCircle.java
public class RedCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: red, radius: "
+ radius +", x: " +x+", "+ y +"]");
}
}

GreenCircle.java
public class GreenCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: green, radius: "
+ radius +", x: " +x+", "+ y +"]");
}
}

步骤 3 使用 DrawAPI 接口创建抽象类 Shape。
Shape.java
public abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI){
this.drawAPI = drawAPI;
}
public abstract void draw();
}

步骤 4 创建实现了 Shape 抽象类的实体类。

Circle.java
public class Circle extends Shape {
private int x, y, radius;
public Circle(int x, int y, int radius, DrawAPI drawAPI) {
super(drawAPI);
this.x = x;
this.y = y;
this.radius = radius;
}

public void draw() {
drawAPI.drawCircle(radius,x,y);
}
}

步骤 5 使用 Shape 和 DrawAPI 类画出不同颜色的圆。

BridgePatternDemo.java
public class BridgePatternDemo {
public static void main(String[] args) {
Shape redCircle = new Circle(100,100, 10, new RedCircle());
Shape greenCircle = new Circle(100,100, 10, new GreenCircle());

redCircle.draw();
greenCircle.draw();
}
}

步骤 6 执行程序,输出结果:

Drawing Circle[ color: red, radius: 10, x: 100, 100]
Drawing Circle[ color: green, radius: 10, x: 100, 100]

过滤器模式

  • 过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来,它结合多个标准来获得单一标准。

实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EbfXfxhH-1665330113045)(https://www.runoob.com/wp-content/uploads/2014/08/20220725-filter-md-20201230.svg#crop=0&crop=0&crop=1&crop=1&height=377&id=NdtQX&originHeight=687&originWidth=1086&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=&width=596)]

步骤 1  创建一个类,在该类上应用标准。

Person.java
public class Person {

private String name;
private String gender;
private String maritalStatus;

public Person(String name,String gender,String maritalStatus){
this.name = name;
this.gender = gender;
this.maritalStatus = maritalStatus;
}

public String getName() {
return name;
}
public String getGender() {
return gender;
}
public String getMaritalStatus() {
return maritalStatus;
}
}


步骤 2 为标准(Criteria)创建一个接口。
Criteria.java
import java.util.List;
public interface Criteria {
public List<Person> meetCriteria(List<Person> persons);
}


步骤 3 创建实现了 Criteria 接口的实体类。
CriteriaMale.java
import java.util.ArrayList;
import java.util.List;
public class CriteriaMale implements Criteria {
@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> malePersons = new ArrayList<Person>();
for (Person person : persons) {
if(person.getGender().equalsIgnoreCase("MALE")){
malePersons.add(person);
}
}
return malePersons;
}
}

CriteriaFemale.java
import java.util.ArrayList;
import java.util.List;
public class CriteriaFemale implements Criteria {
@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> femalePersons = new ArrayList<Person>();
for (Person person : persons) {
if(person.getGender().equalsIgnoreCase("FEMALE")){
femalePersons.add(person);
}
}
return femalePersons;
}
}

CriteriaSingle.java
import java.util.ArrayList;
import java.util.List;

public class CriteriaSingle implements Criteria {
@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> singlePersons = new ArrayList<Person>();
for (Person person : persons) {
if(person.getMaritalStatus().equalsIgnoreCase("SINGLE")){
singlePersons.add(person);
}
}
return singlePersons;
}
}


AndCriteria.java
import java.util.List;

public class AndCriteria implements Criteria {
private Criteria criteria;
private Criteria otherCriteria;

public AndCriteria(Criteria criteria, Criteria otherCriteria) {
this.criteria = criteria;
this.otherCriteria = otherCriteria;
}

@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> firstCriteriaPersons = criteria.meetCriteria(persons);
return otherCriteria.meetCriteria(firstCriteriaPersons);
}
}

OrCriteria.java
import java.util.List;

public class OrCriteria implements Criteria {
private Criteria criteria;
private Criteria otherCriteria;

public OrCriteria(Criteria criteria, Criteria otherCriteria) {
this.criteria = criteria;
this.otherCriteria = otherCriteria;
}

@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> firstCriteriaItems = criteria.meetCriteria(persons);
List<Person> otherCriteriaItems = otherCriteria.meetCriteria(persons);

for (Person person : otherCriteriaItems) {
if(!firstCriteriaItems.contains(person)){
firstCriteriaItems.add(person);
}
}
return firstCriteriaItems;
}
}

步骤4 使用不同的标准(Criteria)和它们的结合来过滤 Person 对象的列表。
CriteriaPatternDemo.java
import java.util.ArrayList;
import java.util.List;

public class CriteriaPatternDemo {
public static void main(String[] args) {
List<Person> persons = new ArrayList<Person>();

persons.add(new Person("Robert","Male", "Single"));
persons.add(new Person("John","Male", "Married"));
persons.add(new Person("Laura","Female", "Married"));
persons.add(new Person("Diana","Female", "Single"));
persons.add(new Person("Mike","Male", "Single"));
persons.add(new Person("Bobby","Male", "Single"));

Criteria male = new CriteriaMale();
Criteria female = new CriteriaFemale();
Criteria single = new CriteriaSingle();
Criteria singleMale = new AndCriteria(single, male);
Criteria singleOrFemale = new OrCriteria(single, female);

System.out.println("Males: ");
printPersons(male.meetCriteria(persons));

System.out.println("\nFemales: ");
printPersons(female.meetCriteria(persons));

System.out.println("\nSingle Males: ");
printPersons(singleMale.meetCriteria(persons));

System.out.println("\nSingle Or Females: ");
printPersons(singleOrFemale.meetCriteria(persons));
}

public static void printPersons(List<Person> persons){
for (Person person : persons) {
System.out.println("Person : [ Name : " + person.getName()
+", Gender : " + person.getGender()
+", Marital Status : " + person.getMaritalStatus()
+" ]");
}
}
}

步骤 5 执行程序,输出结果:

Males:
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : John, Gender : Male, Marital Status : Married ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]

Females:
Person : [ Name : Laura, Gender : Female, Marital Status : Married ]
Person : [ Name : Diana, Gender : Female, Marital Status : Single ]

Single Males:
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]

Single Or Females:
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : Diana, Gender : Female, Marital Status : Single ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]
Person : [ Name : Laura, Gender : Female, Marital Status : Married ]

组合模式

  • 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。
  • 意图:将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
  • 开闭原则。 无需更改现有代码, 你就可以在应用中添加新元素, 使其成为对象树的一部分。
  • 主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
  • 如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。
  • 关键代码:树枝内部组合该接口,并且含有内部属性 List,里面放 Component。
  • 优点: 1、高层模块调用简单。 2、节点自由增加。
  • 缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。

实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MFJxHN0g-1665330113046)(https://www.runoob.com/wp-content/uploads/2014/08/20210817-composite-composite.svg#crop=0&crop=0&crop=1&crop=1&height=450&id=TT3PI&originHeight=506&originWidth=487&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=&width=433)]

步骤 1 创建 Employee 类,该类带有 Employee 对象的列表。
Employee.java
import java.util.ArrayList;
import java.util.List;

public class Employee {
private String name;
private String dept;
private int salary;
private List<Employee> subordinates;

//构造函数
public Employee(String name,String dept, int sal) {
this.name = name;
this.dept = dept;
this.salary = sal;
subordinates = new ArrayList<Employee>();
}

public void add(Employee e) {
subordinates.add(e);
}

public void remove(Employee e) {
subordinates.remove(e);
}

public List<Employee> getSubordinates(){
return subordinates;
}

public String toString(){
return ("Employee :[ Name : "+ name
+", dept : "+ dept + ", salary :"
+ salary+" ]");
}
}


步骤 2 使用 Employee 类来创建和打印员工的层次结构。

CompositePatternDemo.java
public class CompositePatternDemo {
public static void main(String[] args) {
Employee CEO = new Employee("John","CEO", 30000);

Employee headSales = new Employee("Robert","Head Sales", 20000);

Employee headMarketing = new Employee("Michel","Head Marketing", 20000);

Employee clerk1 = new Employee("Laura","Marketing", 10000);
Employee clerk2 = new Employee("Bob","Marketing", 10000);

Employee salesExecutive1 = new Employee("Richard","Sales", 10000);
Employee salesExecutive2 = new Employee("Rob","Sales", 10000);

CEO.add(headSales);
CEO.add(headMarketing);

headSales.add(salesExecutive1);
headSales.add(salesExecutive2);

headMarketing.add(clerk1);
headMarketing.add(clerk2);

//打印该组织的所有员工
System.out.println(CEO);
for (Employee headEmployee : CEO.getSubordinates()) {
System.out.println(headEmployee);
for (Employee employee : headEmployee.getSubordinates()) {
System.out.println(employee);
}
}
}
}

步骤 3 执行程序,输出结果为:
Employee :[ Name : John, dept : CEO, salary :30000 ]
Employee :[ Name : Robert, dept : Head Sales, salary :20000 ]
Employee :[ Name : Richard, dept : Sales, salary :10000 ]
Employee :[ Name : Rob, dept : Sales, salary :10000 ]
Employee :[ Name : Michel, dept : Head Marketing, salary :20000 ]
Employee :[ Name : Laura, dept : Marketing, salary :10000 ]
Employee :[ Name : Bob, dept : Marketing, salary :10000 ]

外观模式

  • 外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。它向现有的系统添加一个接口,来隐藏系统的复杂性。这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
  • 意图:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
  • 主要解决:降低访问复杂系统的内部子系统时的复杂度,简化客户端之间的接口。
  • 何时使用: 1、客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。 2、定义系统的入口。 如果你需要一个指向复杂子系统的直接接口, 且该接口的功能有限, 则可以使用外观模式。 如果需要将子系统组织为多层结构, 可以使用外观。
  • 如何解决:客户端不与系统耦合,外观类与系统耦合。
  • 关键代码:在客户端和复杂系统之间再加一层,这一层将调用顺序、依赖关系等处理好。
  • 优点: 1、减少系统相互依赖。 2、提高灵活性。 3、提高了安全性。 你可以让自己的代码独立于复杂子系统。
  • 缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。 外观可能成为与程序中所有类都耦合的上帝对象。
  • 使用场景: 1、为复杂的模块或子系统提供外界访问的模块。 2、子系统相对独立。 3、预防低水平人员带来的风险。
  • 注意事项:在层次化结构中,可以使用外观模式定义系统中每一层的入口。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d2M6m2co-1665330113046)(https://www.runoob.com/wp-content/uploads/2014/08/20201015-facade.svg#crop=0&crop=0&crop=1&crop=1&height=382&id=Fx9sC&originHeight=595&originWidth=845&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=&width=542)]

实现

步骤 1 创建一个接口。
Shape.java
public interface Shape {
void draw();
}

步骤 2 创建实现接口的实体类。
Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Rectangle::draw()");
}
}

Square.java
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Square::draw()");
}
}

Circle.java
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Circle::draw()");
}
}

步骤 3 创建一个外观类。
ShapeMaker.java
public class ShapeMaker {
private Shape circle;
private Shape rectangle;
private Shape square;

public ShapeMaker() {
circle = new Circle();
rectangle = new Rectangle();
square = new Square();
}

public void drawCircle(){
circle.draw();
}
public void drawRectangle(){
rectangle.draw();
}
public void drawSquare(){
square.draw();
}
}

步骤 4 使用该外观类画出各种类型的形状。

FacadePatternDemo.java
public class FacadePatternDemo {
public static void main(String[] args) {

ShapeMaker shapeMaker = new ShapeMaker();
shapeMaker.drawCircle();
shapeMaker.drawRectangle();
shapeMaker.drawSquare();
}
}

步骤 5 执行程序,输出结果:
Circle::draw()
Rectangle::draw()
Square::draw()

享元模式

  • 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
  • 意图:运用共享技术有效地支持大量细粒度的对象。
  • 主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
  • 何时使用: 1、系统中有大量对象。 2、这些对象消耗大量内存。 3、这些对象的状态大部分可以外部化。 4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。 5、系统不依赖于这些对象身份,这些对象是不可分辨的。 仅在程序必须支持大量对象且没有足够的内存容量时使用享元模式。
  • 如何解决:用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。
  • 关键代码:用 HashMap 存储这些对象。
  • 优点:大大减少对象的创建,降低系统的内存,使效率提高。 如果程序中有很多相似对象, 那么你将可以节省大量内存。
  • 缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。你可能需要牺牲执行速度来换取内存, 因为他人每次调用享元方法时都需要重新计算部分情景数据。代码会变得更加复杂。 团队中的新成员总是会问: “为什么要像这样拆分一个实体的状态?”。
  • 使用场景: 1、系统有大量相似对象。 2、需要缓冲池的场景。
  • 注意事项: 1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。 2、这些类必须有一个工厂对象加以控制。

实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x76nDLTr-1665330113046)(https://www.runoob.com/wp-content/uploads/2014/08/20201015-fiyweight.svg#crop=0&crop=0&crop=1&crop=1&height=428&id=jvJ7m&originHeight=517&originWidth=594&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=&width=492)]

步骤 1 创建一个接口。
Shape.java
public interface Shape {
void draw();
}

步骤 2 创建实现接口的实体类。
Circle.java
public class Circle implements Shape {
private String color;
private int x;
private int y;
private int radius;

public Circle(String color){
this.color = color;
}

public void setX(int x) {
this.x = x;
}

public void setY(int y) {
this.y = y;
}

public void setRadius(int radius) {
this.radius = radius;
}

@Override
public void draw() {
System.out.println("Circle: Draw() [Color : " + color
+", x : " + x +", y :" + y +", radius :" + radius);
}
}


步骤 3 创建一个工厂,生成基于给定信息的实体类的对象。

ShapeFactory.java
import java.util.HashMap;

public class ShapeFactory {
private static final HashMap<String, Shape> circleMap = new HashMap<>();

public static Shape getCircle(String color) {
Circle circle = (Circle)circleMap.get(color);

if(circle == null) {
circle = new Circle(color);
circleMap.put(color, circle);
System.out.println("Creating circle of color : " + color);
}
return circle;
}
}

步骤 4 使用该工厂,通过传递颜色信息来获取实体类的对象。

FlyweightPatternDemo.java
public class FlyweightPatternDemo {
private static final String colors[] =
{ "Red", "Green", "Blue", "White", "Black" };
public static void main(String[] args) {

for(int i=0; i < 20; ++i) {
Circle circle =
(Circle)ShapeFactory.getCircle(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw();
}
}
private static String getRandomColor() {
return colors[(int)(Math.random()*colors.length)];
}
private static int getRandomX() {
return (int)(Math.random()*100 );
}
private static int getRandomY() {
return (int)(Math.random()*100);
}
}
步骤 5
执行程序,输出结果:

Creating circle of color : Black
Circle: Draw() [Color : Black, x : 36, y :71, radius :100
Creating circle of color : Green
Circle: Draw() [Color : Green, x : 27, y :27, radius :100
Creating circle of color : White
Circle: Draw() [Color : White, x : 64, y :10, radius :100
Creating circle of color : Red
Circle: Draw() [Color : Red, x : 15, y :44, radius :100
Circle: Draw() [Color : Green, x : 19, y :10, radius :100
Circle: Draw() [Color : Green, x : 94, y :32, radius :100
Circle: Draw() [Color : White, x : 69, y :98, radius :100
Creating circle of color : Blue
Circle: Draw() [Color : Blue, x : 13, y :4, radius :100
Circle: Draw() [Color : Green, x : 21, y :21, radius :100
Circle: Draw() [Color : Blue, x : 55, y :86, radius :100

装饰模式

  • 装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。如果你希望在无需修改代码的情况下即可使用对象, 且希望在运行时为对象新增额外的行为, 可以使用装饰模式。如果用继承来扩展对象行为的方案难以实现或者根本不可行, 你可以使用该模式。
  • 优点:
  • 你无需创建新子类即可扩展对象的行为。
  • 你可以在运行时添加或删除对象的功能。
  • 你可以用多个装饰封装对象来组合几种行为。
  • 单一职责原则。 你可以将实现了许多不同行为的一个大类拆分为多个较小的类。
  • 缺点:
  • 在封装器栈中删除特定封装器比较困难。
  • 实现行为不受装饰栈顺序影响的装饰比较困难。
  • 各层的初始化配置代码看上去可能会很糟糕。

实现

设计模式之结构型_设计模式_04


![image.png](https://img-blog.csdnimg.cn/img_convert/cdacfcdbae7a656501b802ffbf2ffc69.png#clientId=u5d5a8384-892b-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown error&from=paste&height=275&id=u219b810b&name=image.png&originHeight=550&originWidth=854&originalType=binary&ratio=1&rotatinotallow=0&showTitle=false&size=62951&status=error&style=none&taskId=u7605ada9-a073-4543-bec0-e2a0cf096e9&title=&width=427)

步骤 1
创建一个接口:
Shape.java
public interface Shape {
void draw();
}

步骤 2
创建实现接口的实体类。
Rectangle.java
public class Rectangle implements Shape {

@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
Circle.java
public class Circle implements Shape {

@Override
public void draw() {
System.out.println("Shape: Circle");
}
}

步骤 3
创建实现了 Shape 接口的抽象装饰类。
ShapeDecorator.java
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;

public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}

public void draw(){
decoratedShape.draw();
}
}

步骤 4
创建扩展了 ShapeDecorator 类的实体装饰类。
RedShapeDecorator.java
public class RedShapeDecorator extends ShapeDecorator {

public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}

@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}

private void setRedBorder(Shape decoratedShape){
System.out.println("Border Color: Red");
}
}
步骤 5
使用 RedShapeDecorator 来装饰 Shape 对象。

DecoratorPatternDemo.java
public class DecoratorPatternDemo {
public static void main(String[] args) {

Shape circle = new Circle();
ShapeDecorator redCircle = new RedShapeDecorator(new Circle());
ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());
//Shape redCircle = new RedShapeDecorator(new Circle());
//Shape redRectangle = new RedShapeDecorator(new Rectangle());
System.out.println("Circle with normal border");
circle.draw();

System.out.println("\nCircle of red border");
redCircle.draw();

System.out.println("\nRectangle of red border");
redRectangle.draw();
}
}
步骤 6
执行程序,输出结果:

Circle with normal border
Shape: Circle

Circle of red border
Shape: Circle
Border Color: Red

Rectangle of red border
Shape: Rectangle
Border Color: Red

代理模式

  • 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
  • 意图:为其他对象提供一种代理以控制对这个对象的访问。
  • 开闭原则。 你可以在不对服务或客户端做出修改的情况下创建新代理。
  • 主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
  • 如何解决:增加中间层。
  • 关键代码:实现与被代理类组合。
  • 优点: 1、职责清晰。 2、高扩展性。 3、智能化。
  • 缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
  • 代码可能会变得复杂, 因为需要新建许多类。
  • 服务响应可能会延迟。
  • 注意事项:
  • 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
  • 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。

实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ejC0u8At-1665330113047)(https://www.runoob.com/wp-content/uploads/2014/08/20211025-proxy.svg#crop=0&crop=0&crop=1&crop=1&height=273&id=O0Lx0&originHeight=365&originWidth=742&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=&width=554)]

步骤 1 创建一个接口。
Image.java
public interface Image {
void display();
}

步骤 2 创建实现接口的实体类。
RealImage.java
public class RealImage implements Image {
private String fileName;

public RealImage(String fileName){
this.fileName = fileName;
loadFromDisk(fileName);
}

@Override
public void display() {
System.out.println("Displaying " + fileName);
}

private void loadFromDisk(String fileName){
System.out.println("Loading " + fileName);
}
}


ProxyImage.java
public class ProxyImage implements Image{

private RealImage realImage;
private String fileName;

public ProxyImage(String fileName){
this.fileName = fileName;
}

@Override
public void display() {
if(realImage == null){
realImage = new RealImage(fileName);
}
realImage.display();
}
}

步骤 3 当被请求时,使用 ProxyImage 来获取 RealImage 类的对象。

ProxyPatternDemo.java
public class ProxyPatternDemo {

public static void main(String[] args) {
Image image = new ProxyImage("test_10mb.jpg");

// 图像将从磁盘加载
image.display();
System.out.println("");
// 图像不需要从磁盘加载
image.display();
}
}

步骤 4 执行程序,输出结果:

Loading test_10mb.jpg
Displaying test_10mb.jpg

Displaying test_10mb.jpg

参考文档

  • ​​http://c.biancheng.net/view/1317.html​​
  • ​​https://www.runoob.com/design-pattern/design-pattern-intro.html​​


举报

相关推荐

0 条评论